merge m-c to oak
authorRobert Strong <robert.bugzilla@gmail.com>
Tue, 23 Sep 2014 16:59:59 -0700
changeset 491278 1faa9b2bb5ff19386f7852893ba57cbfb7f1b1f3
parent 491277 6e4b7c3b7ba59edcbe6e01e6f822e4f0e9e34e45 (current diff)
parent 206785 afc933adf7234e4374e18e3c116d89fa0ce62df8 (diff)
child 491279 2f889454bea600a375721fe2f19da1f9f603961b
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
milestone35.0a1
merge m-c to oak
testing/xpcshell/runxpcshelltests.py
toolkit/xre/nsAppRunner.cpp
--- a/accessible/atk/ApplicationAccessibleWrap.cpp
+++ b/accessible/atk/ApplicationAccessibleWrap.cpp
@@ -80,17 +80,17 @@ toplevel_event_watcher(GSignalInvocation
 
 ENameValueFlag
 ApplicationAccessibleWrap::Name(nsString& aName)
 {
   // ATK doesn't provide a way to obtain an application name (for example,
   // Firefox or Thunderbird) like IA2 does. Thus let's return an application
   // name as accessible name that was used to get a branding name (for example,
   // Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
-  GetAppName(aName);
+  AppName(aName);
   return eNameOK;
 }
 
 NS_IMETHODIMP
 ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible)
 {
     *aOutAccessible = nullptr;
 
--- a/accessible/atk/nsMaiInterfaceDocument.cpp
+++ b/accessible/atk/nsMaiInterfaceDocument.cpp
@@ -74,29 +74,26 @@ getDocumentAttributesCB(AtkDocument *aDo
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
   if (!accWrap || !accWrap->IsDoc())
     return nullptr;
 
   // according to atkobject.h, AtkAttributeSet is a GSList
   GSList* attributes = nullptr;
   DocAccessible* document = accWrap->AsDoc();
   nsAutoString aURL;
-  nsresult rv = document->GetURL(aURL);
-  if (NS_SUCCEEDED(rv))
-    attributes = prependToList(attributes, kDocUrlName, aURL);
+  document->URL(aURL);
+  attributes = prependToList(attributes, kDocUrlName, aURL);
 
   nsAutoString aW3CDocType;
-  rv = document->GetDocType(aW3CDocType);
-  if (NS_SUCCEEDED(rv))
-    attributes = prependToList(attributes, kDocTypeName, aW3CDocType);
+  document->GetDocType(aW3CDocType);
+  attributes = prependToList(attributes, kDocTypeName, aW3CDocType);
 
   nsAutoString aMimeType;
-  rv = document->GetMimeType(aMimeType);
-  if (NS_SUCCEEDED(rv))
-    attributes = prependToList(attributes, kMimeTypeName, aMimeType);
+  document->MimeType(aMimeType);
+  attributes = prependToList(attributes, kMimeTypeName, aMimeType);
 
   return attributes;
 }
 
 const gchar *
 getDocumentAttributeValueCB(AtkDocument *aDocument,
                             const gchar *aAttrName)
 {
@@ -105,18 +102,18 @@ getDocumentAttributeValueCB(AtkDocument 
     return nullptr;
 
   DocAccessible* document = accWrap->AsDoc();
   nsresult rv;
   nsAutoString attrValue;
   if (!strcasecmp(aAttrName, kDocTypeName))
     rv = document->GetDocType(attrValue);
   else if (!strcasecmp(aAttrName, kDocUrlName))
-    rv = document->GetURL(attrValue);
+    document->URL(attrValue);
   else if (!strcasecmp(aAttrName, kMimeTypeName))
-    rv = document->GetMimeType(attrValue);
+    document->MimeType(attrValue);
   else
     return nullptr;
 
   NS_ENSURE_SUCCESS(rv, nullptr);
   return attrValue.IsEmpty() ? nullptr : AccessibleWrap::ReturnString(attrValue);
 }
 }
--- a/accessible/generic/ApplicationAccessible.cpp
+++ b/accessible/generic/ApplicationAccessible.cpp
@@ -124,74 +124,16 @@ ApplicationAccessible::RelationByType(Re
 
 nsIntRect
 ApplicationAccessible::Bounds() const
 {
   return nsIntRect();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibleApplication
-
-NS_IMETHODIMP
-ApplicationAccessible::GetAppName(nsAString& aName)
-{
-  aName.Truncate();
-
-  if (!mAppInfo)
-    return NS_ERROR_FAILURE;
-
-  nsAutoCString cname;
-  nsresult rv = mAppInfo->GetName(cname);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  AppendUTF8toUTF16(cname, aName);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-ApplicationAccessible::GetAppVersion(nsAString& aVersion)
-{
-  aVersion.Truncate();
-
-  if (!mAppInfo)
-    return NS_ERROR_FAILURE;
-
-  nsAutoCString cversion;
-  nsresult rv = mAppInfo->GetVersion(cversion);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  AppendUTF8toUTF16(cversion, aVersion);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-ApplicationAccessible::GetPlatformName(nsAString& aName)
-{
-  aName.AssignLiteral("Gecko");
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-ApplicationAccessible::GetPlatformVersion(nsAString& aVersion)
-{
-  aVersion.Truncate();
-
-  if (!mAppInfo)
-    return NS_ERROR_FAILURE;
-
-  nsAutoCString cversion;
-  nsresult rv = mAppInfo->GetPlatformVersion(cversion);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  AppendUTF8toUTF16(cversion, aVersion);
-  return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // Accessible public methods
 
 void
 ApplicationAccessible::Shutdown()
 {
   mAppInfo = nullptr;
 }
 
--- a/accessible/generic/ApplicationAccessible.h
+++ b/accessible/generic/ApplicationAccessible.h
@@ -4,17 +4,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_ApplicationAccessible_h__
 #define mozilla_a11y_ApplicationAccessible_h__
 
 #include "AccessibleWrap.h"
-#include "nsIAccessibleApplication.h"
+#include "xpcAccessibleApplication.h"
 
 #include "nsIMutableArray.h"
 #include "nsIXULAppInfo.h"
 
 namespace mozilla {
 namespace a11y {
 
 /**
@@ -23,28 +23,25 @@ namespace a11y {
  * And this one should be created when Mozilla Startup (if accessibility
  * feature has been enabled) and destroyed when Mozilla Shutdown.
  *
  * All the accessibility objects for toplevel windows are direct children of
  * the ApplicationAccessible instance.
  */
 
 class ApplicationAccessible : public AccessibleWrap,
-                              public nsIAccessibleApplication
+                              public xpcAccessibleApplication
 {
 public:
 
   ApplicationAccessible();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIAccessibleApplication
-  NS_DECL_NSIACCESSIBLEAPPLICATION
-
   // Accessible
   virtual void Shutdown();
   virtual nsIntRect Bounds() const MOZ_OVERRIDE;
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual GroupPos GroupPosition();
   virtual ENameValueFlag Name(nsString& aName);
   virtual void ApplyARIAState(uint64_t* aState) const;
   virtual void Description(nsString& aDescription);
@@ -58,16 +55,43 @@ public:
                                    EWhichChildAtPoint aWhichChild);
   virtual Accessible* FocusedChild();
 
   virtual void InvalidateChildren();
 
   // ActionAccessible
   virtual KeyBinding AccessKey() const;
 
+  // ApplicationAccessible
+  void AppName(nsAString& aName) const
+  {
+    nsAutoCString cname;
+    mAppInfo->GetName(cname);
+    AppendUTF8toUTF16(cname, aName);
+  }
+
+  void AppVersion(nsAString& aVersion) const
+  {
+    nsAutoCString cversion;
+    mAppInfo->GetVersion(cversion);
+    AppendUTF8toUTF16(cversion, aVersion);
+  }
+
+  void PlatformName(nsAString& aName) const
+  {
+    aName.AssignLiteral("Gecko");
+  }
+
+  void PlatformVersion(nsAString& aVersion) const
+  {
+    nsAutoCString cversion;
+    mAppInfo->GetPlatformVersion(cversion);
+    AppendUTF8toUTF16(cversion, aVersion);
+  }
+
 protected:
   virtual ~ApplicationAccessible() {}
 
   // Accessible
   virtual void CacheChildren();
   virtual Accessible* GetSiblingAtOffset(int32_t aOffset,
                                          nsresult *aError = nullptr) const;
 
--- a/accessible/generic/DocAccessible-inl.h
+++ b/accessible/generic/DocAccessible-inl.h
@@ -4,27 +4,38 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_DocAccessible_inl_h_
 #define mozilla_a11y_DocAccessible_inl_h_
 
 #include "DocAccessible.h"
 #include "nsAccessibilityService.h"
+#include "nsAccessiblePivot.h"
 #include "NotificationController.h"
 #include "States.h"
 #include "nsIScrollableFrame.h"
 
 #ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 namespace mozilla {
 namespace a11y {
 
+inline nsIAccessiblePivot*
+DocAccessible::VirtualCursor()
+{
+  if (!mVirtualCursor) {
+    mVirtualCursor = new nsAccessiblePivot(this);
+    mVirtualCursor->AddObserver(this);
+  }
+  return mVirtualCursor;
+}
+
 inline void
 DocAccessible::FireDelayedEvent(AccEvent* aEvent)
 {
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocLoad))
     logging::DocLoadEventFired(aEvent);
 #endif
 
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -35,17 +35,16 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
-#include "nsNameSpaceManager.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/Element.h"
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
@@ -71,17 +70,17 @@ static nsIAtom** kRelationAttrs[] =
 static const uint32_t kRelationAttrsLen = ArrayLength(kRelationAttrs);
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
 DocAccessible::
   DocAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
                   nsIPresShell* aPresShell) :
-  HyperTextAccessibleWrap(aRootContent, this),
+  HyperTextAccessibleWrap(aRootContent, this), xpcAccessibleDocument(),
   // XXX aaronl should we use an algorithm for the initial cache size?
   mAccessibleCache(kDefaultCacheLength),
   mNodeToAccessibleMap(kDefaultCacheLength),
   mDocumentNode(aDocument),
   mScrollPositionChangedTicks(0),
   mLoadState(eTreeConstructionPending), mDocFlags(0), mLoadEventType(0),
   mVirtualCursor(nullptr),
   mPresShell(aPresShell)
@@ -170,22 +169,22 @@ DocAccessible::Name(nsString& aName)
   if (mParent) {
     mParent->Name(aName); // Allow owning iframe to override the name
   }
   if (aName.IsEmpty()) {
     // Allow name via aria-labelledby or title attribute
     Accessible::Name(aName);
   }
   if (aName.IsEmpty()) {
-    GetTitle(aName);   // Try title element
+    Title(aName); // Try title element
   }
   if (aName.IsEmpty()) {   // Last resort: use URL
-    GetURL(aName);
+    URL(aName);
   }
- 
+
   return eNameOK;
 }
 
 // Accessible public method
 role
 DocAccessible::NativeRole()
 {
   nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(mDocumentNode);
@@ -318,184 +317,16 @@ DocAccessible::TakeFocus()
 {
   // Focus the document.
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   nsCOMPtr<nsIDOMElement> newFocus;
   fm->MoveFocus(mDocumentNode->GetWindow(), nullptr,
                 nsFocusManager::MOVEFOCUS_ROOT, 0, getter_AddRefs(newFocus));
 }
 
-
-////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibleDocument
-
-NS_IMETHODIMP
-DocAccessible::GetURL(nsAString& aURL)
-{
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  nsCOMPtr<nsISupports> container = mDocumentNode->GetContainer();
-  nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
-  nsAutoCString theURL;
-  if (webNav) {
-    nsCOMPtr<nsIURI> pURI;
-    webNav->GetCurrentURI(getter_AddRefs(pURI));
-    if (pURI)
-      pURI->GetSpec(theURL);
-  }
-  CopyUTF8toUTF16(theURL, aURL);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetTitle(nsAString& aTitle)
-{
-  if (!mDocumentNode) {
-    return NS_ERROR_FAILURE;
-  }
-  nsString title;
-  mDocumentNode->GetTitle(title);
-  aTitle = title;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetMimeType(nsAString& aMimeType)
-{
-  if (!mDocumentNode) {
-    return NS_ERROR_FAILURE;
-  }
-  return mDocumentNode->GetContentType(aMimeType);
-}
-
-NS_IMETHODIMP
-DocAccessible::GetDocType(nsAString& aDocType)
-{
-#ifdef MOZ_XUL
-  nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocumentNode));
-  if (xulDoc) {
-    aDocType.AssignLiteral("window"); // doctype not implemented for XUL at time of writing - causes assertion
-    return NS_OK;
-  } else
-#endif
-  if (mDocumentNode) {
-    dom::DocumentType* docType = mDocumentNode->GetDoctype();
-    if (docType) {
-      return docType->GetPublicId(aDocType);
-    }
-  }
-
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetNameSpaceURIForID(int16_t aNameSpaceID, nsAString& aNameSpaceURI)
-{
-  if (mDocumentNode) {
-    nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
-    if (nameSpaceManager)
-      return nameSpaceManager->GetNameSpaceURI(aNameSpaceID, aNameSpaceURI);
-  }
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetWindowHandle(void** aWindow)
-{
-  NS_ENSURE_ARG_POINTER(aWindow);
-  *aWindow = GetNativeWindow();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetWindow(nsIDOMWindow** aDOMWin)
-{
-  *aDOMWin = nullptr;
-  if (!mDocumentNode) {
-    return NS_ERROR_FAILURE;  // Accessible is Shutdown()
-  }
-  *aDOMWin = mDocumentNode->GetWindow();
-
-  if (!*aDOMWin)
-    return NS_ERROR_FAILURE;  // No DOM Window
-
-  NS_ADDREF(*aDOMWin);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetDOMDocument(nsIDOMDocument** aDOMDocument)
-{
-  NS_ENSURE_ARG_POINTER(aDOMDocument);
-  *aDOMDocument = nullptr;
-
-  if (mDocumentNode)
-    CallQueryInterface(mDocumentNode, aDOMDocument);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetParentDocument(nsIAccessibleDocument** aDocument)
-{
-  NS_ENSURE_ARG_POINTER(aDocument);
-  *aDocument = nullptr;
-
-  if (!IsDefunct())
-    NS_IF_ADDREF(*aDocument = ParentDocument());
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetChildDocumentCount(uint32_t* aCount)
-{
-  NS_ENSURE_ARG_POINTER(aCount);
-  *aCount = 0;
-
-  if (!IsDefunct())
-    *aCount = ChildDocumentCount();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetChildDocumentAt(uint32_t aIndex,
-                                  nsIAccessibleDocument** aDocument)
-{
-  NS_ENSURE_ARG_POINTER(aDocument);
-  *aDocument = nullptr;
-
-  if (IsDefunct())
-    return NS_OK;
-
-  NS_IF_ADDREF(*aDocument = GetChildDocumentAt(aIndex));
-  return *aDocument ? NS_OK : NS_ERROR_INVALID_ARG;
-}
-
-NS_IMETHODIMP
-DocAccessible::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor)
-{
-  NS_ENSURE_ARG_POINTER(aVirtualCursor);
-  *aVirtualCursor = nullptr;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  if (!mVirtualCursor) {
-    mVirtualCursor = new nsAccessiblePivot(this);
-    mVirtualCursor->AddObserver(this);
-  }
-
-  NS_ADDREF(*aVirtualCursor = mVirtualCursor);
-  return NS_OK;
-}
-
 // HyperTextAccessible method
 already_AddRefed<nsIEditor>
 DocAccessible::GetEditor() const
 {
   // Check if document is editable (designMode="on" case). Otherwise check if
   // the html:body (for HTML document case) or document element is editable.
   if (!mDocumentNode->HasFlag(NODE_IS_EDITABLE) &&
       (!mContent || !mContent->HasFlag(NODE_IS_EDITABLE)))
@@ -515,16 +346,47 @@ DocAccessible::GetEditor() const
   editor->GetIsDocumentEditable(&isEditable);
   if (isEditable)
     return editor.forget();
 
   return nullptr;
 }
 
 // DocAccessible public method
+
+void
+DocAccessible::URL(nsAString& aURL) const
+{
+  nsCOMPtr<nsISupports> container = mDocumentNode->GetContainer();
+  nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
+  nsAutoCString theURL;
+  if (webNav) {
+    nsCOMPtr<nsIURI> pURI;
+    webNav->GetCurrentURI(getter_AddRefs(pURI));
+    if (pURI)
+      pURI->GetSpec(theURL);
+  }
+  CopyUTF8toUTF16(theURL, aURL);
+}
+
+void
+DocAccessible::DocType(nsAString& aType) const
+{
+#ifdef MOZ_XUL
+  nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocumentNode));
+  if (xulDoc) {
+    aType.AssignLiteral("window"); // doctype not implemented for XUL at time of writing - causes assertion
+    return;
+  }
+#endif
+  dom::DocumentType* docType = mDocumentNode->GetDoctype();
+  if (docType)
+    docType->GetPublicId(aType);
+}
+
 Accessible*
 DocAccessible::GetAccessible(nsINode* aNode) const
 {
   Accessible* accessible = mNodeToAccessibleMap.Get(aNode);
 
   // No accessible in the cache, check if the given ID is unique ID of this
   // document accessible.
   if (!accessible) {
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_DocAccessible_h__
 #define mozilla_a11y_DocAccessible_h__
 
-#include "nsIAccessibleDocument.h"
+#include "xpcAccessibleDocument.h"
 #include "nsIAccessiblePivot.h"
 
 #include "AccEvent.h"
 #include "HyperTextAccessibleWrap.h"
 
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsIDocument.h"
@@ -33,28 +33,26 @@ namespace a11y {
 
 class DocManager;
 class NotificationController;
 class RelatedAccIterator;
 template<class Class, class Arg>
 class TNotification;
 
 class DocAccessible : public HyperTextAccessibleWrap,
-                      public nsIAccessibleDocument,
+                      public xpcAccessibleDocument,
                       public nsIDocumentObserver,
                       public nsIObserver,
                       public nsIScrollPositionListener,
                       public nsSupportsWeakReference,
                       public nsIAccessiblePivotObserver
 {
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocAccessible, Accessible)
 
-  NS_DECL_NSIACCESSIBLEDOCUMENT
-
   NS_DECL_NSIOBSERVER
 
   NS_DECL_NSIACCESSIBLEPIVOTOBSERVER
 
 public:
 
   DocAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
                 nsIPresShell* aPresShell);
@@ -92,25 +90,50 @@ public:
   virtual nsRect RelativeBounds(nsIFrame** aRelativeFrame) const MOZ_OVERRIDE;
 
   // HyperTextAccessible
   virtual already_AddRefed<nsIEditor> GetEditor() const;
 
   // DocAccessible
 
   /**
+   * Return document URL.
+   */
+  void URL(nsAString& aURL) const;
+
+  /**
+   * Return DOM document title.
+   */
+  void Title(nsString& aTitle) const { mDocumentNode->GetTitle(aTitle); }
+
+  /**
+   * Return DOM document mime type.
+   */
+  void MimeType(nsAString& aType) const { mDocumentNode->GetContentType(aType); }
+
+  /**
+   * Return DOM document type.
+   */
+  void DocType(nsAString& aType) const;
+
+  /**
+   * Return virtual cursor associated with the document.
+   */
+  nsIAccessiblePivot* VirtualCursor();
+
+  /**
    * Return presentation shell for this document accessible.
    */
   nsIPresShell* PresShell() const { return mPresShell; }
 
   /**
    * Return the presentation shell's context.
    */
   nsPresContext* PresContext() const { return mPresShell->GetPresContext(); }
-    
+
   /**
    * Return true if associated DOM document was loaded and isn't unloading.
    */
   bool IsContentLoaded() const
   {
     // eDOMLoaded flag check is used for error pages as workaround to make this
     // method return correct result since error pages do not receive 'pageshow'
     // event and as consequence nsIDocument::IsShowing() returns false.
--- a/accessible/generic/ImageAccessible.cpp
+++ b/accessible/generic/ImageAccessible.cpp
@@ -141,43 +141,30 @@ ImageAccessible::DoAction(uint8_t aIndex
     return false;
 
   nsCOMPtr<nsIDOMWindow> tmp;
   return NS_SUCCEEDED(win->Open(spec, EmptyString(), EmptyString(),
                                 getter_AddRefs(tmp)));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibleImage
+// ImageAccessible
 
-NS_IMETHODIMP
-ImageAccessible::GetImagePosition(uint32_t aCoordType, int32_t* aX, int32_t* aY)
+nsIntPoint
+ImageAccessible::Position(uint32_t aCoordType)
 {
-  NS_ENSURE_ARG_POINTER(aX);
-  NS_ENSURE_ARG_POINTER(aY);
-
   nsIntRect rect = Bounds();
-  *aX = rect.x;
-  *aY = rect.y;
-  nsAccUtils::ConvertScreenCoordsTo(aX, aY, aCoordType, this);
-
-  return NS_OK;
+  nsAccUtils::ConvertScreenCoordsTo(&rect.x, &rect.y, aCoordType, this);
+  return rect.TopLeft();
 }
 
-NS_IMETHODIMP
-ImageAccessible::GetImageSize(int32_t* aWidth, int32_t* aHeight)
+nsIntSize
+ImageAccessible::Size()
 {
-  NS_ENSURE_ARG_POINTER(aWidth);
-  NS_ENSURE_ARG_POINTER(aHeight);
-
-  nsIntRect rect = Bounds();
-  *aWidth = rect.width;
-  *aHeight = rect.height;
-
-  return NS_OK;
+  return Bounds().Size();
 }
 
 // Accessible
 already_AddRefed<nsIPersistentProperties>
 ImageAccessible::NativeAttributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
     LinkableAccessible::NativeAttributes();
--- a/accessible/generic/ImageAccessible.h
+++ b/accessible/generic/ImageAccessible.h
@@ -2,50 +2,51 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_a11y_ImageAccessible_h__
 #define mozilla_a11y_ImageAccessible_h__
 
 #include "BaseAccessibles.h"
-#include "nsIAccessibleImage.h"
+#include "xpcAccessibleImage.h"
 
 class nsGenericHTMLElement;
 
 namespace mozilla {
 namespace a11y {
 
 /* Accessible for supporting images
  * supports:
  * - gets name, role
  * - support basic state
  */
 class ImageAccessible : public LinkableAccessible,
-                        public nsIAccessibleImage
+                        public xpcAccessibleImage
 {
 public:
   ImageAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIAccessibleImage
-  NS_DECL_NSIACCESSIBLEIMAGE
-
   // Accessible
   virtual a11y::role NativeRole() MOZ_OVERRIDE;
   virtual uint64_t NativeState() MOZ_OVERRIDE;
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
 
   // ActionAccessible
   virtual uint8_t ActionCount() MOZ_OVERRIDE;
   virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) MOZ_OVERRIDE;
   virtual bool DoAction(uint8_t aIndex) MOZ_OVERRIDE;
 
+  // ImageAccessible
+  nsIntPoint Position(uint32_t aCoordType);
+  nsIntSize Size();
+
 protected:
   virtual ~ImageAccessible();
 
   // Accessible
   virtual ENameValueFlag NativeName(nsString& aName) MOZ_OVERRIDE;
 
 private:
   /**
--- a/accessible/interfaces/nsIAccessibleDocument.idl
+++ b/accessible/interfaces/nsIAccessibleDocument.idl
@@ -1,33 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsIAccessible;
 interface nsIAccessiblePivot;
 interface nsIDOMDocument;
-interface nsIDOMNode;
 interface nsIDOMWindow;
 
 /**
  * An interface for in-process accessibility clients
  * that wish to retrieve information about a document.
  * When accessibility is turned on in Gecko,
  * there is an nsIAccessibleDocument for each document
  * whether it is XUL, HTML or whatever.
  * You can QueryInterface to nsIAccessibleDocument from the nsIAccessible for
- * the root node of a document. You can also get one from 
- * nsIAccessible::GetAccessibleDocument() or 
- * nsIAccessibleEvent::GetAccessibleDocument()
+ * the root node of a document or you can get one from
+ * nsIAccessible::GetDocument().
  */
-[scriptable, uuid(fe5b3886-2b6a-491a-80cd-a3e6342c451d)]
+[scriptable, uuid(c80f6600-3210-4893-8f71-fde381ca39c9)]
 interface nsIAccessibleDocument : nsISupports
 {
   /**
    * The URL of the document
    */
   readonly attribute AString URL;
 
   /**
@@ -51,27 +48,16 @@ interface nsIAccessibleDocument : nsISup
   readonly attribute nsIDOMDocument DOMDocument;
 
   /**
    * The nsIDOMWindow that the document resides in.
    */
   readonly attribute nsIDOMWindow window;
 
   /**
-   * The namespace for each ID that is handed back.
-   */
-  AString getNameSpaceURIForID(in short nameSpaceID);
-
-  /**
-   * The window handle for the OS window the document is being displayed in.
-   * For example, in Windows you can static cast it to an HWND.
-   */
-  [noscript] readonly attribute voidPtr windowHandle;
-
-  /**
    * Return the parent document accessible.
    */
   readonly attribute nsIAccessibleDocument parentDocument;
 
   /**
    * Return the count of child document accessibles.
    */
   readonly attribute unsigned long childDocumentCount;
@@ -79,10 +65,11 @@ interface nsIAccessibleDocument : nsISup
   /**
    * The virtual cursor pivot this document manages.
    */
   readonly attribute nsIAccessiblePivot virtualCursor;
 
   /**
    * Return the child document accessible at the given index.
    */
+  [binaryname(ScriptableGetChildDocumentAt)]
   nsIAccessibleDocument getChildDocumentAt(in unsigned long index);
 };
--- a/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
+++ b/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
@@ -74,20 +74,17 @@ ApplicationAccessibleWrap::get_appName(B
     return E_INVALIDARG;
 
   *aName = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString name;
-  nsresult rv = GetAppName(name);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
+  AppName(name);
   if (name.IsEmpty())
     return S_FALSE;
 
   *aName = ::SysAllocStringLen(name.get(), name.Length());
   return *aName ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
@@ -101,20 +98,17 @@ ApplicationAccessibleWrap::get_appVersio
     return E_INVALIDARG;
 
   *aVersion = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString version;
-  nsresult rv = GetAppVersion(version);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
+  AppVersion(version);
   if (version.IsEmpty())
     return S_FALSE;
 
   *aVersion = ::SysAllocStringLen(version.get(), version.Length());
   return *aVersion ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
@@ -126,20 +120,17 @@ ApplicationAccessibleWrap::get_toolkitNa
 
   if (!aName)
     return E_INVALIDARG;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString name;
-  nsresult rv = GetPlatformName(name);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
+  PlatformName(name);
   if (name.IsEmpty())
     return S_FALSE;
 
   *aName = ::SysAllocStringLen(name.get(), name.Length());
   return *aName ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
@@ -153,20 +144,17 @@ ApplicationAccessibleWrap::get_toolkitVe
     return E_INVALIDARG;
 
   *aVersion = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString version;
-  nsresult rv = GetPlatformVersion(version);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
+  PlatformVersion(version);
   if (version.IsEmpty())
     return S_FALSE;
 
   *aVersion = ::SysAllocStringLen(version.get(), version.Length());
   return *aVersion ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
--- a/accessible/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/windows/msaa/DocAccessibleWrap.cpp
@@ -56,26 +56,26 @@ DocAccessibleWrap::get_accValue(VARIANT 
   // For backwards-compat, we still support old MSAA hack to provide URL in accValue
   // Check for real value first
   HRESULT hr = AccessibleWrap::get_accValue(aVarChild, aValue);
   if (FAILED(hr) || *aValue || aVarChild.lVal != CHILDID_SELF)
     return hr;
 
   // If document is being used to create a widget, don't use the URL hack
   roles::Role role = Role();
-  if (role != roles::DOCUMENT && role != roles::APPLICATION && 
-      role != roles::DIALOG && role != roles::ALERT) 
+  if (role != roles::DOCUMENT && role != roles::APPLICATION &&
+      role != roles::DIALOG && role != roles::ALERT)
     return hr;
 
-  nsAutoString URL;
-  nsresult rv = GetURL(URL);
-  if (URL.IsEmpty())
+  nsAutoString url;
+  URL(url);
+  if (url.IsEmpty())
     return S_FALSE;
 
-  *aValue = ::SysAllocStringLen(URL.get(), URL.Length());
+  *aValue = ::SysAllocStringLen(url.get(), url.Length());
   return *aValue ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible
 
--- a/accessible/windows/sdn/sdnDocAccessible.cpp
+++ b/accessible/windows/sdn/sdnDocAccessible.cpp
@@ -3,16 +3,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "sdnDocAccessible.h"
 
 #include "ISimpleDOMDocument_i.c"
 
+#include "nsNameSpaceManager.h"
+
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // sdnDocAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 IMPL_IUNKNOWN_QUERY_HEAD(sdnDocAccessible)
@@ -27,20 +29,17 @@ sdnDocAccessible::get_URL(BSTR __RPC_FAR
   if (!aURL)
     return E_INVALIDARG;
   *aURL = nullptr;
 
   if (mAccessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString URL;
-  nsresult rv = mAccessible->GetURL(URL);
-  if (NS_FAILED(rv))
-    return E_FAIL;
-
+  mAccessible->URL(URL);
   if (URL.IsEmpty())
     return S_FALSE;
 
   *aURL = ::SysAllocStringLen(URL.get(), URL.Length());
   return *aURL ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
@@ -53,20 +52,17 @@ sdnDocAccessible::get_title(BSTR __RPC_F
   if (!aTitle)
     return E_INVALIDARG;
   *aTitle = nullptr;
 
   if (mAccessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString title;
-  nsresult rv = mAccessible->GetTitle(title);
-  if (NS_FAILED(rv))
-    return E_FAIL;
-
+  mAccessible->Title(title);
   *aTitle = ::SysAllocStringLen(title.get(), title.Length());
   return *aTitle ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 sdnDocAccessible::get_mimeType(BSTR __RPC_FAR* aMimeType)
@@ -132,19 +128,19 @@ sdnDocAccessible::get_nameSpaceURIForID(
 
   if (mAccessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (aNameSpaceID < 0)
     return E_INVALIDARG;  // -1 is kNameSpaceID_Unknown
 
   nsAutoString nameSpaceURI;
-  nsresult rv = mAccessible->GetNameSpaceURIForID(aNameSpaceID, nameSpaceURI);
-  if (NS_FAILED(rv))
-    return E_FAIL;
+  nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
+  if (nameSpaceManager)
+    nameSpaceManager->GetNameSpaceURI(aNameSpaceID, nameSpaceURI);
 
   if (nameSpaceURI.IsEmpty())
     return S_FALSE;
 
   *aNameSpaceURI = ::SysAllocStringLen(nameSpaceURI.get(),
                                        nameSpaceURI.Length());
 
   return *aNameSpaceURI ? S_OK : E_OUTOFMEMORY;
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -1,27 +1,31 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
     'xpcAccessible.h',
+    'xpcAccessibleDocument.h',
     'xpcAccessibleHyperLink.h',
     'xpcAccessibleHyperText.h',
     'xpcAccessibleSelectable.h',
     'xpcAccessibleValue.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsAccessibleRelation.cpp',
     'xpcAccessible.cpp',
+    'xpcAccessibleApplication.cpp',
+    'xpcAccessibleDocument.cpp',
     'xpcAccessibleHyperLink.cpp',
     'xpcAccessibleHyperText.cpp',
+    'xpcAccessibleImage.cpp',
     'xpcAccessibleSelectable.cpp',
     'xpcAccessibleTable.cpp',
     'xpcAccessibleTableCell.cpp',
     'xpcAccessibleTextRange.cpp',
     'xpcAccessibleValue.cpp',
 ]
 
 GENERATED_SOURCES += [
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleApplication.cpp
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xpcAccessibleApplication.h"
+
+#include "ApplicationAccessible.h"
+
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetAppName(nsAString& aName)
+{
+  aName.Truncate();
+
+  if (static_cast<ApplicationAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  static_cast<ApplicationAccessible*>(this)->AppName(aName);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetAppVersion(nsAString& aVersion)
+{
+  aVersion.Truncate();
+
+  if (static_cast<ApplicationAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  static_cast<ApplicationAccessible*>(this)->AppVersion(aVersion);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetPlatformName(nsAString& aName)
+{
+  aName.Truncate();
+
+  if (static_cast<ApplicationAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  static_cast<ApplicationAccessible*>(this)->PlatformName(aName);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetPlatformVersion(nsAString& aVersion)
+{
+  aVersion.Truncate();
+
+  if (static_cast<ApplicationAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  static_cast<ApplicationAccessible*>(this)->PlatformVersion(aVersion);
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleApplication.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_xpcAccessibleApplication_h_
+#define mozilla_a11y_xpcAccessibleApplication_h_
+
+#include "nsIAccessibleApplication.h"
+
+class nsIAccessible;
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleApplication : public nsIAccessibleApplication
+{
+public:
+  NS_IMETHOD GetAppName(nsAString& aName) MOZ_FINAL;
+  NS_IMETHOD GetAppVersion(nsAString& aVersion) MOZ_FINAL;
+  NS_IMETHOD GetPlatformName(nsAString& aName) MOZ_FINAL;
+  NS_IMETHOD GetPlatformVersion(nsAString& aVersion) MOZ_FINAL;
+
+private:
+  xpcAccessibleApplication() { }
+  friend class ApplicationAccessible;
+
+  xpcAccessibleApplication(const xpcAccessibleApplication&) MOZ_DELETE;
+  xpcAccessibleApplication& operator =(const xpcAccessibleApplication&) MOZ_DELETE;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleDocument.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xpcAccessibleDocument.h"
+
+#include "DocAccessible-inl.h"
+#include "nsIDOMDocument.h"
+
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetURL(nsAString& aURL)
+{
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  static_cast<DocAccessible*>(this)->URL(aURL);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetTitle(nsAString& aTitle)
+{
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsAutoString title;
+  static_cast<DocAccessible*>(this)->Title(title);
+  aTitle = title;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetMimeType(nsAString& aType)
+{
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  static_cast<DocAccessible*>(this)->MimeType(aType);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetDocType(nsAString& aType)
+{
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  static_cast<DocAccessible*>(this)->DocType(aType);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetDOMDocument(nsIDOMDocument** aDOMDocument)
+{
+  NS_ENSURE_ARG_POINTER(aDOMDocument);
+  *aDOMDocument = nullptr;
+
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  if (static_cast<DocAccessible*>(this)->DocumentNode())
+    CallQueryInterface(static_cast<DocAccessible*>(this)->DocumentNode(), aDOMDocument);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetWindow(nsIDOMWindow** aDOMWindow)
+{
+  NS_ENSURE_ARG_POINTER(aDOMWindow);
+  *aDOMWindow = nullptr;
+
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  NS_IF_ADDREF(*aDOMWindow = static_cast<DocAccessible*>(this)->DocumentNode()->GetWindow());
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetParentDocument(nsIAccessibleDocument** aDocument)
+{
+  NS_ENSURE_ARG_POINTER(aDocument);
+  *aDocument = nullptr;
+
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  NS_IF_ADDREF(*aDocument = static_cast<DocAccessible*>(this)->ParentDocument());
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetChildDocumentCount(uint32_t* aCount)
+{
+  NS_ENSURE_ARG_POINTER(aCount);
+  *aCount = 0;
+
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  *aCount = static_cast<DocAccessible*>(this)->ChildDocumentCount();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::ScriptableGetChildDocumentAt(uint32_t aIndex,
+                                                    nsIAccessibleDocument** aDocument)
+{
+  NS_ENSURE_ARG_POINTER(aDocument);
+  *aDocument = nullptr;
+
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  NS_IF_ADDREF(*aDocument = static_cast<DocAccessible*>(this)->GetChildDocumentAt(aIndex));
+  return *aDocument ? NS_OK : NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor)
+{
+  NS_ENSURE_ARG_POINTER(aVirtualCursor);
+  *aVirtualCursor = nullptr;
+
+  if (static_cast<DocAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  NS_ADDREF(*aVirtualCursor = static_cast<DocAccessible*>(this)->VirtualCursor());
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleDocument.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_xpcAccessibleDocument_h_
+#define mozilla_a11y_xpcAccessibleDocument_h_
+
+#include "nsIAccessibleDocument.h"
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleDocument : public nsIAccessibleDocument
+{
+public:
+  NS_IMETHOD GetURL(nsAString& aURL) MOZ_FINAL;
+  NS_IMETHOD GetTitle(nsAString& aTitle) MOZ_FINAL;
+  NS_IMETHOD GetMimeType(nsAString& aType) MOZ_FINAL;
+  NS_IMETHOD GetDocType(nsAString& aType) MOZ_FINAL;
+  NS_IMETHOD GetDOMDocument(nsIDOMDocument** aDOMDocument) MOZ_FINAL;
+  NS_IMETHOD GetWindow(nsIDOMWindow** aDOMWindow) MOZ_FINAL;
+  NS_IMETHOD GetParentDocument(nsIAccessibleDocument** aDocument) MOZ_FINAL;
+  NS_IMETHOD GetChildDocumentCount(uint32_t* aCount) MOZ_FINAL;
+  NS_IMETHOD ScriptableGetChildDocumentAt(uint32_t aIndex,
+                                          nsIAccessibleDocument** aDocument) MOZ_FINAL;
+  NS_IMETHOD GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) MOZ_FINAL;
+
+private:
+  friend class DocAccessible;
+
+  xpcAccessibleDocument() { }
+
+  xpcAccessibleDocument(const xpcAccessibleDocument&) MOZ_DELETE;
+  xpcAccessibleDocument& operator =(const xpcAccessibleDocument&) MOZ_DELETE;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleImage.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xpcAccessibleImage.h"
+
+#include "ImageAccessible.h"
+
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleImage::GetImagePosition(uint32_t aCoordType, int32_t* aX, int32_t* aY)
+{
+  NS_ENSURE_ARG_POINTER(aX);
+  *aX = 0;
+  NS_ENSURE_ARG_POINTER(aY);
+  *aY = 0;
+
+  if (static_cast<ImageAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsIntPoint point = static_cast<ImageAccessible*>(this)->Position(aCoordType);
+  *aX = point.x; *aY = point.y;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleImage::GetImageSize(int32_t* aWidth, int32_t* aHeight)
+{
+  NS_ENSURE_ARG_POINTER(aWidth);
+  *aWidth = 0;
+  NS_ENSURE_ARG_POINTER(aHeight);
+  *aHeight = 0;
+
+  if (static_cast<ImageAccessible*>(this)->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  nsIntSize size = static_cast<ImageAccessible*>(this)->Size();
+  *aWidth = size.width;
+  *aHeight = size.height;
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleImage.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_xpcAccessibleImage_h_
+#define mozilla_a11y_xpcAccessibleImage_h_
+
+#include "nsIAccessibleImage.h"
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleImage : public nsIAccessibleImage
+{
+public:
+  NS_IMETHOD GetImagePosition(uint32_t aCoordType,
+                              int32_t* aX, int32_t* aY) MOZ_FINAL;
+  NS_IMETHOD GetImageSize(int32_t* aWidth, int32_t* aHeight) MOZ_FINAL;
+
+private:
+  friend class ImageAccessible;
+
+  xpcAccessibleImage() { }
+
+  xpcAccessibleImage(const xpcAccessibleImage&) MOZ_DELETE;
+  xpcAccessibleImage& operator =(const xpcAccessibleImage&) MOZ_DELETE;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -733,17 +733,18 @@ var CustomEventManager = {
 let DoCommandHelper = {
   _event: null,
   setEvent: function docommand_setEvent(evt) {
     this._event = evt;
   },
 
   handleEvent: function docommand_handleEvent(cmd) {
     if (this._event) {
-      shell.sendEvent(this._event.target, 'mozdocommand', { cmd: cmd });
+      Services.obs.notifyObservers({ wrappedJSObject: this._event.target },
+                                   'copypaste-docommand', cmd);
       this._event = null;
     }
   }
 }
 
 var WebappsHelper = {
   _installers: {},
   _count: 0,
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,19 +10,19 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,19 +10,19 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,19 +10,19 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "6890cdf5807b0c9a4341b97ee39fd692dc95fd0c", 
+    "revision": "aa27f131a40f855892c6ed638e05b6d0ef92aece", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,18 +10,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ff6dbb006e4e60edba697639aa2a2a199b07069b"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/browser/components/loop/content/js/conversation.js
+++ b/browser/components/loop/content/js/conversation.js
@@ -450,30 +450,44 @@ loop.conversation = (function(OT, mozL10
   /**
    * Panel initialisation.
    */
   function init() {
     // Do the initial L10n setup, we do this before anything
     // else to ensure the L10n environment is setup correctly.
     mozL10n.initialize(navigator.mozLoop);
 
+    // Plug in an alternate client ID mechanism, as localStorage and cookies
+    // don't work in the conversation window
+    if (OT && OT.hasOwnProperty("overrideGuidStorage")) {
+      OT.overrideGuidStorage({
+        get: function(callback) {
+          callback(null, navigator.mozLoop.getLoopCharPref("ot.guid"));
+        },
+        set: function(guid, callback) {
+          navigator.mozLoop.setLoopCharPref("ot.guid", guid);
+          callback(null);
+        }
+      });
+    }
+
     document.title = mozL10n.get("incoming_call_title2");
 
     document.body.classList.add(loop.shared.utils.getTargetPlatform());
 
     var client = new loop.Client();
     router = new ConversationRouter({
       client: client,
       conversation: new loop.shared.models.ConversationModel(
         {},         // Model attributes
         {sdk: OT}), // Model dependencies
       notifications: new loop.shared.models.NotificationCollection()
     });
 
-    window.addEventListener("unload", (event) => {
+    window.addEventListener("unload", function(event) {
       // Handle direct close of dialog box via [x] control.
       navigator.mozLoop.releaseCallData(router._conversation.get("callId"));
     });
 
     Backbone.history.start();
   }
 
   return {
--- a/browser/components/loop/content/js/conversation.jsx
+++ b/browser/components/loop/content/js/conversation.jsx
@@ -450,30 +450,44 @@ loop.conversation = (function(OT, mozL10
   /**
    * Panel initialisation.
    */
   function init() {
     // Do the initial L10n setup, we do this before anything
     // else to ensure the L10n environment is setup correctly.
     mozL10n.initialize(navigator.mozLoop);
 
+    // Plug in an alternate client ID mechanism, as localStorage and cookies
+    // don't work in the conversation window
+    if (OT && OT.hasOwnProperty("overrideGuidStorage")) {
+      OT.overrideGuidStorage({
+        get: function(callback) {
+          callback(null, navigator.mozLoop.getLoopCharPref("ot.guid"));
+        },
+        set: function(guid, callback) {
+          navigator.mozLoop.setLoopCharPref("ot.guid", guid);
+          callback(null);
+        }
+      });
+    }
+
     document.title = mozL10n.get("incoming_call_title2");
 
     document.body.classList.add(loop.shared.utils.getTargetPlatform());
 
     var client = new loop.Client();
     router = new ConversationRouter({
       client: client,
       conversation: new loop.shared.models.ConversationModel(
         {},         // Model attributes
         {sdk: OT}), // Model dependencies
       notifications: new loop.shared.models.NotificationCollection()
     });
 
-    window.addEventListener("unload", (event) => {
+    window.addEventListener("unload", function(event) {
       // Handle direct close of dialog box via [x] control.
       navigator.mozLoop.releaseCallData(router._conversation.get("callId"));
     });
 
     Backbone.history.start();
   }
 
   return {
--- a/browser/components/loop/ui/fake-mozLoop.js
+++ b/browser/components/loop/ui/fake-mozLoop.js
@@ -4,10 +4,17 @@
 
 /**
  * Faking the mozLoop object which doesn't exist in regular web pages.
  * @type {Object}
  */
 navigator.mozLoop = {
   ensureRegistered: function() {},
   getLoopCharPref: function() {},
-  getLoopBoolPref: function() {}
+  getLoopBoolPref: function() {},
+  releaseCallData: function() {},
+  contacts: {
+    getAll: function(callback) {
+      callback(null, []);
+    },
+    on: function() {}
+  }
 };
--- a/browser/components/loop/ui/index.html
+++ b/browser/components/loop/ui/index.html
@@ -5,16 +5,17 @@
 <html>
   <head>
     <meta charset="utf-8">
     <title>Loop UI Components Showcase</title>
     <link rel="stylesheet" type="text/css" href="../content/shared/css/reset.css">
     <link rel="stylesheet" type="text/css" href="../content/shared/css/common.css">
     <link rel="stylesheet" type="text/css" href="../content/shared/css/conversation.css">
     <link rel="stylesheet" type="text/css" href="../content/shared/css/panel.css">
+    <link rel="stylesheet" type="text/css" href="../content/shared/css/contacts.css">
     <link rel="stylesheet" type="text/css" href="../standalone/content/css/webapp.css">
     <link rel="stylesheet" type="text/css" href="ui-showcase.css">
  </head>
   <body>
     <div id="main"></div>
     <script src="fake-mozLoop.js"></script>
     <script src="fake-l10n.js"></script>
     <script>
@@ -34,13 +35,26 @@
     <script src="../content/shared/js/utils.js"></script>
     <script src="../content/shared/js/models.js"></script>
     <script src="../content/shared/js/router.js"></script>
     <script src="../content/shared/js/mixins.js"></script>
     <script src="../content/shared/js/views.js"></script>
     <script src="../content/js/client.js"></script>
     <script src="../content/js/desktopRouter.js"></script>
     <script src="../standalone/content/js/webapp.js"></script>
+    <script type="text/javascript;version=1.8" src="../content/js/contacts.js"></script>
+    <script>
+      if (!loop.contacts) {
+        // For browsers that don't support ES6 without special flags (all but Fx
+        // at the moment), we shim the contacts namespace with its most barebone
+        // implementation.
+        loop.contacts = {
+          ContactsList: React.createClass({render: function() {
+            return React.DOM.div();
+          }})
+        };
+      }
+    </script>
     <script src="../content/js/panel.js"></script>
     <script src="../content/js/conversation.js"></script>
     <script src="ui-showcase.js"></script>
   </body>
 </html>
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -147,34 +147,34 @@
                          userProfile: {email: "test@example.com"}})
             )
           ), 
 
           Section({name: "IncomingCallView"}, 
             Example({summary: "Default / incoming video call", dashed: "true", style: {width: "280px"}}, 
               React.DOM.div({className: "fx-embedded"}, 
                 IncomingCallView({model: mockConversationModel, 
-                                  video: {enabled: true}})
+                                  video: true})
               )
             ), 
 
             Example({summary: "Default / incoming audio only call", dashed: "true", style: {width: "280px"}}, 
               React.DOM.div({className: "fx-embedded"}, 
                 IncomingCallView({model: mockConversationModel, 
-                                  video: {enabled: false}})
+                                  video: false})
               )
             )
           ), 
 
           Section({name: "IncomingCallView-ActiveState"}, 
             Example({summary: "Default", dashed: "true", style: {width: "280px"}}, 
               React.DOM.div({className: "fx-embedded"}, 
                 IncomingCallView({model: mockConversationModel, 
                                    showDeclineMenu: true, 
-                                   video: {enabled: true}})
+                                   video: true})
               )
             )
           ), 
 
           Section({name: "ConversationToolbar"}, 
             React.DOM.h2(null, "Desktop Conversation Window"), 
             React.DOM.div({className: "fx-embedded override-position"}, 
               Example({summary: "Default (260x265)", dashed: "true"}, 
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -147,34 +147,34 @@
                          userProfile={{email: "test@example.com"}} />
             </Example>
           </Section>
 
           <Section name="IncomingCallView">
             <Example summary="Default / incoming video call" dashed="true" style={{width: "280px"}}>
               <div className="fx-embedded">
                 <IncomingCallView model={mockConversationModel}
-                                  video={{enabled: true}} />
+                                  video={true} />
               </div>
             </Example>
 
             <Example summary="Default / incoming audio only call" dashed="true" style={{width: "280px"}}>
               <div className="fx-embedded">
                 <IncomingCallView model={mockConversationModel}
-                                  video={{enabled: false}} />
+                                  video={false} />
               </div>
             </Example>
           </Section>
 
           <Section name="IncomingCallView-ActiveState">
             <Example summary="Default" dashed="true" style={{width: "280px"}}>
               <div className="fx-embedded" >
                 <IncomingCallView  model={mockConversationModel}
                                    showDeclineMenu={true}
-                                   video={{enabled: true}} />
+                                   video={true} />
               </div>
             </Example>
           </Section>
 
           <Section name="ConversationToolbar">
             <h2>Desktop Conversation Window</h2>
             <div className="fx-embedded override-position">
               <Example summary="Default (260x265)" dashed="true">
--- a/browser/devtools/styleinspector/test/browser_ruleview_add-rule_01.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_add-rule_01.js
@@ -10,22 +10,24 @@
 let PAGE_CONTENT = [
   '<style type="text/css">',
   '  .testclass {',
   '    text-align: center;',
   '  }',
   '</style>',
   '<div id="testid" class="testclass">Styled Node</div>',
   '<span class="testclass2">This is a span</span>',
+  '<span class="class1 class2">Multiple classes</span>',
   '<p>Empty<p>'
 ].join("\n");
 
 const TEST_DATA = [
   { node: "#testid", expected: "#testid" },
   { node: ".testclass2", expected: ".testclass2" },
+  { node: ".class1.class2", expected: ".class1" },
   { node: "p", expected: "p" }
 ];
 
 let test = asyncTest(function*() {
   yield addTab("data:text/html;charset=utf-8,test rule view add rule");
 
   info("Creating the test document");
   content.document.body.innerHTML = PAGE_CONTENT;
--- a/browser/devtools/webaudioeditor/test/browser.ini
+++ b/browser/devtools/webaudioeditor/test/browser.ini
@@ -26,16 +26,17 @@ support-files =
 
 [browser_wa_destroy-node-01.js]
 
 [browser_wa_first-run.js]
 [browser_wa_reset-01.js]
 [browser_wa_reset-02.js]
 [browser_wa_reset-03.js]
 [browser_wa_reset-04.js]
+[browser_wa_navigate.js]
 
 [browser_wa_graph-click.js]
 [browser_wa_graph-markers.js]
 [browser_wa_graph-render-01.js]
 [browser_wa_graph-render-02.js]
 [browser_wa_graph-render-03.js]
 [browser_wa_graph-render-04.js]
 [browser_wa_graph-selected.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webaudioeditor/test/browser_wa_navigate.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests naviating from a page to another will repopulate
+ * the audio graph if both pages have an AudioContext.
+ */
+
+function spawnTest() {
+  let [target, debuggee, panel] = yield initWebAudioEditor(SIMPLE_CONTEXT_URL);
+  let { panelWin } = panel;
+  let { gFront, $ } = panelWin;
+
+  reload(target);
+
+  var [actors] = yield Promise.all([
+    get3(gFront, "create-node"),
+    waitForGraphRendered(panelWin, 3, 2)
+  ]);
+
+  var { nodes, edges } = countGraphObjects(panelWin);
+  ise(nodes, 3, "should only be 3 nodes.");
+  ise(edges, 2, "should only be 2 edges.");
+
+  navigate(target, SIMPLE_NODES_URL);
+
+  var [actors] = yield Promise.all([
+    getN(gFront, "create-node", 14),
+    waitForGraphRendered(panelWin, 14, 0)
+  ]);
+
+  is($("#reload-notice").hidden, true,
+    "The 'reload this page' notice should be hidden after context found after navigation.");
+  is($("#waiting-notice").hidden, true,
+    "The 'waiting for an audio context' notice should be hidden after context found after navigation.");
+  is($("#content").hidden, false,
+    "The tool's content should reappear without closing and reopening the toolbox.");
+
+  var { nodes, edges } = countGraphObjects(panelWin);
+  ise(nodes, 14, "after navigation, should have 14 nodes");
+  ise(edges, 0, "after navigation, should have 0 edges.");
+
+  yield teardown(panel);
+  finish();
+}
--- a/browser/devtools/webaudioeditor/test/head.js
+++ b/browser/devtools/webaudioeditor/test/head.js
@@ -109,16 +109,21 @@ function once(aTarget, aEventName, aUseC
   return deferred.promise;
 }
 
 function reload(aTarget, aWaitForTargetEvent = "navigate") {
   aTarget.activeTab.reload();
   return once(aTarget, aWaitForTargetEvent);
 }
 
+function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
+  executeSoon(() => aTarget.activeTab.navigateTo(aUrl));
+  return once(aTarget, aWaitForTargetEvent);
+}
+
 function test () {
   Task.spawn(spawnTest).then(finish, handleError);
 }
 
 function initBackend(aUrl) {
   info("Initializing a web audio editor front.");
 
   if (!DebuggerServer.initialized) {
--- a/browser/devtools/webide/content/webide.js
+++ b/browser/devtools/webide/content/webide.js
@@ -2,30 +2,30 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const Cc = Components.classes;
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 
 Cu.import("resource:///modules/devtools/gDevTools.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 
 const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 const {require} = devtools;
 const {Services} = Cu.import("resource://gre/modules/Services.jsm");
 const {AppProjects} = require("devtools/app-manager/app-projects");
 const {Connection} = require("devtools/client/connection-manager");
 const {AppManager} = require("devtools/webide/app-manager");
 const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
 const ProjectEditor = require("projecteditor/projecteditor");
 const {Devices} = Cu.import("resource://gre/modules/devtools/Devices.jsm");
 const {GetAvailableAddons} = require("devtools/webide/addons");
 const {GetTemplatesJSON, GetAddonsJSON} = require("devtools/webide/remote-resources");
+const utils = require("devtools/webide/utils");
 
 const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
 
 const HTML = "http://www.w3.org/1999/xhtml";
 const HELP_URL = "https://developer.mozilla.org/docs/Tools/WebIDE/Troubleshooting";
 
 // download template index early
 GetTemplatesJSON(true);
@@ -129,23 +129,25 @@ let UI = {
         this.updateRuntimeList();
         this.autoConnectRuntime();
         break;
       case "connection":
         this.updateRuntimeButton();
         this.updateCommands();
         break;
       case "project":
-        this.updateTitle();
-        this.destroyToolbox();
-        this.updateCommands();
-        this.updateProjectButton();
-        this.openProject();
-        this.autoStartProject();
-        break;
+        this._updatePromise = Task.spawn(function() {
+          UI.updateTitle();
+          yield UI.destroyToolbox();
+          UI.updateCommands();
+          UI.updateProjectButton();
+          UI.openProject();
+          UI.autoStartProject();
+        });
+        return;
       case "project-is-not-running":
       case "project-is-running":
       case "list-tabs-response":
         this.updateCommands();
         break;
       case "runtime":
         this.updateRuntimeButton();
         this.saveLastConnectedRuntime();
@@ -154,16 +156,17 @@ let UI = {
         this.updateTitle();
         this.updateCommands();
         this.updateProjectButton();
         this.updateProjectEditorHeader();
         break;
       case "install-progress":
         this.updateProgress(Math.round(100 * details.bytesSent / details.totalBytes));
     };
+    this._updatePromise = promise.resolve();
   },
 
   openInBrowser: function(url) {
     // Open a URL in a Firefox window
     let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
     if (browserWin) {
       let gBrowser = browserWin.gBrowser;
       gBrowser.selectedTab = gBrowser.addTab(url);
@@ -247,20 +250,21 @@ let UI = {
     this._busyPromise = promise;
     this._busyOperationDescription = operationDescription;
     this.setupBusyTimeout();
     this.busy();
     promise.then(() => {
       this.cancelBusyTimeout();
       this.unbusy();
     }, (e) => {
+      let message = operationDescription + (e ? (": " + e) : "");
       this.cancelBusyTimeout();
       let operationCanceled = e && e.canceled;
       if (!operationCanceled) {
-        UI.reportError("error_operationFail", operationDescription);
+        UI.reportError("error_operationFail", message);
         console.error(e);
       }
       this.unbusy();
     });
     return promise;
   },
 
   reportError: function(l10nProperty, ...l10nArgs) {
@@ -498,18 +502,17 @@ let UI = {
     if (project.location) {
       Services.prefs.setCharPref("devtools.webide.lastprojectlocation", project.location);
     }
 
     // Make sure the directory exist before we show Project Editor
 
     let forceDetailsOnly = false;
     if (project.type == "packaged") {
-      let directory = new FileUtils.File(project.location);
-      forceDetailsOnly = !directory.exists();
+      forceDetailsOnly = !utils.doesFileExist(project.location);
     }
 
     // Show only the details screen
 
     if (project.type != "packaged" ||
         !this.isProjectEditorEnabled() ||
         forceDetailsOnly) {
       this.selectDeckPanel("details");
@@ -540,16 +543,38 @@ let UI = {
     Task.spawn(function() {
       if (project.type == "runtimeApp") {
         yield UI.busyUntil(AppManager.launchRuntimeApp(), "running app");
       }
       yield UI.createToolbox();
     });
   },
 
+  importAndSelectApp: Task.async(function* (source) {
+    let isPackaged = !!source.path;
+    let project;
+    try {
+      project = yield AppProjects[isPackaged ? "addPackaged" : "addHosted"](source);
+    } catch (e) {
+      if (e === "Already added") {
+        // Select project that's already been added,
+        // and allow it to be revalidated and selected
+        project = AppProjects.get(isPackaged ? source.path : source);
+      } else {
+        throw e;
+      }
+    }
+
+    // Validate project
+    yield AppManager.validateProject(project);
+
+    // Select project
+    AppManager.selectedProject = project;
+  }),
+
   /********** DECK **********/
 
   setupDeck: function() {
     let iframes = document.querySelectorAll("#deck > iframe");
     for (let iframe of iframes) {
       iframe.tooltip = "aHTMLTooltip";
     }
   },
@@ -690,21 +715,22 @@ let UI = {
           this.closeToolboxUI();
           break;
       }
     } catch(e) { console.error(e); }
   },
 
   destroyToolbox: function() {
     if (this.toolboxPromise) {
-      this.toolboxPromise.then(toolbox => {
+      return this.toolboxPromise.then(toolbox => {
         toolbox.destroy();
         this.toolboxPromise = null;
       }, console.error);
     }
+    return promise.resolve();
   },
 
   createToolbox: function() {
     this.toolboxPromise = AppManager.getTarget().then((target) => {
       return this.showToolbox(target);
     }, console.error);
     return this.busyUntil(this.toolboxPromise, "opening toolbox");
   },
@@ -780,79 +806,40 @@ let Cmds = {
       AppManager.selectedProject = project;
 
     }), "creating new app");
   },
 
   importPackagedApp: function(location) {
     return UI.busyUntil(Task.spawn(function* () {
 
-      let directory;
+      let directory = utils.getPackagedDirectory(window, location);
 
-      if (!location) {
-        let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-        fp.init(window, Strings.GetStringFromName("importPackagedApp_title"), Ci.nsIFilePicker.modeGetFolder);
-        let res = fp.show();
-        if (res == Ci.nsIFilePicker.returnCancel) {
-          return promise.resolve();
-        }
-        directory = fp.file;
-      } else {
-        directory = new FileUtils.File(location);
+      if (!directory) {
+        // User cancelled directory selection
+        return;
       }
 
-      // Add project
-      let project = yield AppProjects.addPackaged(directory);
-
-      // Validate project
-      yield AppManager.validateProject(project);
-
-      // Select project
-      AppManager.selectedProject = project;
+      yield UI.importAndSelectApp(directory);
     }), "importing packaged app");
   },
 
-
   importHostedApp: function(location) {
     return UI.busyUntil(Task.spawn(function* () {
-      let ret = {value: null};
 
-      let url;
-      if (!location) {
-        Services.prompt.prompt(window,
-                               Strings.GetStringFromName("importHostedApp_title"),
-                               Strings.GetStringFromName("importHostedApp_header"),
-                               ret, null, {});
-        location = ret.value;
-      }
+      let url = utils.getHostedURL(window, location);
 
-      if (!location) {
+      if (!url) {
         return;
       }
 
-      // Clean location string and add "http://" if missing
-      location = location.trim();
-      try { // Will fail if no scheme
-        Services.io.extractScheme(location);
-      } catch(e) {
-        location = "http://" + location;
-      }
-
-      // Add project
-      let project = yield AppProjects.addHosted(location)
-
-      // Validate project
-      yield AppManager.validateProject(project);
-
-      // Select project
-      AppManager.selectedProject = project;
+      yield UI.importAndSelectApp(url);
     }), "importing hosted app");
   },
 
-
   showProjectPanel: function() {
     let deferred = promise.defer();
 
     let panelNode = document.querySelector("#project-panel");
     let panelVboxNode = document.querySelector("#project-panel > vbox");
     let anchorNode = document.querySelector("#project-panel-button > .panel-button-anchor");
     let projectsNode = document.querySelector("#project-panel-projects");
 
@@ -1096,9 +1083,9 @@ let Cmds = {
 
   showAddons: function() {
     UI.selectDeckPanel("addons");
   },
 
   showPrefs: function() {
     UI.selectDeckPanel("prefs");
   },
-}
+};
--- a/browser/devtools/webide/modules/tab-store.js
+++ b/browser/devtools/webide/modules/tab-store.js
@@ -117,17 +117,21 @@ TabStore.prototype = {
   // which is the selected project.  This should be done as part of the
   // project-agnostic work.
   _selectedTab: null,
   _selectedTabTargetPromise: null,
   get selectedTab() {
     return this._selectedTab;
   },
   set selectedTab(tab) {
+    if (this._selectedTab === tab) {
+      return;
+    }
     this._selectedTab = tab;
+    this._selectedTabTargetPromise = null;
     // Attach to the tab to follow navigation events
     if (this._selectedTab) {
       this.getTargetForTab();
     }
   },
 
   _checkSelectedTab: function() {
     if (!this._selectedTab) {
@@ -155,12 +159,17 @@ TabStore.prototype = {
       // issue, we force a "listTabs" request before connecting to a tab.
       yield store.listTabs();
       return devtools.TargetFactory.forRemoteTab({
         form: store._selectedTab,
         client: store._connection.client,
         chrome: false
       });
     });
+    this._selectedTabTargetPromise.then(target => {
+      target.once("close", () => {
+        this._selectedTabTargetPromise = null;
+      });
+    });
     return this._selectedTabTargetPromise;
   },
 
 };
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webide/modules/utils.js
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const { Cc, Cu, Ci } = require("chrome");
+const { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
+const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
+const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
+
+function doesFileExist (location) {
+  let file = new FileUtils.File(location);
+  return file.exists();
+}
+exports.doesFileExist = doesFileExist;
+
+function getPackagedDirectory (window, location) {
+  let directory;
+  if (!location) {
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    fp.init(window, Strings.GetStringFromName("importPackagedApp_title"), Ci.nsIFilePicker.modeGetFolder);
+    let res = fp.show();
+    if (res == Ci.nsIFilePicker.returnCancel) {
+      return null;
+    }
+    return fp.file;
+  } else {
+    return new FileUtils.File(location);
+  }
+}
+exports.getPackagedDirectory = getPackagedDirectory;
+
+function getHostedURL (window, location) {
+  let ret = { value: null };
+
+  if (!location) {
+    Services.prompt.prompt(window,
+        Strings.GetStringFromName("importHostedApp_title"),
+        Strings.GetStringFromName("importHostedApp_header"),
+        ret, null, {});
+    location = ret.value;
+  }
+
+  if (!location) {
+    return null;
+  }
+
+  // Clean location string and add "http://" if missing
+  location = location.trim();
+  try { // Will fail if no scheme
+    Services.io.extractScheme(location);
+  } catch(e) {
+    location = "http://" + location;
+  }
+  return location;
+}
+exports.getHostedURL = getHostedURL;
--- a/browser/devtools/webide/moz.build
+++ b/browser/devtools/webide/moz.build
@@ -14,9 +14,10 @@ BROWSER_CHROME_MANIFESTS += ['test/brows
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 EXTRA_JS_MODULES.devtools.webide += [
     'modules/addons.js',
     'modules/app-manager.js',
     'modules/remote-resources.js',
     'modules/runtimes.js',
     'modules/tab-store.js',
+    'modules/utils.js',
 ]
--- a/browser/devtools/webide/test/chrome.ini
+++ b/browser/devtools/webide/test/chrome.ini
@@ -22,13 +22,14 @@ support-files =
   addons/adbhelper-mac64.xpi
   head.js
   hosted_app.manifest
   templates.json
 
 [test_basic.html]
 [test_newapp.html]
 [test_import.html]
+[test_duplicate_import.html]
 [test_runtime.html]
 [test_manifestUpdate.html]
 [test_addons.html]
 [test_deviceinfo.html]
 [test_autoconnect_runtime.html]
--- a/browser/devtools/webide/test/head.js
+++ b/browser/devtools/webide/test/head.js
@@ -80,19 +80,21 @@ function closeWebIDE(win) {
   win.close();
 
   return deferred.promise;
 }
 
 function removeAllProjects() {
   return Task.spawn(function* () {
     yield AppProjects.load();
-    let projects = AppProjects.store.object.projects;
+    // use a new array so we're not iterating over the same
+    // underlying array that's being modified by AppProjects
+    let projects = AppProjects.store.object.projects.map(p => p.location);
     for (let i = 0; i < projects.length; i++) {
-      yield AppProjects.remove(projects[i].location);
+      yield AppProjects.remove(projects[i]);
     }
   });
 }
 
 function nextTick() {
   let deferred = promise.defer();
   SimpleTest.executeSoon(() => {
     deferred.resolve();
@@ -103,17 +105,17 @@ function nextTick() {
 
 function waitForUpdate(win, update) {
   let deferred = promise.defer();
   win.AppManager.on("app-manager-update", function onUpdate(e, what) {
     if (what !== update) {
       return;
     }
     win.AppManager.off("app-manager-update", onUpdate);
-    deferred.resolve();
+    deferred.resolve(win.UI._updatePromise);
   });
   return deferred.promise;
 }
 
 function documentIsLoaded(doc) {
   let deferred = promise.defer();
   if (doc.readyState == "complete") {
     deferred.resolve();
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webide/test/test_duplicate_import.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+
+<html>
+
+  <head>
+    <meta charset="utf8">
+    <title></title>
+
+    <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
+    <script type="application/javascript;version=1.8" src="head.js"></script>
+    <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+  </head>
+
+  <body>
+
+    <script type="application/javascript;version=1.8">
+      window.onload = function() {
+        SimpleTest.waitForExplicitFinish();
+
+        Task.spawn(function* () {
+          let win = yield openWebIDE();
+          let packagedAppLocation = getTestFilePath("app");
+          let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
+
+          yield win.AppProjects.load();
+          is(win.AppProjects.store.object.projects.length, 0, "IDB is empty");
+
+          info("to call importPackagedApp(" + packagedAppLocation + ")");
+          yield win.Cmds.importPackagedApp(packagedAppLocation);
+          yield nextTick();
+
+          info("to call importHostedApp(" + hostedAppManifest + ")");
+          yield win.Cmds.importHostedApp(hostedAppManifest);
+          yield nextTick();
+
+          info("to call importPackagedApp(" + packagedAppLocation + ") again");
+          yield win.Cmds.importPackagedApp(packagedAppLocation);
+
+          let project = win.AppManager.selectedProject;
+          is(project.location, packagedAppLocation, "Correctly reselected existing packaged app.");
+          yield nextTick();
+
+          info("to call importHostedApp(" + hostedAppManifest + ") again");
+          yield win.Cmds.importHostedApp(hostedAppManifest);
+          project = win.AppManager.selectedProject;
+          is(project.location, hostedAppManifest, "Correctly reselected existing hosted app.");
+          yield nextTick();
+
+          info("opening panel");
+          yield win.Cmds.showProjectPanel();
+          info("panel open");
+
+          let panelNode = win.document.querySelector("#project-panel");
+          let items = panelNode.querySelectorAll(".panel-item");
+          // 3 controls, + 2 projects
+          is(items.length, 5, "5 projects in panel");
+          is(items[3].getAttribute("label"), "A name (in app directory)", "Panel label is correct");
+          is(items[4].getAttribute("label"), "hosted manifest name property", "Panel label is correct");
+
+          yield closeWebIDE(win);
+
+          yield removeAllProjects();
+
+          SimpleTest.finish();
+        }).then(null, e => {
+          ok(false, "Exception: " + e);
+          SimpleTest.finish();
+        });
+      }
+    </script>
+  </body>
+</html>
+
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -503,18 +503,21 @@ class Automation(object):
       env[preloadEnvVar] = os.path.join(dmdPath, dmdLibrary)
 
     if crashreporter and not debugger:
       env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
       env['MOZ_CRASHREPORTER'] = '1'
     else:
       env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
-    # Crash on non-local network connections.
-    env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
+    # Crash on non-local network connections by default.
+    # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily
+    # enable non-local connections for the purposes of local testing.  Don't
+    # override the user's choice here.  See bug 1049688.
+    env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
 
     env['GNOME_DISABLE_CRASH_DIALOG'] = '1'
     env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1'
     env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
 
     # Set WebRTC logging in case it is not set yet
     env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
     env.setdefault('R_LOG_LEVEL', '6')
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -427,18 +427,21 @@ def environment(xrePath, env=None, crash
   env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
 
   if crashreporter and not debugger:
     env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
     env['MOZ_CRASHREPORTER'] = '1'
   else:
     env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
-  # Crash on non-local network connections.
-  env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
+  # Crash on non-local network connections by default.
+  # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily
+  # enable non-local connections for the purposes of local testing.  Don't
+  # override the user's choice here.  See bug 1049688.
+  env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
 
   # Set WebRTC logging in case it is not set yet
   env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
   env.setdefault('R_LOG_LEVEL', '6')
   env.setdefault('R_LOG_DESTINATION', 'stderr')
   env.setdefault('R_LOG_VERBOSE', '1')
 
   # ASan specific environment stuff
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -69,18 +69,21 @@ class RemoteAutomation(Automation):
             env['MOZ_HIDE_RESULTS_TABLE'] = os.environ['MOZ_HIDE_RESULTS_TABLE']
 
         if crashreporter and not debugger:
             env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
             env['MOZ_CRASHREPORTER'] = '1'
         else:
             env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
-        # Crash on non-local network connections.
-        env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
+        # Crash on non-local network connections by default.
+        # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily
+        # enable non-local connections for the purposes of local testing.
+        # Don't override the user's choice here.  See bug 1049688.
+        env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
 
         return env
 
     def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath):
         """ Wait for tests to finish.
             If maxTime seconds elapse or no output is detected for timeout
             seconds, kill the process and fail the test.
         """
--- a/config/external/nss/nss.def
+++ b/config/external/nss/nss.def
@@ -665,8 +665,9 @@ SSL_VersionRangeSetDefault
 UTIL_SetForkState
 VFY_Begin
 VFY_CreateContext
 VFY_DestroyContext
 VFY_End
 VFY_Update
 VFY_VerifyDataDirect
 VFY_VerifyDataWithAlgorithmID
+_SGN_VerifyPKCS1DigestInfo
--- a/content/base/src/nsCSPContext.cpp
+++ b/content/base/src/nsCSPContext.cpp
@@ -1237,14 +1237,15 @@ nsCSPContext::Write(nsIObjectOutputStrea
                                                true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Serialize all the policies.
   aStream->Write32(mPolicies.Length());
 
   nsAutoString polStr;
   for (uint32_t p = 0; p < mPolicies.Length(); p++) {
+    polStr.Truncate();
     mPolicies[p]->toString(polStr);
     aStream->WriteWStringZ(polStr.get());
     aStream->WriteBoolean(mPolicies[p]->getReportOnlyFlag());
   }
   return NS_OK;
 }
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -507,16 +507,17 @@ BrowserElementChild.prototype = {
       target[attribute] = src.getAttribute(attribute);
     }
   },
 
   _iconChangedHandler: function(e) {
     debug('Got iconchanged: (' + e.target.href + ')');
     let icon = { href: e.target.href };
     this._maybeCopyAttribute(e.target, icon, 'sizes');
+    this._maybeCopyAttribute(e.target, icon, 'rel');
     sendAsyncMsg('iconchange', icon);
   },
 
   _openSearchHandler: function(e) {
     debug('Got opensearch: (' + e.target.href + ')');
 
     if (e.target.type !== "application/opensearchdescription+xml") {
       return;
--- a/dom/browser-element/BrowserElementParent.jsm
+++ b/dom/browser-element/BrowserElementParent.jsm
@@ -80,16 +80,17 @@ function BrowserElementParent(frameLoade
   let self = this;
   if (!this._frameElement) {
     debug("No frame element?");
     return;
   }
 
   Services.obs.addObserver(this, 'ask-children-to-exit-fullscreen', /* ownsWeak = */ true);
   Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
+  Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true);
 
   let defineMethod = function(name, fn) {
     XPCNativeWrapper.unwrap(self._frameElement)[name] = function() {
       if (self._isAlive()) {
         return fn.apply(self, arguments);
       }
     };
   }
@@ -164,24 +165,16 @@ function BrowserElementParent(frameLoade
   if (!this._window._browserElementParents) {
     this._window._browserElementParents = new WeakMap();
     this._window.addEventListener('visibilitychange',
                                   visibilityChangeHandler,
                                   /* useCapture = */ false,
                                   /* wantsUntrusted = */ false);
   }
 
-  this._doCommandHandlerBinder = this._doCommandHandler.bind(this);
-  this._frameElement.addEventListener('mozdocommand',
-                                      this._doCommandHandlerBinder,
-                                      /* useCapture = */ false,
-                                      /* wantsUntrusted = */ false);
-
-  Services.obs.addObserver(this, 'ipc:browser-destroyed', /* ownsWeak = */ true);
-
   this._window._browserElementParents.set(this, null);
 
   // Insert ourself into the prompt service.
   BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this);
   if (!isPendingFrame) {
     this._setupMessageListener();
     this._registerAppManifest();
   } else {
@@ -493,21 +486,16 @@ BrowserElementParent.prototype = {
   },
 
   _handleSelectionChange: function(data) {
     let evt = this._createEvent('selectionchange', data.json,
                                 /* cancelable = */ false);
     this._frameElement.dispatchEvent(evt);
   },
 
-  _doCommandHandler: function(e) {
-    e.stopPropagation();
-    this._sendAsyncMsg('do-command', { command: e.detail.cmd });
-  },
-
   _createEvent: function(evtName, detail, cancelable) {
     // This will have to change if we ever want to send a CustomEvent with null
     // detail.  For now, it's OK.
     if (detail !== undefined && detail !== null) {
       detail = Cu.cloneInto(detail, this._window);
       return new this._window.CustomEvent('mozbrowser' + evtName,
                                           { bubbles: true,
                                             cancelable: cancelable,
@@ -921,21 +909,19 @@ BrowserElementParent.prototype = {
     case 'remote-browser-frame-shown':
       if (this._frameLoader == subject) {
         if (!this._mm) {
           this._setupMessageListener();
           this._registerAppManifest();
         }
         Services.obs.removeObserver(this, 'remote-browser-frame-shown');
       }
-    case 'ipc:browser-destroyed':
-      if (this._isAlive() && subject == this._frameLoader) {
-        Services.obs.removeObserver(this, 'ipc:browser-destroyed');
-        this._frameElement.removeEventListener('mozdocommand',
-                                               this._doCommandHandlerBinder)
+    case 'copypaste-docommand':
+      if (this._isAlive() && this._frameElement.isEqualNode(subject.wrappedJSObject)) {
+        this._sendAsyncMsg('do-command', { command: data });
       }
       break;
     default:
       debug('Unknown topic: ' + topic);
       break;
     };
   },
 };
--- a/dom/browser-element/mochitest/browserElement_CopyPaste.js
+++ b/dom/browser-element/mochitest/browserElement_CopyPaste.js
@@ -3,16 +3,17 @@
 
 // Test that "cut, copy, paste, selectall" and selectionchange event works from inside an <iframe mozbrowser>.
 "use strict";
 
 SimpleTest.waitForExplicitFinish();
 browserElementTestHelpers.setEnabledPref(true);
 browserElementTestHelpers.setSelectionChangeEnabledPref(true);
 browserElementTestHelpers.addPermission();
+const { Services } = SpecialPowers.Cu.import('resource://gre/modules/Services.jsm');
 var gTextarea = null;
 var mm;
 var iframe;
 var state = 0;
 var stateMeaning;
 var defaultData;
 var pasteData;
 var focusScript;
@@ -55,20 +56,18 @@ function runTest() {
 
   iframe.addEventListener("mozbrowserloadend", function onloadend(e) {
     iframe.removeEventListener("mozbrowserloadend", onloadend);
     dispatchTest(e);
   });
 }
 
 function doCommand(cmd) {
-  let doc = iframe.ownerDocument;
-  let event = doc.createEvent('CustomEvent');
-  event.initCustomEvent('mozdocommand', true, true, { cmd: cmd });
-  SpecialPowers.wrap(iframe).dispatchEvent(event);
+  Services.obs.notifyObservers({wrappedJSObject: iframe},
+                               'copypaste-docommand', cmd);
 }
 
 function dispatchTest(e) {
   iframe.addEventListener("mozbrowserloadend", function onloadend2(e) {
     iframe.removeEventListener("mozbrowserloadend", onloadend2);
     SimpleTest.executeSoon(function() { testSelectAll(e); });
   });
 
--- a/dom/browser-element/mochitest/browserElement_Iconchange.js
+++ b/dom/browser-element/mochitest/browserElement_Iconchange.js
@@ -95,16 +95,17 @@ function runTest() {
       iframe1.src = createHtml(createLink('testsize', '50x50', 'icon'));
     }
     else if (numIconChanges == 7) {
       is(e.detail.href, 'http://example.com/testsize.png');
       is(e.detail.sizes, '50x50');
       iframe1.src = createHtml(createLink('testapple1', '100x100', 'apple-touch-icon'));
     } else if (numIconChanges == 8) {
       is(e.detail.href, 'http://example.com/testapple1.png');
+      is(e.detail.rel, 'apple-touch-icon');
       is(e.detail.sizes, '100x100');
       SimpleTest.finish();
     } else {
       ok(false, 'Too many iconchange events.');
     }
   });
 
   iframe3.addEventListener('mozbrowsericonchange', function(e) {
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4617,16 +4617,17 @@ CanvasPath::AddPath(CanvasPath& aCanvasP
     Matrix transform(m.A(), m.B(), m.C(), m.D(), m.E(), m.F());
 
     if (!transform.IsIdentity()) {
       RefPtr<PathBuilder> tempBuilder = tempPath->TransformedCopyToBuilder(transform, FillRule::FILL_WINDING);
       tempPath = tempBuilder->Finish();
     }
   }
 
+  EnsurePathBuilder(); // in case a path is added to itself
   tempPath->StreamToSink(mPathBuilder);
 }
 
 TemporaryRef<gfx::Path>
 CanvasPath::GetPath(const CanvasWindingRule& winding, const DrawTarget* aTarget) const
 {
   FillRule fillRule = FillRule::FILL_WINDING;
   if (winding == CanvasWindingRule::Evenodd) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -88,17 +88,17 @@ class Element;
 struct WebGLContextAttributes;
 template<typename> struct Nullable;
 }
 
 namespace gfx {
 class SourceSurface;
 }
 
-WebGLTexelFormat GetWebGLTexelFormat(GLenum format, GLenum type);
+WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format, TexType type);
 
 void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
 
 struct WebGLContextOptions {
     // these are defaults
     WebGLContextOptions();
 
     bool operator==(const WebGLContextOptions& other) const {
@@ -216,17 +216,17 @@ public:
 
     /**
      * Return displayable name for GLenum.
      * This version is like gl::GLenumToStr but with out the GL_ prefix to
      * keep consistency with how errors are reported from WebGL.
      */
     static const char *EnumName(GLenum glenum);
 
-    bool IsTextureFormatCompressed(GLenum format);
+    bool IsTextureFormatCompressed(TexInternalFormat format);
 
     void DummyFramebufferOperation(const char *info);
 
     WebGLTexture* activeBoundTextureForTarget(const TexTarget texTarget) const {
         return texTarget == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
                                                 : mBoundCubeMapTextures[mActiveTexture];
     }
 
@@ -1088,17 +1088,17 @@ protected:
     bool ValidateStencilParamsForDrawCall();
 
     bool ValidateGLSLVariableName(const nsAString& name, const char *info);
     bool ValidateGLSLCharacter(char16_t c);
     bool ValidateGLSLString(const nsAString& string, const char *info);
 
     bool ValidateCopyTexImage(GLenum format, WebGLTexImageFunc func);
     bool ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
-                          GLint level, GLint internalFormat,
+                          GLint level, GLenum internalFormat,
                           GLint xoffset, GLint yoffset, GLint zoffset,
                           GLint width, GLint height, GLint depth,
                           GLint border, GLenum format, GLenum type,
                           WebGLTexImageFunc func);
     bool ValidateTexImageTarget(GLuint dims, GLenum target, WebGLTexImageFunc func);
     bool ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func);
     bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func);
     bool ValidateTexImageFormatAndType(GLenum format, GLenum type, WebGLTexImageFunc func);
@@ -1115,17 +1115,17 @@ protected:
                                   GLsizei width, GLsizei height,
                                   GLsizei levelWidth, GLsizei levelHeight,
                                   WebGLTexImageFunc func);
     bool ValidateCompTexImageDataSize(GLint level, GLenum format,
                                       GLsizei width, GLsizei height,
                                       uint32_t byteLength, WebGLTexImageFunc func);
 
 
-    static uint32_t GetBitsPerTexel(GLenum format, GLenum type);
+    static uint32_t GetBitsPerTexel(TexInternalFormat format, TexType type);
 
     void Invalidate();
     void DestroyResourcesAndContext();
 
     void MakeContextCurrent() const;
 
     // helpers
     void TexImage2D_base(TexImageTarget target, GLint level, GLenum internalformat,
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -590,17 +590,17 @@ WebGLContext::CopyTexSubImage2D(GLenum r
 
     if (!mBoundFramebuffer)
         ClearBackbufferIfNeeded();
 
     if (imageInfo.HasUninitializedImageData()) {
         tex->DoDeferredImageInitialization(texImageTarget, level);
     }
 
-    return CopyTexSubImage2D_base(texImageTarget, level, imageInfo.WebGLFormat(), xoffset, yoffset, x, y, width, height, true);
+    return CopyTexSubImage2D_base(texImageTarget, level, imageInfo.WebGLFormat().get(), xoffset, yoffset, x, y, width, height, true);
 }
 
 
 already_AddRefed<WebGLProgram>
 WebGLContext::CreateProgram()
 {
     if (IsContextLost())
         return nullptr;
@@ -895,17 +895,17 @@ WebGLContext::GenerateMipmap(GLenum rawT
     if (!tex->HasImageInfoAt(imageTarget, 0))
     {
         return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
     }
 
     if (!tex->IsFirstImagePowerOfTwo())
         return ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
 
-    GLenum webGLFormat = tex->ImageInfoAt(imageTarget, 0).WebGLFormat();
+    TexInternalFormat webGLFormat = tex->ImageInfoAt(imageTarget, 0).WebGLFormat();
     if (IsTextureFormatCompressed(webGLFormat))
         return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
 
     if (IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
         (IsGLDepthFormat(webGLFormat) || IsGLDepthStencilFormat(webGLFormat)))
     {
         return ErrorInvalidOperation("generateMipmap: "
                                      "A texture that has a base internal format of "
@@ -1172,17 +1172,17 @@ WebGLContext::GetFramebufferAttachmentPa
         }
 
         ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
         return JS::NullValue();
     } else if (fba.Texture()) {
         switch (pname) {
              case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
                 if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB)) {
-                    const GLenum webGLFormat =
+                    const TexInternalFormat webGLFormat =
                         fba.Texture()->ImageInfoBase().WebGLFormat();
                     return (webGLFormat == LOCAL_GL_SRGB ||
                             webGLFormat == LOCAL_GL_SRGB_ALPHA) ?
                         JS::NumberValue(uint32_t(LOCAL_GL_SRGB)) :
                         JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
                 }
                 break;
 
@@ -1214,19 +1214,19 @@ WebGLContext::GetFramebufferAttachmentPa
                                           " type of depth-stencil attachments.");
                     return JS::NullValue();
                 }
 
                 if (!fba.IsComplete())
                     return JS::NumberValue(uint32_t(LOCAL_GL_NONE));
 
                 uint32_t ret = LOCAL_GL_NONE;
-                GLenum type = fba.Texture()->ImageInfoAt(fba.ImageTarget(),
-                                                         fba.MipLevel()).WebGLType();
-                switch (type) {
+                TexType type = fba.Texture()->ImageInfoAt(fba.ImageTarget(),
+                                                          fba.MipLevel()).WebGLType();
+                switch (type.get()) {
                 case LOCAL_GL_UNSIGNED_BYTE:
                 case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
                 case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
                 case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
                     ret = LOCAL_GL_UNSIGNED_NORMALIZED;
                     break;
                 case LOCAL_GL_FLOAT:
                 case LOCAL_GL_HALF_FLOAT_OES:
@@ -2404,25 +2404,25 @@ WebGLContext::RenderbufferStorage(GLenum
         break;
     case LOCAL_GL_SRGB8_ALPHA8_EXT:
         break;
     case LOCAL_GL_RGB16F:
     case LOCAL_GL_RGBA16F: {
         bool hasExtensions = IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float) &&
                              IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float);
         if (!hasExtensions)
-            return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", target);
+            return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
         break;
     }
     case LOCAL_GL_RGB32F:
     case LOCAL_GL_RGBA32F: {
         bool hasExtensions = IsExtensionEnabled(WebGLExtensionID::OES_texture_float) &&
                              IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float);
         if (!hasExtensions)
-            return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", target);
+            return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
         break;
     }
     default:
         return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
     }
 
     MakeContextCurrent();
 
@@ -4027,33 +4027,33 @@ BaseTypeAndSizeFromUniformType(GLenum uT
         default:
             return false;
     }
 
     return true;
 }
 
 
-WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum internalformat, GLenum type)
+WebGLTexelFormat mozilla::GetWebGLTexelFormat(TexInternalFormat internalformat, TexType type)
 {
     //
     // WEBGL_depth_texture
     if (internalformat == LOCAL_GL_DEPTH_COMPONENT) {
-        switch (type) {
+        switch (type.get()) {
             case LOCAL_GL_UNSIGNED_SHORT:
                 return WebGLTexelFormat::D16;
             case LOCAL_GL_UNSIGNED_INT:
                 return WebGLTexelFormat::D32;
         }
 
         MOZ_CRASH("Invalid WebGL texture format/type?");
     }
 
     if (internalformat == LOCAL_GL_DEPTH_STENCIL) {
-        switch (type) {
+        switch (type.get()) {
             case LOCAL_GL_UNSIGNED_INT_24_8_EXT:
                 return WebGLTexelFormat::D24S8;
         }
 
         MOZ_CRASH("Invalid WebGL texture format/type?");
     }
 
     if (internalformat == LOCAL_GL_DEPTH_COMPONENT16) {
@@ -4064,17 +4064,17 @@ WebGLTexelFormat mozilla::GetWebGLTexelF
         return WebGLTexelFormat::D32;
     }
 
     if (internalformat == LOCAL_GL_DEPTH24_STENCIL8) {
         return WebGLTexelFormat::D24S8;
     }
 
     if (type == LOCAL_GL_UNSIGNED_BYTE) {
-        switch (internalformat) {
+        switch (internalformat.get()) {
             case LOCAL_GL_RGBA:
             case LOCAL_GL_SRGB_ALPHA_EXT:
                 return WebGLTexelFormat::RGBA8;
             case LOCAL_GL_RGB:
             case LOCAL_GL_SRGB_EXT:
                 return WebGLTexelFormat::RGB8;
             case LOCAL_GL_ALPHA:
                 return WebGLTexelFormat::A8;
@@ -4084,17 +4084,17 @@ WebGLTexelFormat mozilla::GetWebGLTexelF
                 return WebGLTexelFormat::RA8;
         }
 
         MOZ_CRASH("Invalid WebGL texture format/type?");
     }
 
     if (type == LOCAL_GL_FLOAT) {
         // OES_texture_float
-        switch (internalformat) {
+        switch (internalformat.get()) {
             case LOCAL_GL_RGBA:
             case LOCAL_GL_RGBA32F:
                 return WebGLTexelFormat::RGBA32F;
             case LOCAL_GL_RGB:
             case LOCAL_GL_RGB32F:
                 return WebGLTexelFormat::RGB32F;
             case LOCAL_GL_ALPHA:
             case LOCAL_GL_ALPHA32F_ARB:
@@ -4105,17 +4105,17 @@ WebGLTexelFormat mozilla::GetWebGLTexelF
             case LOCAL_GL_LUMINANCE_ALPHA:
             case LOCAL_GL_LUMINANCE_ALPHA32F_ARB:
                 return WebGLTexelFormat::RA32F;
         }
 
         MOZ_CRASH("Invalid WebGL texture format/type?");
     } else if (type == LOCAL_GL_HALF_FLOAT_OES) {
         // OES_texture_half_float
-        switch (internalformat) {
+        switch (internalformat.get()) {
             case LOCAL_GL_RGBA:
             case LOCAL_GL_RGBA16F:
                 return WebGLTexelFormat::RGBA16F;
             case LOCAL_GL_RGB:
             case LOCAL_GL_RGB16F:
                 return WebGLTexelFormat::RGB16F;
             case LOCAL_GL_ALPHA:
             case LOCAL_GL_ALPHA16F_ARB:
@@ -4127,17 +4127,17 @@ WebGLTexelFormat mozilla::GetWebGLTexelF
             case LOCAL_GL_LUMINANCE_ALPHA16F_ARB:
                 return WebGLTexelFormat::RA16F;
             default:
                 MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
                 return WebGLTexelFormat::BadFormat;
         }
     }
 
-    switch (type) {
+    switch (type.get()) {
         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
            return WebGLTexelFormat::RGBA4444;
         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
            return WebGLTexelFormat::RGBA5551;
         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
            return WebGLTexelFormat::RGB565;
         default:
             MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -26,32 +26,32 @@
 
 #include "mozilla/dom/ScriptSettings.h"
 
 namespace mozilla {
 
 using namespace gl;
 
 bool
-IsGLDepthFormat(GLenum webGLFormat)
+IsGLDepthFormat(TexInternalFormat webGLFormat)
 {
     return (webGLFormat == LOCAL_GL_DEPTH_COMPONENT ||
             webGLFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
             webGLFormat == LOCAL_GL_DEPTH_COMPONENT32);
 }
 
 bool
-IsGLDepthStencilFormat(GLenum webGLFormat)
+IsGLDepthStencilFormat(TexInternalFormat webGLFormat)
 {
     return (webGLFormat == LOCAL_GL_DEPTH_STENCIL ||
             webGLFormat == LOCAL_GL_DEPTH24_STENCIL8);
 }
 
 bool
-FormatHasAlpha(GLenum webGLFormat)
+FormatHasAlpha(TexInternalFormat webGLFormat)
 {
     return webGLFormat == LOCAL_GL_RGBA ||
            webGLFormat == LOCAL_GL_LUMINANCE_ALPHA ||
            webGLFormat == LOCAL_GL_ALPHA ||
            webGLFormat == LOCAL_GL_RGBA4 ||
            webGLFormat == LOCAL_GL_RGB5_A1 ||
            webGLFormat == LOCAL_GL_SRGB_ALPHA;
 }
@@ -71,21 +71,21 @@ TexImageTargetToTexTarget(TexImageTarget
         return LOCAL_GL_TEXTURE_CUBE_MAP;
     default:
         MOZ_ASSERT(false, "Bad texture conversion");
         // Should be caught by the constructor for TexTarget
         return LOCAL_GL_NONE;
     }
 }
 
-GLComponents::GLComponents(GLenum format)
+GLComponents::GLComponents(TexInternalFormat format)
 {
     mComponents = 0;
 
-    switch (format) {
+    switch (format.get()) {
         case LOCAL_GL_RGBA:
         case LOCAL_GL_RGBA4:
         case LOCAL_GL_RGBA8:
         case LOCAL_GL_RGB5_A1:
         // Luminance + Alpha can be converted
         // to and from RGBA
         case LOCAL_GL_LUMINANCE_ALPHA:
             mComponents |= Components::Alpha;
@@ -113,153 +113,161 @@ GLComponents::GLComponents(GLenum format
 
 bool
 GLComponents::IsSubsetOf(const GLComponents& other) const
 {
     return (mComponents | other.mComponents) == other.mComponents;
 }
 
 /**
- * Convert WebGL/ES format and type into GL format and GL internal
+ * Convert WebGL/ES format and type into GL internal
  * format valid for underlying driver.
  */
 void
-DriverFormatsFromFormatAndType(GLContext* gl, GLenum webGLFormat, GLenum webGLType,
+DriverFormatsFromFormatAndType(GLContext* gl, TexInternalFormat webGLInternalFormat, TexType webGLType,
                                GLenum* out_driverInternalFormat, GLenum* out_driverFormat)
 {
-    MOZ_ASSERT(out_driverInternalFormat, "out_driverInternalFormat can't be nullptr.");
-    MOZ_ASSERT(out_driverFormat, "out_driverFormat can't be nullptr.");
-    if (!out_driverInternalFormat || !out_driverFormat)
-        return;
+    MOZ_ASSERT(out_driverInternalFormat);
+    MOZ_ASSERT(out_driverFormat);
 
     // ES2 requires that format == internalformat; floating-point is
     // indicated purely by the type that's loaded.  For desktop GL, we
     // have to specify a floating point internal format.
     if (gl->IsGLES()) {
-        *out_driverInternalFormat = webGLFormat;
-        *out_driverFormat = webGLFormat;
-
+        *out_driverFormat = *out_driverInternalFormat = webGLInternalFormat.get();
         return;
     }
 
-    GLenum format = webGLFormat;
     GLenum internalFormat = LOCAL_GL_NONE;
+    GLenum format = LOCAL_GL_NONE;
 
-    if (format == LOCAL_GL_DEPTH_COMPONENT) {
+    if (webGLInternalFormat == LOCAL_GL_DEPTH_COMPONENT) {
+        format = LOCAL_GL_DEPTH_COMPONENT;
         if (webGLType == LOCAL_GL_UNSIGNED_SHORT)
             internalFormat = LOCAL_GL_DEPTH_COMPONENT16;
         else if (webGLType == LOCAL_GL_UNSIGNED_INT)
             internalFormat = LOCAL_GL_DEPTH_COMPONENT32;
-    } else if (format == LOCAL_GL_DEPTH_STENCIL) {
+    } else if (webGLInternalFormat == LOCAL_GL_DEPTH_STENCIL) {
+        format = LOCAL_GL_DEPTH_STENCIL;
         if (webGLType == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
             internalFormat = LOCAL_GL_DEPTH24_STENCIL8;
     } else {
-        switch (webGLType) {
+        switch (webGLType.get()) {
         case LOCAL_GL_UNSIGNED_BYTE:
         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
-            internalFormat = format;
+            format = internalFormat = webGLInternalFormat.get();
             break;
 
         case LOCAL_GL_FLOAT:
-            switch (format) {
+            switch (webGLInternalFormat.get()) {
             case LOCAL_GL_RGBA:
+                format = LOCAL_GL_RGBA;
                 internalFormat = LOCAL_GL_RGBA32F;
                 break;
 
             case LOCAL_GL_RGB:
+                format = LOCAL_GL_RGB;
                 internalFormat = LOCAL_GL_RGB32F;
                 break;
 
             case LOCAL_GL_ALPHA:
+                format = LOCAL_GL_ALPHA;
                 internalFormat = LOCAL_GL_ALPHA32F_ARB;
                 break;
 
             case LOCAL_GL_LUMINANCE:
+                format = LOCAL_GL_LUMINANCE;
                 internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
                 break;
 
             case LOCAL_GL_LUMINANCE_ALPHA:
+                format = LOCAL_GL_LUMINANCE_ALPHA;
                 internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
                 break;
             }
             break;
 
         case LOCAL_GL_HALF_FLOAT_OES:
-            switch (format) {
+            switch (webGLInternalFormat.get()) {
             case LOCAL_GL_RGBA:
+                format = LOCAL_GL_RGBA;
                 internalFormat = LOCAL_GL_RGBA16F;
                 break;
 
             case LOCAL_GL_RGB:
+                format = LOCAL_GL_RGB;
                 internalFormat = LOCAL_GL_RGB16F;
                 break;
 
             case LOCAL_GL_ALPHA:
+                format = LOCAL_GL_ALPHA;
                 internalFormat = LOCAL_GL_ALPHA16F_ARB;
                 break;
 
             case LOCAL_GL_LUMINANCE:
+                format = LOCAL_GL_LUMINANCE;
                 internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
                 break;
 
             case LOCAL_GL_LUMINANCE_ALPHA:
+                format = LOCAL_GL_LUMINANCE_ALPHA;
                 internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
                 break;
             }
             break;
 
         default:
             break;
         }
 
         // Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
         // requires that format == internalformat, but GL will fail in this case.
         // GL requires:
         //      format  ->  internalformat
         //      GL_RGB      GL_SRGB_EXT
         //      GL_RGBA     GL_SRGB_ALPHA_EXT
-        switch (format) {
+        switch (webGLInternalFormat.get()) {
         case LOCAL_GL_SRGB:
-            internalFormat = format;
             format = LOCAL_GL_RGB;
+            internalFormat = LOCAL_GL_SRGB;
             break;
-
         case LOCAL_GL_SRGB_ALPHA:
-            internalFormat = format;
             format = LOCAL_GL_RGBA;
+            internalFormat = LOCAL_GL_SRGB_ALPHA;
             break;
         }
     }
 
-    MOZ_ASSERT(format != LOCAL_GL_NONE && internalFormat != LOCAL_GL_NONE,
+    MOZ_ASSERT(webGLInternalFormat != LOCAL_GL_NONE && internalFormat != LOCAL_GL_NONE,
                "Coding mistake -- bad format/type passed?");
 
     *out_driverInternalFormat = internalFormat;
     *out_driverFormat = format;
 }
 
 GLenum
-DriverTypeFromType(GLContext* gl, GLenum webGLType)
+DriverTypeFromType(GLContext* gl, TexType webGLType)
 {
+    GLenum type = webGLType.get();
+
     if (gl->IsGLES())
-        return webGLType;
+        return type;
 
     // convert type for half float if not on GLES2
-    GLenum type = webGLType;
     if (type == LOCAL_GL_HALF_FLOAT_OES) {
         if (gl->IsSupported(gl::GLFeature::texture_half_float)) {
             return LOCAL_GL_HALF_FLOAT;
         } else {
             MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
         }
     }
 
-    return webGLType;
+    return type;
 }
 
 void
 WebGLContext::GenerateWarning(const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
 
@@ -479,19 +487,19 @@ WebGLContext::EnumName(GLenum glenum)
 #undef XX
     }
 
     return "[Unknown enum name]";
 }
 
 
 bool
-WebGLContext::IsTextureFormatCompressed(GLenum format)
+WebGLContext::IsTextureFormatCompressed(TexInternalFormat format)
 {
-    switch (format) {
+    switch (format.get()) {
         case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
         case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
         case LOCAL_GL_ATC_RGB:
         case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
         case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
         case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -8,22 +8,22 @@
 
 #include "WebGLContext.h"
 #include "WebGLStrongTypes.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/BindingUtils.h"
 
 namespace mozilla {
 
-bool IsGLDepthFormat(GLenum webGLFormat);
-bool IsGLDepthStencilFormat(GLenum webGLFormat);
-bool FormatHasAlpha(GLenum webGLFormat);
-void DriverFormatsFromFormatAndType(gl::GLContext* gl, GLenum webGLFormat, GLenum webGLType,
+bool IsGLDepthFormat(TexInternalFormat webGLFormat);
+bool IsGLDepthStencilFormat(TexInternalFormat webGLFormat);
+bool FormatHasAlpha(TexInternalFormat webGLFormat);
+void DriverFormatsFromFormatAndType(gl::GLContext* gl, TexInternalFormat webGLFormat, TexType webGLType,
                                     GLenum* out_driverInternalFormat, GLenum* out_driverFormat);
-GLenum DriverTypeFromType(gl::GLContext* gl, GLenum webGLType);
+GLenum DriverTypeFromType(gl::GLContext* gl, TexType webGLType);
 
 // For use with the different texture calls, i.e.
 //   TexImage2D, CopyTex[Sub]Image2D, ...
 // that take a "target" parameter. This parameter is not always the same as
 // the texture binding location, like GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP.
 // For example, cube maps would pass GL_TEXTURE_CUBE_MAP_[POS|NEG]_[X|Y|Z]
 // instead of just GL_TEXTURE_CUBE_MAP.
 //
@@ -46,17 +46,17 @@ struct GLComponents
         Stencil = (1 << 4),
         Depth   = (1 << 5),
     };
 
     GLComponents()
         : mComponents(0)
     { }
 
-    explicit GLComponents(GLenum aFormat);
+    explicit GLComponents(TexInternalFormat aFormat);
 
     // Returns true iff other has all (or more) of
     // the components present in this GLComponents
     bool IsSubsetOf(const GLComponents& other) const;
 };
 
 template <typename WebGLObjectType>
 JS::Value
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -1034,36 +1034,31 @@ WebGLContext::ValidateTexSubImageSize(GL
 }
 
 /**
  * Return the bits per texel for format & type combination.
  * Assumes that format & type are a valid combination as checked with
  * ValidateTexImageFormatAndType().
  */
 uint32_t
-WebGLContext::GetBitsPerTexel(GLenum format, GLenum type)
+WebGLContext::GetBitsPerTexel(TexInternalFormat format, TexType type)
 {
-    // If there is no defined format or type, we're not taking up any memory
-    if (!format || !type) {
-        return 0;
-    }
-
     /* Known fixed-sized types */
     if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
         type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
         type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
     {
         return 16;
     }
 
     if (type == LOCAL_GL_UNSIGNED_INT_24_8)
         return 32;
 
     int bitsPerComponent = 0;
-    switch (type) {
+    switch (type.get()) {
     case LOCAL_GL_UNSIGNED_BYTE:
         bitsPerComponent = 8;
         break;
 
     case LOCAL_GL_HALF_FLOAT:
     case LOCAL_GL_HALF_FLOAT_OES:
     case LOCAL_GL_UNSIGNED_SHORT:
         bitsPerComponent = 16;
@@ -1074,17 +1069,17 @@ WebGLContext::GetBitsPerTexel(GLenum for
         bitsPerComponent = 32;
         break;
 
     default:
         MOZ_ASSERT(false, "Unhandled type.");
         break;
     }
 
-    switch (format) {
+    switch (format.get()) {
         // Uncompressed formats
     case LOCAL_GL_ALPHA:
     case LOCAL_GL_LUMINANCE:
     case LOCAL_GL_DEPTH_COMPONENT:
     case LOCAL_GL_DEPTH_STENCIL:
         return 1 * bitsPerComponent;
 
     case LOCAL_GL_LUMINANCE_ALPHA:
@@ -1304,17 +1299,17 @@ WebGLContext::ValidateCopyTexImage(GLenu
 
 /**
  * Test the gl(Copy|Compressed)?Tex[Sub]?Image[23]() parameters for errors.
  * Verifies each of the parameters against the WebGL standard and enabled extensions.
  */
 // TODO: Texture dims is here for future expansion in WebGL 2.0
 bool
 WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
-                               GLint level, GLint internalFormat,
+                               GLint level, GLenum internalFormat,
                                GLint xoffset, GLint yoffset, GLint zoffset,
                                GLint width, GLint height, GLint depth,
                                GLint border, GLenum format, GLenum type,
                                WebGLTexImageFunc func)
 {
     const char* info = InfoFrom(func);
 
     /* Check level */
@@ -1334,17 +1329,17 @@ WebGLContext::ValidateTexImage(GLuint di
         return false;
 
     /* WebGL and OpenGL ES 2.0 impose additional restrictions on the
      * combinations of format, internalFormat, and type that can be
      * used.  Formats and types that require additional extensions
      * (e.g., GL_FLOAT requires GL_OES_texture_float) are filtered
      * elsewhere.
      */
-    if ((GLint) format != internalFormat) {
+    if (format != internalFormat) {
         ErrorInvalidOperation("%s: format does not match internalformat", info);
         return false;
     }
 
     /* check internalFormat */
     // TODO: Not sure if this is a bit of over kill.
     if (BaseTexFormat(internalFormat) == LOCAL_GL_NONE) {
         MOZ_ASSERT(false);
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -60,54 +60,60 @@ bool
 WebGLFramebuffer::Attachment::IsDeleteRequested() const
 {
     return Texture() ? Texture()->IsDeleteRequested()
          : Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
          : false;
 }
 
 bool
+WebGLFramebuffer::Attachment::IsDefined() const
+{
+    return Renderbuffer() ||
+           (Texture() && Texture()->HasImageInfoAt(ImageTarget(), 0));
+}
+
+bool
 WebGLFramebuffer::Attachment::HasAlpha() const
 {
     MOZ_ASSERT(HasImage());
 
-    GLenum format = 0;
     if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
-        format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLFormat();
+        return FormatHasAlpha(Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLFormat());
     else if (Renderbuffer())
-        format = Renderbuffer()->InternalFormat();
-    return FormatHasAlpha(format);
+        return FormatHasAlpha(Renderbuffer()->InternalFormat());
+    else return false;
 }
 
 GLenum
 WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const
 {
     MOZ_ASSERT(attachment.IsDefined());
     MOZ_ASSERT(attachment.Texture() || attachment.Renderbuffer());
 
     if (attachment.Texture()) {
         const WebGLTexture& tex = *attachment.Texture();
         MOZ_ASSERT(tex.HasImageInfoAt(attachment.ImageTarget(), 0));
 
         const WebGLTexture::ImageInfo& imgInfo = tex.ImageInfoAt(attachment.ImageTarget(), 0);
-        return imgInfo.WebGLFormat();
+        return imgInfo.WebGLFormat().get();
     }
 
     if (attachment.Renderbuffer())
         return attachment.Renderbuffer()->InternalFormat();
 
     return LOCAL_GL_NONE;
 }
 
 bool
 WebGLFramebuffer::Attachment::IsReadableFloat() const
 {
     const WebGLTexture* tex = Texture();
     if (tex && tex->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
-        GLenum type = tex->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLType();
+        GLenum type = tex->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLType().get();
         switch (type) {
         case LOCAL_GL_FLOAT:
         case LOCAL_GL_HALF_FLOAT_OES:
             return true;
         }
         return false;
     }
 
@@ -317,17 +323,17 @@ WebGLFramebuffer::Attachment::IsComplete
     {
         return false;
     }
 
     if (Texture()) {
         MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
         const WebGLTexture::ImageInfo& imageInfo =
             Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
-        GLenum webGLFormat = imageInfo.WebGLFormat();
+        GLenum webGLFormat = imageInfo.WebGLFormat().get();
 
         if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
             return IsValidFBOTextureDepthFormat(webGLFormat);
 
         if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT)
             return false; // Textures can't have the correct format for stencil buffers
 
         if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -44,19 +44,17 @@ public:
         GLenum mAttachmentPoint;
         TexImageTarget mTexImageTarget;
         GLint mTexImageLevel;
         mutable bool mNeedsFinalize;
 
         explicit Attachment(GLenum aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
         ~Attachment();
 
-        bool IsDefined() const {
-            return Texture() || Renderbuffer();
-        }
+        bool IsDefined() const;
 
         bool IsDeleteRequested() const;
 
         bool HasAlpha() const;
         bool IsReadableFloat() const;
 
         void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
         void SetRenderbuffer(WebGLRenderbuffer* rb);
--- a/dom/canvas/WebGLStrongTypes.h
+++ b/dom/canvas/WebGLStrongTypes.h
@@ -12,47 +12,47 @@
 #include "mozilla/ArrayUtils.h"
 
 // Usage:
 // ===========
 //
 // To create a new type from a set of GLenums do the following:
 //
 //   STRONG_GLENUM_BEGIN(TypeName)
-//     Enum1,
-//     Enum2,
+//     STRONG_GLENUM_VALUE(ENUM1),
+//     STRONG_GLENUM_VALUE(ENUM2),
 //     ...
 //   STRONG_GLENUM_END()
 //
 // where TypeName is the name you want to give the type. Now simply use TypeName
-// instead of GLenum.
+// instead of GLenum. The enum values must be given without GL_ prefix.
 //
 // ~~~~~~~~~~~~~~~~
 // Important Notes:
 // ~~~~~~~~~~~~~~~~
 //
 // Boolean operators (==, !=) are provided in an effort to prevent some mistakes
 // when using constants. For example we want to make sure that GL_ENUM_X is
 // a valid value for the type in code like:
 //
-//   if (myNewType == LOCAL_GL_SOME_ENUM)
+//   if (myNewType == STRONG_GLENUM_VALUE(SOME_ENUM))
 //       ...
 //
-// The operators will assert that LOCAL_GL_SOME_ENUM is a value that myNewType
+// The operators will assert that STRONG_GLENUM_VALUE(SOME_ENUM) is a value that myNewType
 // can have.
 //
 // ----
 //
 // A get() method is provided to allow access to the underlying GLenum. This
 // method should ideally only be called when passing parameters to the gl->fXXXX
 // functions, and be used very minimally everywhere else.
 //
 // Definitely XXX - DO NOT DO - XXX:
 //
-//   if (myNewType.get() == LOCAL_GL_SOME_ENUM)
+//   if (myNewType.get() == STRONG_GLENUM_VALUE(SOME_ENUM))
 //       ...
 //
 // As that undermines the debug checks that were implemented in the ==, and !=
 // operators. If you see code like this it should be treated with suspicion.
 //
 // Background:
 // ===========
 //
@@ -72,81 +72,273 @@
 //   GL_TEXTURE_CUBE_MAP_POSITIVE_Y
 //   ...
 //
 // This subtle distinction has already led to many bugs in the texture code
 // because of invalid assumptions about what type goes where. The macro below
 // is an attempt at fixing this by providing a small wrapper around GLenum that
 // validates its values.
 //
-#ifdef DEBUG
+// Comparison between STRONG_GLENUM's vs. enum classes
+// ===================================================
+//
+// The present STRONG_GLENUM's differ from ordinary enum classes
+// in that they assert at runtime that their values are legal, and in that they
+// allow implicit conversion from integers to STRONG_GLENUM's but disallow
+// implicit conversion from STRONG_GLENUM's to integers (enum classes are the opposite).
+//
+// When to use GLenum's vs. STRONG_GLENUM's vs. enum classes
+// =========================================================
+//
+// Rule of thumb:
+// * For unchecked GLenum constants, such as WebGL method parameters that haven't been
+//   validated yet, use GLenum.
+// * For already-validated GLenum constants, use STRONG_GLENUM's.
+// * For custom constants that aren't GL enum values, use enum classes.
 
-template<size_t N>
-static bool
-IsValueInArr(GLenum value, const GLenum (&arr)[N])
+template<typename Details>
+class StrongGLenum MOZ_FINAL
 {
-    for (size_t i = 0; i < N; ++i) {
-        if (value == arr[i])
-            return true;
+private:
+    static const GLenum NonexistantGLenum = 0xdeaddead;
+
+    GLenum mValue;
+
+    static void AssertOnceThatEnumValuesAreSorted()
+    {
+#ifdef DEBUG
+        static bool alreadyChecked = false;
+        if (alreadyChecked) {
+            return;
+        }
+        for (size_t i = 1; i < Details::valuesCount(); i++) {
+            MOZ_ASSERT(Details::values()[i] > Details::values()[i - 1],
+                       "GLenum values should be sorted in ascending order");
+        }
+        alreadyChecked = true;
+#endif
     }
 
-    return false;
+public:
+    StrongGLenum(const StrongGLenum& other)
+        : mValue(other.mValue)
+    {
+        AssertOnceThatEnumValuesAreSorted();
+    }
+
+    StrongGLenum()
+#ifdef DEBUG
+        : mValue(NonexistantGLenum)
+#endif
+    {
+        AssertOnceThatEnumValuesAreSorted();
+    }
+
+    StrongGLenum(GLenum val)
+        : mValue(val)
+    {
+        AssertOnceThatEnumValuesAreSorted();
+        MOZ_ASSERT(IsValueLegal(mValue));
+    }
+
+    GLenum get() const {
+        MOZ_ASSERT(mValue != NonexistantGLenum);
+        return mValue;
+    }
+
+    bool operator==(const StrongGLenum& other) const {
+        return get() == other.get();
+    }
+
+    bool operator!=(const StrongGLenum& other) const {
+        return get() != other.get();
+    }
+
+    static bool IsValueLegal(GLenum value) {
+        if (value > UINT16_MAX) {
+            return false;
+        }
+        return std::binary_search(Details::values(),
+                                  Details::values() + Details::valuesCount(),
+                                  uint16_t(value));
+    }
+};
+
+template<typename Details>
+bool operator==(GLenum a, StrongGLenum<Details> b)
+{
+    return a == b.get();
 }
 
-#endif
+template<typename Details>
+bool operator!=(GLenum a, StrongGLenum<Details> b)
+{
+    return a != b.get();
+}
+
+template<typename Details>
+bool operator==(StrongGLenum<Details> a, GLenum b)
+{
+    return a.get() == b;
+}
 
-#define STRONG_GLENUM_BEGIN(NAME)                  \
-    class NAME {                                   \
-    private:                                       \
-        GLenum mValue;                             \
-    public:                                        \
-        MOZ_CONSTEXPR NAME(const NAME& other)      \
-            : mValue(other.mValue) { }             \
-                                                   \
-        bool operator==(const NAME& other) const { \
-            return mValue == other.mValue;         \
-        }                                          \
-                                                   \
-        bool operator!=(const NAME& other) const { \
-            return mValue != other.mValue;         \
-        }                                          \
-                                                   \
-        GLenum get() const {                       \
-            MOZ_ASSERT(mValue != LOCAL_GL_NONE);   \
-            return mValue;                         \
-        }                                          \
-                                                   \
-        NAME(GLenum val)                           \
-            : mValue(val)                          \
-        {                                          \
-            const GLenum validValues[] = {
+template<typename Details>
+bool operator!=(StrongGLenum<Details> a, GLenum b)
+{
+    return a.get() != b;
+}
+
+#define STRONG_GLENUM_BEGIN(NAME) \
+    const uint16_t NAME##Values[] = {
 
-#define STRONG_GLENUM_END()                        \
-            };                                     \
-            (void)validValues;                     \
-            MOZ_ASSERT(IsValueInArr(mValue, validValues)); \
-        }                                          \
-    };
+#define STRONG_GLENUM_VALUE(VALUE) LOCAL_GL_##VALUE
+
+#define STRONG_GLENUM_END(NAME) \
+    }; \
+    struct NAME##Details { \
+        static size_t valuesCount() { return MOZ_ARRAY_LENGTH(NAME##Values); } \
+        static const uint16_t* values() { return NAME##Values; } \
+    }; \
+    typedef StrongGLenum<NAME##Details> NAME;
 
 /******************************************************************************
  *  Add your types after this comment
  *****************************************************************************/
 
 STRONG_GLENUM_BEGIN(TexImageTarget)
-    LOCAL_GL_NONE,
-    LOCAL_GL_TEXTURE_2D,
-    LOCAL_GL_TEXTURE_3D,
-    LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X,
-    LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
-    LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
-    LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
-    LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-    LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
-STRONG_GLENUM_END()
+    STRONG_GLENUM_VALUE(NONE),
+    STRONG_GLENUM_VALUE(TEXTURE_2D),
+    STRONG_GLENUM_VALUE(TEXTURE_3D),
+    STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_X),
+    STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_X),
+    STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_Y),
+    STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Y),
+    STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_Z),
+    STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Z),
+STRONG_GLENUM_END(TexImageTarget)
 
 STRONG_GLENUM_BEGIN(TexTarget)
-    LOCAL_GL_NONE,
-    LOCAL_GL_TEXTURE_2D,
-    LOCAL_GL_TEXTURE_3D,
-    LOCAL_GL_TEXTURE_CUBE_MAP,
-STRONG_GLENUM_END()
+    STRONG_GLENUM_VALUE(NONE),
+    STRONG_GLENUM_VALUE(TEXTURE_2D),
+    STRONG_GLENUM_VALUE(TEXTURE_3D),
+    STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP),
+STRONG_GLENUM_END(TexTarget)
+
+STRONG_GLENUM_BEGIN(TexType)
+    STRONG_GLENUM_VALUE(NONE),
+    STRONG_GLENUM_VALUE(BYTE),
+    STRONG_GLENUM_VALUE(UNSIGNED_BYTE),
+    STRONG_GLENUM_VALUE(SHORT),
+    STRONG_GLENUM_VALUE(UNSIGNED_SHORT),
+    STRONG_GLENUM_VALUE(INT),
+    STRONG_GLENUM_VALUE(UNSIGNED_INT),
+    STRONG_GLENUM_VALUE(FLOAT),
+    STRONG_GLENUM_VALUE(HALF_FLOAT),
+    STRONG_GLENUM_VALUE(UNSIGNED_SHORT_4_4_4_4),
+    STRONG_GLENUM_VALUE(UNSIGNED_SHORT_5_5_5_1),
+    STRONG_GLENUM_VALUE(UNSIGNED_SHORT_5_6_5),
+    STRONG_GLENUM_VALUE(UNSIGNED_INT_2_10_10_10_REV),
+    STRONG_GLENUM_VALUE(UNSIGNED_INT_24_8),
+    STRONG_GLENUM_VALUE(UNSIGNED_INT_10F_11F_11F_REV),
+    STRONG_GLENUM_VALUE(UNSIGNED_INT_5_9_9_9_REV),
+    STRONG_GLENUM_VALUE(HALF_FLOAT_OES),
+    STRONG_GLENUM_VALUE(FLOAT_32_UNSIGNED_INT_24_8_REV),
+STRONG_GLENUM_END(TexType)
+
+STRONG_GLENUM_BEGIN(TexFormat)
+    STRONG_GLENUM_VALUE(NONE),
+    STRONG_GLENUM_VALUE(DEPTH_COMPONENT),
+    STRONG_GLENUM_VALUE(RED),
+    STRONG_GLENUM_VALUE(ALPHA),
+    STRONG_GLENUM_VALUE(RGB),
+    STRONG_GLENUM_VALUE(RGBA),
+    STRONG_GLENUM_VALUE(LUMINANCE),
+    STRONG_GLENUM_VALUE(LUMINANCE_ALPHA),
+    STRONG_GLENUM_VALUE(RG),
+    STRONG_GLENUM_VALUE(SRGB),
+    STRONG_GLENUM_VALUE(SRGB_ALPHA),
+    STRONG_GLENUM_VALUE(RG_INTEGER),
+    STRONG_GLENUM_VALUE(DEPTH_STENCIL),
+    STRONG_GLENUM_VALUE(RED_INTEGER),
+    STRONG_GLENUM_VALUE(RGB_INTEGER),
+    STRONG_GLENUM_VALUE(RGBA_INTEGER),
+STRONG_GLENUM_END(TexFormat)
+
+STRONG_GLENUM_BEGIN(TexInternalFormat)
+    STRONG_GLENUM_VALUE(NONE),
+    STRONG_GLENUM_VALUE(DEPTH_COMPONENT),
+    STRONG_GLENUM_VALUE(ALPHA),
+    STRONG_GLENUM_VALUE(RGB),
+    STRONG_GLENUM_VALUE(RGBA),
+    STRONG_GLENUM_VALUE(LUMINANCE),
+    STRONG_GLENUM_VALUE(LUMINANCE_ALPHA),
+    STRONG_GLENUM_VALUE(RGB8),
+    STRONG_GLENUM_VALUE(RGBA4),
+    STRONG_GLENUM_VALUE(RGB5_A1),
+    STRONG_GLENUM_VALUE(RGBA8),
+    STRONG_GLENUM_VALUE(RGB10_A2),
+    STRONG_GLENUM_VALUE(DEPTH_COMPONENT16),
+    STRONG_GLENUM_VALUE(DEPTH_COMPONENT24),
+    STRONG_GLENUM_VALUE(R8),
+    STRONG_GLENUM_VALUE(RG8),
+    STRONG_GLENUM_VALUE(R16F),
+    STRONG_GLENUM_VALUE(R32F),
+    STRONG_GLENUM_VALUE(RG16F),
+    STRONG_GLENUM_VALUE(RG32F),
+    STRONG_GLENUM_VALUE(R8I),
+    STRONG_GLENUM_VALUE(R8UI),
+    STRONG_GLENUM_VALUE(R16I),
+    STRONG_GLENUM_VALUE(R16UI),
+    STRONG_GLENUM_VALUE(R32I),
+    STRONG_GLENUM_VALUE(R32UI),
+    STRONG_GLENUM_VALUE(RG8I),
+    STRONG_GLENUM_VALUE(RG8UI),
+    STRONG_GLENUM_VALUE(RG16I),
+    STRONG_GLENUM_VALUE(RG16UI),
+    STRONG_GLENUM_VALUE(RG32I),
+    STRONG_GLENUM_VALUE(RG32UI),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGB_S3TC_DXT1_EXT),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT1_EXT),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT3_EXT),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT5_EXT),
+    STRONG_GLENUM_VALUE(DEPTH_STENCIL),
+    STRONG_GLENUM_VALUE(ATC_RGBA_INTERPOLATED_ALPHA),
+    STRONG_GLENUM_VALUE(RGBA32F),
+    STRONG_GLENUM_VALUE(RGB32F),
+    STRONG_GLENUM_VALUE(RGBA16F),
+    STRONG_GLENUM_VALUE(RGB16F),
+    STRONG_GLENUM_VALUE(DEPTH24_STENCIL8),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGB_PVRTC_4BPPV1),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGB_PVRTC_2BPPV1),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGBA_PVRTC_4BPPV1),
+    STRONG_GLENUM_VALUE(COMPRESSED_RGBA_PVRTC_2BPPV1),
+    STRONG_GLENUM_VALUE(R11F_G11F_B10F),
+    STRONG_GLENUM_VALUE(RGB9_E5),
+    STRONG_GLENUM_VALUE(SRGB),
+    STRONG_GLENUM_VALUE(SRGB8),
+    STRONG_GLENUM_VALUE(SRGB_ALPHA),
+    STRONG_GLENUM_VALUE(SRGB8_ALPHA8),
+    STRONG_GLENUM_VALUE(ATC_RGB),
+    STRONG_GLENUM_VALUE(ATC_RGBA_EXPLICIT_ALPHA),
+    STRONG_GLENUM_VALUE(DEPTH_COMPONENT32F),
+    STRONG_GLENUM_VALUE(DEPTH32F_STENCIL8),
+    STRONG_GLENUM_VALUE(RGB565),
+    STRONG_GLENUM_VALUE(ETC1_RGB8_OES),
+    STRONG_GLENUM_VALUE(RGBA32UI),
+    STRONG_GLENUM_VALUE(RGB32UI),
+    STRONG_GLENUM_VALUE(RGBA16UI),
+    STRONG_GLENUM_VALUE(RGB16UI),
+    STRONG_GLENUM_VALUE(RGBA8UI),
+    STRONG_GLENUM_VALUE(RGB8UI),
+    STRONG_GLENUM_VALUE(RGBA32I),
+    STRONG_GLENUM_VALUE(RGB32I),
+    STRONG_GLENUM_VALUE(RGBA16I),
+    STRONG_GLENUM_VALUE(RGB16I),
+    STRONG_GLENUM_VALUE(RGBA8I),
+    STRONG_GLENUM_VALUE(RGB8I),
+    STRONG_GLENUM_VALUE(R8_SNORM),
+    STRONG_GLENUM_VALUE(RG8_SNORM),
+    STRONG_GLENUM_VALUE(RGB8_SNORM),
+    STRONG_GLENUM_VALUE(RGBA8_SNORM),
+    STRONG_GLENUM_VALUE(RGB10_A2UI),
+STRONG_GLENUM_END(TexInternalFormat)
 
 #endif
--- a/dom/canvas/WebGLTexture.cpp
+++ b/dom/canvas/WebGLTexture.cpp
@@ -133,17 +133,17 @@ WebGLTexture::Bind(TexTarget aTexTarget)
         if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP && !mContext->gl->IsGLES())
             mContext->gl->fTexParameteri(aTexTarget.get(), LOCAL_GL_TEXTURE_WRAP_R, LOCAL_GL_CLAMP_TO_EDGE);
     }
 }
 
 void
 WebGLTexture::SetImageInfo(TexImageTarget aTexImageTarget, GLint aLevel,
                   GLsizei aWidth, GLsizei aHeight,
-                  GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus)
+                  TexInternalFormat aFormat, TexType aType, WebGLImageDataStatus aStatus)
 {
     MOZ_ASSERT(TexImageTargetToTexTarget(aTexImageTarget) == mTarget);
     if (TexImageTargetToTexTarget(aTexImageTarget) != mTarget)
         return;
 
     EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
 
     ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aFormat, aType, aStatus);
@@ -454,30 +454,30 @@ ClearByMask(WebGLContext* context, GLbit
     context->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
     return true;
 }
 
 // `mask` from glClear.
 static bool
 ClearWithTempFB(WebGLContext* context, GLuint tex,
                 TexImageTarget texImageTarget, GLint level,
-                GLenum baseInternalFormat,
+                TexInternalFormat baseInternalFormat,
                 GLsizei width, GLsizei height)
 {
     if (texImageTarget != LOCAL_GL_TEXTURE_2D)
         return false;
 
     gl::GLContext* gl = context->GL();
     MOZ_ASSERT(gl->IsCurrent());
 
     gl::ScopedFramebuffer fb(gl);
     gl::ScopedBindFramebuffer autoFB(gl, fb.FB());
     GLbitfield mask = 0;
 
-    switch (baseInternalFormat) {
+    switch (baseInternalFormat.get()) {
     case LOCAL_GL_LUMINANCE:
     case LOCAL_GL_LUMINANCE_ALPHA:
     case LOCAL_GL_ALPHA:
     case LOCAL_GL_RGB:
     case LOCAL_GL_RGBA:
     case LOCAL_GL_BGR:
     case LOCAL_GL_BGRA:
         mask = LOCAL_GL_COLOR_BUFFER_BIT;
@@ -537,18 +537,18 @@ void
 WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint level)
 {
     const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
     MOZ_ASSERT(imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
 
     mContext->MakeContextCurrent();
 
     // Try to clear with glCLear.
-    GLenum format = imageInfo.mWebGLFormat;
-    GLenum type = imageInfo.mWebGLType;
+    TexInternalFormat format = imageInfo.mWebGLFormat;
+    TexType type = imageInfo.mWebGLType;
     WebGLTexelFormat texelformat = GetWebGLTexelFormat(format, type);
 
     bool cleared = ClearWithTempFB(mContext, GLName(),
                                    imageTarget, level,
                                    format, imageInfo.mHeight, imageInfo.mWidth);
     if (cleared) {
         SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
         return;
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -69,18 +69,18 @@ public:
         ImageInfo()
             : mWebGLFormat(LOCAL_GL_NONE)
             , mWebGLType(LOCAL_GL_NONE)
             , mImageDataStatus(WebGLImageDataStatus::NoImageData)
         {}
 
         ImageInfo(GLsizei width,
                   GLsizei height,
-                  GLenum webGLFormat,
-                  GLenum webGLType,
+                  TexInternalFormat webGLFormat,
+                  TexType webGLType,
                   WebGLImageDataStatus status)
             : WebGLRectangleObject(width, height)
             , mWebGLFormat(webGLFormat)
             , mWebGLType(webGLType)
             , mImageDataStatus(status)
         {
             // shouldn't use this constructor to construct a null ImageInfo
             MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
@@ -109,26 +109,26 @@ public:
         bool HasUninitializedImageData() const {
             return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
         }
         int64_t MemoryUsage() const;
         /*! This is the format passed from JS to WebGL.
          * It can be converted to a value to be passed to driver with
          * DriverFormatsFromFormatAndType().
          */
-        GLenum WebGLFormat() const { return mWebGLFormat; }
+        TexInternalFormat WebGLFormat() const { return mWebGLFormat; }
         /*! This is the type passed from JS to WebGL.
          * It can be converted to a value to be passed to driver with
          * DriverTypeFromType().
          */
-        GLenum WebGLType() const { return mWebGLType; }
+        TexType WebGLType() const { return mWebGLType; }
 
     protected:
-        GLenum mWebGLFormat; //!< This is the WebGL/GLES format
-        GLenum mWebGLType;   //!< This is the WebGL/GLES type
+        TexInternalFormat mWebGLFormat; //!< This is the WebGL/GLES format
+        TexType mWebGLType;   //!< This is the WebGL/GLES type
         WebGLImageDataStatus mImageDataStatus;
 
         friend class WebGLTexture;
     };
 
 private:
     static size_t FaceForTarget(TexImageTarget texImageTarget) {
         if (texImageTarget == LOCAL_GL_TEXTURE_2D)
@@ -220,17 +220,17 @@ protected:
     bool DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const;
 
 public:
 
     void Bind(TexTarget aTexTarget);
 
     void SetImageInfo(TexImageTarget aTarget, GLint aLevel,
                       GLsizei aWidth, GLsizei aHeight,
-                      GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus);
+                      TexInternalFormat aFormat, TexType aType, WebGLImageDataStatus aStatus);
 
     void SetMinFilter(GLenum aMinFilter) {
         mMinFilter = aMinFilter;
         SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
     }
     void SetMagFilter(GLenum aMagFilter) {
         mMagFilter = aMagFilter;
         SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
--- a/dom/canvas/test/test_canvas_path.html
+++ b/dom/canvas/test/test_canvas_path.html
@@ -373,16 +373,18 @@ function test_addpath_canvas() {
   isPixel(ctx, 50, 50, [255, 255, 0, 255], 0);
   isPixel(ctx, 150, 150, [0, 0, 0, 0], 0);
 
   var p5 = new Path2D();
   p5.rect(0,0,100,100);
   shouldThrow(ctx, "p5.addPath(null, m)");
   shouldThrow(ctx, "p5.addPath([], m)");
   shouldThrow(ctx, "p5.addPath({}, m)");
+
+  p5 = p5.addPath(p5);
 }
 </script>
 
 <script>
 
 function runTests() {
  try {
   test_drawClipPath_canvas();
--- a/dom/interfaces/base/nsIContentPrefService2.idl
+++ b/dom/interfaces/base/nsIContentPrefService2.idl
@@ -62,17 +62,17 @@ interface nsIContentPref;
  * The methods of callback objects are always called asynchronously.
  *
  * Observers are called after callbacks are called, but they are called in the
  * same turn of the event loop as callbacks.
  *
  * See nsIContentPrefCallback2 below for more information about callbacks.
  */
 
-[scriptable, uuid(f2507add-dc39-48e0-9147-e0270376148b)]
+[scriptable, uuid(bed98666-d995-470f-bebd-62476d318576)]
 interface nsIContentPrefService2 : nsISupports
 {
   /**
    * Gets all the preferences with the given name.
    *
    * @param name      The preferences' name.
    * @param context   The private-browsing context, if any.
    * @param callback  handleResult is called once for each preference unless
@@ -295,16 +295,27 @@ interface nsIContentPrefService2 : nsISu
    *
    * @param context   The private-browsing context, if any.
    * @param callback  handleCompletion is called when the operation completes.
    */
   void removeAllDomains(in nsILoadContext context,
                         [optional] in nsIContentPrefCallback2 callback);
 
   /**
+   * Removes all non-global preferences created after and including |since|.
+   *
+   * @param since     Timestamp in milliseconds.
+   * @param context   The private-browsing context, if any.
+   * @param callback  handleCompletion is called when the operation completes.
+   */
+  void removeAllDomainsSince(in unsigned long long since,
+                             in nsILoadContext context,
+                             [optional] in nsIContentPrefCallback2 callback);
+
+  /**
    * Removes all global preferences -- in other words, all preferences that have
    * no domain.
    *
    * @param context   The private-browsing context, if any.
    * @param callback  handleCompletion is called when the operation completes.
    */
   void removeAllGlobals(in nsILoadContext context,
                         [optional] in nsIContentPrefCallback2 callback);
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -736,17 +736,17 @@ NetworkManager.prototype = {
     this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP]   = DEFAULT_WIFI_DHCPSERVER_ENDIP;
 
 #ifdef MOZ_B2G_RIL
     this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
       libcutils.property_get("ro.tethering.dun_required") === "1";
 #endif
   },
 
-  _requestCount: 0,
+  _usbTetheringRequestCount: 0,
 
   handle: function(aName, aResult) {
     switch(aName) {
       case SETTINGS_DATA_DEFAULT_SERVICE_ID:
         this._dataDefaultServiceId = aResult || 0;
         debug("'_dataDefaultServiceId' is now " + this._dataDefaultServiceId);
         break;
       case SETTINGS_USB_ENABLED:
@@ -771,22 +771,27 @@ NetworkManager.prototype = {
 
         if (this._usbTetheringSettingsToRead.length) {
           debug("We haven't read completely the usb Tethering data from settings db.");
           break;
         }
 
         if (this._oldUsbTetheringEnabledState === this.tetheringSettings[SETTINGS_USB_ENABLED]) {
           debug("No changes for SETTINGS_USB_ENABLED flag. Nothing to do.");
+          this.handlePendingWifiTetheringRequest();
           break;
         }
 
-        this._requestCount++;
-        if (this._requestCount === 1) {
-          this.handleUSBTetheringToggle(aResult);
+        this._usbTetheringRequestCount++;
+        if (this._usbTetheringRequestCount === 1) {
+          if (this._wifiTetheringRequestOngoing) {
+            debug('USB tethering request is blocked by ongoing wifi tethering request.');
+          } else {
+            this.handleLastUsbTetheringRequest();
+          }
         }
         break;
     };
   },
 
   handleError: function(aErrorMessage) {
     debug("There was an error while reading Tethering settings.");
     this.tetheringSettings = {};
@@ -814,34 +819,41 @@ NetworkManager.prototype = {
 
   _usbTetheringSettingsToRead: [],
 
   _oldUsbTetheringEnabledState: null,
 
   // External and internal interface name.
   _tetheringInterface: null,
 
-  handleLastRequest: function() {
-    if (this._requestCount === 1) {
-      this._requestCount = 0;
+  handleLastUsbTetheringRequest: function() {
+    debug('handleLastUsbTetheringRequest... ' + this._usbTetheringRequestCount);
+
+    if (this._usbTetheringRequestCount === 0) {
       if (this.wantConnectionEvent) {
         if (this.tetheringSettings[SETTINGS_USB_ENABLED]) {
           this.wantConnectionEvent.call(this);
         }
         this.wantConnectionEvent = null;
       }
+      this.handlePendingWifiTetheringRequest();
       return;
     }
 
-    if (this._requestCount > 1) {
-      // Set this._requestCount to 1 to prevent from subsequent usb tethering toggles
-      // triggering |handleUSBTetheringToggle|.
-      this._requestCount = 1;
-      this.handleUSBTetheringToggle(this.tetheringSettings[SETTINGS_USB_ENABLED]);
-      this.wantConnectionEvent = null;
+    // Cancel the accumlated count to 1 since we only care about the
+    // last state.
+    this._usbTetheringRequestCount = 1;
+    this.handleUSBTetheringToggle(this.tetheringSettings[SETTINGS_USB_ENABLED]);
+    this.wantConnectionEvent = null;
+  },
+
+  handlePendingWifiTetheringRequest: function() {
+    if (this._pendingWifiTetheringRequestArgs) {
+      this.setWifiTethering.apply(this, this._pendingWifiTetheringRequestArgs);
+      this._pendingWifiTetheringRequestArgs = null;
     }
   },
 
 #ifdef MOZ_B2G_RIL
   dunConnectTimer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
   /**
    * Callback when dun connection fails to connect within timeout.
    */
@@ -927,24 +939,26 @@ NetworkManager.prototype = {
 #endif
 
   handleUSBTetheringToggle: function(enable) {
     debug("handleUSBTetheringToggle: " + enable);
     if (enable &&
         (this._usbTetheringAction === TETHERING_STATE_ONGOING ||
          this._usbTetheringAction === TETHERING_STATE_ACTIVE)) {
       debug("Usb tethering already connecting/connected.");
-      this._requestCount = 0;
+      this._usbTetheringRequestCount = 0;
+      this.handlePendingWifiTetheringRequest();
       return;
     }
 
     if (!enable &&
         this._usbTetheringAction === TETHERING_STATE_IDLE) {
       debug("Usb tethering already disconnected.");
-      this._requestCount = 0;
+      this._usbTetheringRequestCount = 0;
+      this.handlePendingWifiTetheringRequest();
       return;
     }
 
     if (!enable) {
       this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
       gNetworkService.enableUsbRndis(false, this.enableUsbRndisResult.bind(this));
       return;
     }
@@ -1029,52 +1043,74 @@ NetworkManager.prototype = {
       let settingsLock = gSettingsService.createLock();
       // Disable wifi tethering with a useful error message for the user.
       settingsLock.set("tethering.wifi.enabled", false, null, msg);
     }
 
     debug("setWifiTethering: " + (msg ? msg : "success"));
 
     if (callback) {
-      callback.wifiTetheringEnabledChange(msg);
+      // Callback asynchronously to avoid netsted toggling.
+      Services.tm.currentThread.dispatch(() => {
+        callback.wifiTetheringEnabledChange(msg);
+      }, Ci.nsIThread.DISPATCH_NORMAL);
     }
   },
 
+  _wifiTetheringRequestOngoing: false,
   enableWifiTethering: function(enable, config, callback) {
     // Fill in config's required fields.
     config.ifname         = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
     config.internalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
     config.externalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface;
 
+    this._wifiTetheringRequestOngoing = true;
     gNetworkService.setWifiTethering(enable, config, (function(error) {
 #ifdef MOZ_B2G_RIL
       // Disconnect dun on error or when wifi tethering is disabled.
       if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
           (!enable || error)) {
         this.handleDunConnection(false);
       }
 #endif
       let resetSettings = error;
+      debug('gNetworkService.setWifiTethering finished');
       this.notifyError(resetSettings, callback, error);
+      this._wifiTetheringRequestOngoing = false;
+      if (this._usbTetheringRequestCount > 0) {
+        debug('Perform pending USB tethering requests.');
+        this.handleLastUsbTetheringRequest();
+      }
     }).bind(this));
   },
 
+  _pendingWifiTetheringRequestArgs: null,
   // Enable/disable WiFi tethering by sending commands to netd.
   setWifiTethering: function(enable, network, config, callback) {
     debug("setWifiTethering: " + enable);
     if (!network) {
       this.notifyError(true, callback, "invalid network information");
       return;
     }
 
     if (!config) {
       this.notifyError(true, callback, "invalid configuration");
       return;
     }
 
+    if (this._usbTetheringRequestCount > 0) {
+      // If there's still pending usb tethering request, save
+      // the request params and redo |setWifiTethering| on
+      // usb tethering task complete.
+      debug('USB tethering request is being processed. Queue this wifi tethering request.');
+      this._pendingWifiTetheringRequestArgs = Array.prototype.slice.call(arguments);
+      debug('Pending args: ' + JSON.stringify(this._pendingWifiTetheringRequestArgs));
+      return;
+    }
+
     if (!enable) {
       this.enableWifiTethering(false, config, callback);
       return;
     }
 
     this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = network.name;
 
 #ifdef MOZ_B2G_RIL
@@ -1138,30 +1174,34 @@ NetworkManager.prototype = {
       // just use the internal interface in settings.
       if (enable) {
         this._tetheringInterface[TETHERING_TYPE_USB].internalInterface = this.getUsbInterface();
       }
       this.setUSBTethering(enable,
                            this._tetheringInterface[TETHERING_TYPE_USB],
                            this.usbTetheringResultReport.bind(this, enable));
     } else {
-      this.usbTetheringResultReport("Failed to set usb function");
+      this.usbTetheringResultReport(enable, "enableUsbRndisResult failure");
       throw new Error("failed to set USB Function to adb");
     }
   },
 
   usbTetheringResultReport: function(enable, error) {
+    this._usbTetheringRequestCount--;
+
     let settingsLock = gSettingsService.createLock();
 
+    debug('usbTetheringResultReport callback. enable: ' + enable + ', error: ' + error);
+
     // Disable tethering settings when fail to enable it.
     if (error) {
       this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
       settingsLock.set("tethering.usb.enabled", false, null);
       // Skip others request when we found an error.
-      this._requestCount = 0;
+      this._usbTetheringRequestCount = 0;
       this._usbTetheringAction = TETHERING_STATE_IDLE;
 #ifdef MOZ_B2G_RIL
       if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
         this.handleDunConnection(false);
       }
 #endif
     } else {
       if (enable) {
@@ -1169,17 +1209,18 @@ NetworkManager.prototype = {
       } else {
         this._usbTetheringAction = TETHERING_STATE_IDLE;
 #ifdef MOZ_B2G_RIL
         if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
           this.handleDunConnection(false);
         }
 #endif
       }
-      this.handleLastRequest();
+
+      this.handleLastUsbTetheringRequest();
     }
   },
 
   onConnectionChangedReport: function(success, externalIfname) {
     debug("onConnectionChangedReport result: success " + success);
 
     if (success) {
       // Update the external interface.
--- a/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
+++ b/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
@@ -9368,2033 +9368,2035 @@ 16013,16014c21810
 < cent/AR
 ---
 > cent/ARM
 16098,16099c21894
 < chain's
 < chain/UGDS
 ---
 > chain/UGDSM
-16231,16232c22026
+16200a21996
+> charcuterie
+16231,16232c22027
 < charter's
 < charter/ASGD
 ---
 > charter/ASGDM
-16277c22071
+16277c22072
 < check/AGMDS
 ---
 > check/AGMDSU
-16327c22121
+16327c22122
 < chemistry/M
 ---
 > chemistry/MS
-16372c22166
+16372c22167
 < chickenshit/S!
 ---
 > chickenshit/SM!
-16404c22198
+16404c22199
 < children
 ---
 > children/M
-16488d22281
+16488d22282
 < chlorophyl/M
-16629,16630c22422
+16629,16630c22423
 < cider's
 < cider/S
 ---
 > cider/MS
-16651,16652c22443,22444
+16651,16652c22444,22445
 < cipher's
 < cipher/CGDS
 ---
 > cipher/CGDSM
 > ciphertext/S
-16702,16703c22494
+16702,16703c22495
 < cite's
 < cite/IAGSD
 ---
 > cite/IAGSDM
-16733,16735c22524
+16733,16735c22525
 < claim's
 < claim/CKEAGDS
 < claimable
 ---
 > claim/CKEAGDSMB
-16783,16784c22572
+16783,16784c22573
 < clasp's
 < clasp/UGDS
 ---
 > clasp/UGDSM
-16794,16796c22582
+16794,16796c22583
 < classified's
 < classified/U
 < classifieds
 ---
 > classified/MSU
-16918,16919c22704
+16918,16919c22705
 < cloak's
 < cloak/USDG
 ---
 > cloak/USDGM
-16930,16931c22715
+16930,16931c22716
 < clog's
 < clog/US
 ---
 > clog/USM
-16944,16946c22728
+16944,16946c22729
 < close's
 < close/EIGTSD
 < closeable
 ---
 > close/EIGTSDMB
-17072d22853
+17072d22854
 < cocain/M
-17102,17103c22883
+17102,17103c22884
 < cocksucker's
 < cocksucker/S!
 ---
 > cocksucker/SM!
-17117,17118c22897
+17117,17118c22898
 < code's
 < code/CAGDS
 ---
 > code/CAGDSM
-17195,17196c22974
+17195,17196c22975
 < coil's/A
 < coil/UADGS
 ---
 > coil/UADGSM
-17245,17246c23023
+17245,17246c23024
 < collect's
 < collect/ASGVD
 ---
 > collect/ASGVDM
-17301a23079,23080
+17301a23080,23081
 > colonoscope/SM
 > colonoscopy/SM
-17304,17305c23083
+17304,17305c23084
 < color's
 < color/AEGDS
 ---
 > color/AEGDSM
-17311,17313c23089
+17311,17313c23090
 < colored's
 < colored/U
 < coloreds
 ---
 > colored/MSU
-17351,17352c23127
+17351,17352c23128
 < combine's
 < combine/ADSG
 ---
 > combine/ADSGM
-17371c23146
+17371c23147
 < comer's
 ---
 > comer/M
-17376,17377c23151
+17376,17377c23152
 < comfit's
 < comfit/ES
 ---
 > comfit/ESM
-17412c23186
+17412c23187
 < comment/GSMDR
 ---
 > comment/GSMDRZ
-17428,17429c23202
+17428,17429c23203
 < commission's
 < commission/ACGSD
 ---
 > commission/ACGSDM
-17442,17443c23215
+17442,17443c23216
 < commode's
 < commode/EIS
 ---
 > commode/EISM
-17447,17448c23219
+17447,17448c23220
 < common's
 < common/UPRYT
 ---
 > common/UPRYTM
-17537,17538c23308
+17537,17538c23309
 < compilation's
 < compilation/AS
 ---
 > compilation/ASM
-17597,17598c23367
+17597,17598c23368
 < compress's
 < compress/CGVDS
 ---
 > compress/CGVDSM
-17657,17658c23426
+17657,17658c23427
 < concert's
 < concert/ESDG
 ---
 > concert/ESDGM
-17719,17720c23487
+17719,17720c23488
 < condition's
 < condition/AGSD
 ---
 > condition/AGSDM
-17755c23522
+17755c23523
 < confer/S
 ---
 > confer/SB
-17800a23568
+17800a23569
 > conformant
-17986,17987c23754
+17986,17987c23755
 < construct's
 < construct/CADVGS
 ---
 > construct/CADVGSM
-17991,17992c23758
+17991,17992c23759
 < constructionist's
 < constructionist/CS
 ---
 > constructionist/CSM
-18122,18123c23888
+18122,18123c23889
 < control's
 < control/CS
 ---
 > control/CSM
-18151d23915
+18151d23916
 < convenor/S
-18169,18170c23933
+18169,18170c23934
 < convert's
 < convert/AGSD
 ---
 > convert/AGSDM
-18199,18200c23962
+18199,18200c23963
 < cook's
 < cook/ADGS
 ---
 > cook/ADGSM
-18206c23968
+18206c23969
 < cookie/M
 ---
 > cookie/SM
-18294,18295c24056
+18294,18295c24057
 < cork's
 < cork/UDGS
 ---
 > cork/UDGSM
-18375a24137,24138
+18375a24138,24139
 > corrigibility/IM
 > corrigible/I
-18389a24153
+18389a24154
 > corruptibly/I
-18467a24232
+18467a24233
 > could've
-18487,18488c24252
+18487,18488c24253
 < countenance's
 < countenance/EGDS
 ---
 > countenance/EGDSM
-18542,18543c24306
+18542,18543c24307
 < coup's
 < coup/AS
 ---
 > coup/ASM
-18545,18546c24308
+18545,18546c24309
 < couple's
 < couple/CUDSG
 ---
 > couple/CUDSGM
-18581,18582c24343
+18581,18582c24344
 < cover's
 < cover/AEUGDS
 ---
 > cover/AEUGDSM
-18585,18586c24346
+18585,18586c24347
 < covering's
 < coverings
 ---
 > covering/MS
-18739,18740c24499
+18739,18740c24500
 < creation's/K
 < creation/ASM
 ---
 > creation/ASMK
-18816a24576
+18816a24577
 > crimeware/M
-18880,18881c24640
+18880,18881c24641
 < cross's
 < cross/AUGTSD
 ---
 > cross/AUGTSDM
-18925a24685,24686
+18925a24686,24687
 > crowdfunded
 > crowdfunding
-18972,18973c24733
+18972,18973c24734
 < crust's
 < crust/ISDG
 ---
 > crust/ISDGM
-18988,18989c24748
+18988,18989c24749
 < crypt's
 < crypt/CS
 ---
 > crypt/CSM
-18999a24759
+18999a24760
 > cryptologist/MS
-19000a24761
+19000a24762
 > cryptosystem/S
-19035a24797
+19035a24798
 > cul-de-sac
-19104,19105c24866
+19104,19105c24867
 < cure's
 < cure/KZGBDRS
 ---
 > cure/KZGBDRSM
-19119,19120c24880
+19119,19120c24881
 < curl's
 < curl/UDGS
 ---
 > curl/UDGSM
-19131,19133c24891
+19131,19133c24892
 < current's
 < current/FAY
 < currents
 ---
 > current/FAYSM
-19142,19143c24900
+19142,19143c24901
 < cursive's
 < cursive/EAY
 ---
 > cursive/EAYM
-19167,19168c24924
+19167,19168c24925
 < cuss's
 < cuss/FEGSD
 ---
 > cuss/FEGSDM
-19246c25002
+19246c25003
 < cysteine
 ---
 > cysteine/M
-19536a25293
+19536a25294
 > decertify/DSGNX
-19935a25693
+19935a25694
 > dequeue/DSG
-19999a25758
+19999a25759
 > designated/U
-20196,20197c25955,25956
+20196,20197c25956,25957
 < dialog/SM
 < dialogue/SM
 ---
 > dialog/SMGD
 > dialogue/SMRGD
-20220a25980
+20220a25981
 > diatomaceous
-20481a26242
+20481a26243
 > disclose/DSG
-20633a26395
+20633a26396
 > dissentious
-20695,20696c26457
+20695,20696c26458
 < district's
 < district/AS
 ---
 > district/ASM
-20768c26529
+20768c26530
 < djinn's
 ---
 > djinn/M
-20830c26591
+20830c26592
 < dogie/M
 ---
 > dogie/SM
-20850,20851c26611
+20850,20851c26612
 < dole's
 < dole/FGDS
 ---
 > dole/FGDSM
-20895a26656
+20895a26657
 > donator/MS
-20918,20919c26679
+20918,20919c26680
 < door's
 < door/IS
 ---
 > door/ISM
-20975,20976c26735
+20975,20976c26736
 < double's
 < double/ADSG
 ---
 > double/ADSGM
-21067,21068c26826
+21067,21068c26827
 < draft's
 < draft/ASDG
 ---
 > draft/ASDGM
-21282,21283c27040
+21282,21283c27041
 < duct's
 < duct/CIFDG
 ---
 > duct/CIFDGM
-21291,21292c27048
+21291,21292c27049
 < due's
 < due/IS
 ---
 > due/ISM
-21355,21356c27111
+21355,21356c27112
 < duplicate's
 < duplicate/AGNDS
 ---
 > duplicate/AGNDSM
-21367a27123
+21367a27124
 > durian/SM
-21468,21469c27224
+21468,21469c27225
 < earth's
 < earth/UDYG
 ---
 > earth/UDYGM
-21523,21524c27278
+21523,21524c27279
 < echo's
 < echo/ADG
 ---
 > echo/ADGM
-21587,21588c27341
+21587,21588c27342
 < edit's
 < edit/ADGS
 ---
 > edit/ADGSM
-21735,21736c27488
+21735,21736c27489
 < elect's
 < elect/ASDGV
 ---
 > elect/ASDGVM
-21820a27573
+21820a27574
 > elicitor/MS
-21864,21865c27617
+21864,21865c27618
 < em's
 < em/S
 ---
 > em/SM
-21992,21993c27744
+21992,21993c27745
 < employ's
 < employ/ADGLS
 ---
 > employ/ADGLSM
-22071a27823
+22071a27824
 > encyclopaedia
-22196a27949
+22196a27950
 > enqueue/DSG
-22508a28262,28263
+22508a28263,28264
 > eschatological
 > eschatologist/SM
-22556a28312
+22556a28313
 > estoppel
-22638c28394
+22638c28395
 < euthanize
 ---
 > euthanize/DSG
-22719a28476
+22719a28477
 > exabyte/MS
-22722,22724c28479,28482
+22722,22724c28480,28483
 < exact/SPDRYTG
 < exacting/Y
 < exaction/M
 ---
 > exact/SPDRYTGB
 > exacta/S
 > exacting/YP
 > exaction/MS
-22726a28485
+22726a28486
 > exactor/MS
-22947a28707
+22947a28708
 > experimentalism
-23165,23166c28925
+23165,23166c28926
 < face's
 < face/ACSDG
 ---
 > face/ACSDGM
-23207,23208d28965
+23207,23208d28966
 < faecal
 < faeces/M
-23215c28972
+23215c28973
 < faggoting's
 ---
 > faggot/SMG
-23238,23239c28995
+23238,23239c28996
 < faithful's
 < faithful/UPY
 ---
 > faithful/UPYM
-23278,23279c29034
+23278,23279c29035
 < fame's
 < fame/D
 ---
 > fame/DM
-23418a29174
+23418a29175
 > faux
-23589,23590c29345
+23589,23590c29346
 < fetter's
 < fetter/USGD
 ---
 > fetter/USGDM
-23690,23691c29445
+23690,23691c29446
 < figure's
 < figure/FEGSD
 ---
 > figure/FEGSDM
-23699,23700c29453
+23699,23700c29454
 < file's/KC
 < file/CAKGDS
 ---
 > file/CAKGDSM
-23701a29455
+23701a29456
 > filesystem/MS
-23708,23711c29462,29463
+23708,23711c29463,29464
 < filing's
 < filings
 < fill's
 < fill/AIDGS
 ---
 > filing/SM
 > fill/AIDGSM
-23715,23716c29467
+23715,23716c29468
 < filling's
 < filling/S
 ---
 > filling/SM
-23733,23734c29484
+23733,23734c29485
 < filtrate's
 < filtrate/IGNDS
 ---
 > filtrate/IGNDSM
-23745,23746c29495
+23745,23746c29496
 < finance's
 < finance/ADSG
 ---
 > finance/ADSGM
-23755,23756c29504
+23755,23756c29505
 < fine's/F
 < fine/CAFTGDS
 ---
 > fine/CAFTGDSM
-23776,23777c29524
+23776,23777c29525
 < finish's
 < finish/ADSG
 ---
 > finish/ADSGM
-24131,24132c29878
+24131,24132c29879
 < flower's
 < flower/CSDG
 ---
 > flower/CSDGM
-24155c29901
+24155c29902
 < fluidized
 ---
 > fluidize/DSG
-24185,24186c29931
+24185,24186c29932
 < flux's
 < flux/ADG
 ---
 > flux/ADGM
-24217,24218c29962,29963
+24217,24218c29963,29964
 < focus's
 < focus/ADSG
 ---
 > foci
 > focus/ADSGM
-24223,24224c29968
+24223,24224c29969
 < fog's
 < fog/CS
 ---
 > fog/CSM
-24238,24239c29982
+24238,24239c29983
 < fold's
 < fold/IAUSGD
 ---
 > fold/IAUSGDM
-24414,24415c30157
+24414,24415c30158
 < forest's
 < forest/ACGDS
 ---
 > forest/ACGDSM
-24464,24465c30206
+24464,24465c30207
 < form's
 < form/CAIFDGS
 ---
 > form/CAIFDGSM
-24585a30327,30328
+24585a30328,30329
 > frack/DRGS
 > fracker/S
-24609,24610c30352
+24609,24610c30353
 < franchise's
 < franchise/EDSG
 ---
 > franchise/EDSGM
-24633,24634c30375
+24633,24634c30376
 < fraud's
 < fraud/S
 ---
 > fraud/SM
-24639,24640c30380
+24639,24640c30381
 < fray's
 < fray/CDGS
 ---
 > fray/CDGSM
-24657a30398
+24657a30399
 > freegan/S
-24681,24682c30422
+24681,24682c30423
 < freeze's
 < freeze/UAGS
 ---
 > freeze/UAGSM
-24684c30424
+24684c30425
 < freezing's
 ---
 > freezing/M
-24733,24734c30473
+24733,24734c30474
 < friendly's
 < friendly/UTPR
 ---
 > friendly/UTPRM
-24736d30474
+24736d30475
 < frier/M
-24752,24753c30490
+24752,24753c30491
 < fringe's
 < fringe/IDSG
 ---
 > fringe/IDSGM
-24771,24772c30508
+24771,24772c30509
 < frock's
 < frock/CUS
 ---
 > frock/CUSM
-24786,24787c30522
+24786,24787c30523
 < front's
 < front/FSDG
 ---
 > front/FSDGM
-24800,24801c30535
+24800,24801c30536
 < frost's
 < frost/CSDG
 ---
 > frost/CSDGM
-24855,24856c30589,30590
+24855,24856c30590,30591
 < fucker/M!
 < fuckhead/S!
 ---
 > fucker/SM!
 > fuckhead/SM!
-24860,24861c30594
+24860,24861c30595
 < fuel's
 < fuel/ADGS
 ---
 > fuel/ADGSM
-24941,24942c30674
+24941,24942c30675
 < furl's
 < furl/UDGS
 ---
 > furl/UDGSM
-24953d30684
+24953d30685
 < furore/MS
-24969,24970c30700
+24969,24970c30701
 < fuse's/A
 < fuse/CAIFGDS
 ---
 > fuse/CAIFGDSM
-25038,25039c30768
+25038,25039c30769
 < gain's
 < gain/ADGS
 ---
 > gain/ADGSM
-25051,25052c30780
+25051,25052c30781
 < gale's
 < gale/AS
 ---
 > gale/ASM
-25095a30824
+25095a30825
 > gamify/NGDS
-25125c30854
+25125c30855
 < gaolbird/S
 ---
 > gaolbirds
-25169,25170c30898
+25169,25170c30899
 < gas's
 < gas/CS
 ---
 > gas/CSM
-25180d30907
+25180d30908
 < gasolene/M
-25190a30918
+25190a30919
 > gastroenterologist/M
-25262c30990
+25262c30991
 < geezer/M
 ---
 > geezer/MS
-25297,25298c31025
+25297,25298c31026
 < generation's/C
 < generation/ASM
 ---
 > generation/ASMC
-25327c31054
+25327c31055
 < genomic
 ---
 > genomic/S
-25462a31190
+25462a31191
 > gigabit/MS
-25464a31193,31195
+25464a31194,31196
 > gigajoule/MS
 > gigapixel/MS
 > gigawatt/MS
-25560d31290
+25560d31291
 < glamourize/DSG
-25674c31404
+25674c31405
 < glycerine's
 ---
 > glycerine/M
-25816,25817c31546
+25816,25817c31547
 < gorge's
 < gorge/EDSG
 ---
 > gorge/EDSGM
-25884,25885c31613
+25884,25885c31614
 < grade's
 < grade/CADSG
 ---
 > grade/CADSGM
-25905c31633
+25905c31634
 < gram/MS
 ---
 > gram/KMS
-25909d31636
+25909d31637
 < gramme/SM
-26063c31790,31791
+26063c31791,31792
 < greybeard
 ---
 > grey/MDRTGSP
 > greybeard/SM
-26066c31794
+26066c31795
 < greyness
 ---
 > greyness/M
-26246,26247d31973
+26246,26247d31974
 < guerilla's
 < guerillas
-26403,26404c32129
+26403,26404c32130
 < habit's
 < habit/ISB
 ---
 > habit/ISBM
-26432,26436d32156
+26432,26436d32157
 < haemoglobin's
 < haemophilia/M
 < haemorrhage/DSMG
 < haemorrhoid/S
 < haemorrhoids/M
-26555,26556c32275
+26555,26556c32276
 < hand's
 < hand/UDGS
 ---
 > hand/UDGSM
-26702,26703c32421
+26702,26703c32422
 < harness's
 < harness/UDSG
 ---
 > harness/UDSGM
-26725a32444
+26725a32445
 > hashtag/S
-26888,26889c32607
+26888,26889c32608
 < hearse's
 < hearse/AS
 ---
 > hearse/ASM
-26915,26916c32633
+26915,26916c32634
 < heat's
 < heat/ADGS
 ---
 > heat/ADGSM
-27167c32884
+27167c32885
 < hexane
 ---
 > hexane/SM
-27256,27257c32973
+27256,27257c32974
 < hinge's
 < hinge/UDSG
 ---
 > hinge/UDSGM
-27273a32990
+27273a32991
 > hippopotami
-27276,27277c32993
+27276,27277c32994
 < hire's
 < hire/AGDS
 ---
 > hire/AGDSM
-27302,27303c33018
+27302,27303c33019
 < hitch's
 < hitch/UDSG
 ---
 > hitch/UDSGM
-27512,27513c33227
+27512,27513c33228
 < hook's
 < hook/UDSG
 ---
 > hook/UDSGM
-27575,27576c33289
+27575,27576c33290
 < horse's
 < horse/UDSG
 ---
 > horse/UDSGM
-27666,27667c33379
+27666,27667c33380
 < house's
 < house/ADSG
 ---
 > house/ADSGM
-27841c33553
+27841c33554
 < hurrah's
 ---
 > hurrah/M
-27875d33586
+27875d33587
 < hyaena/SM
-27883,27884c33594
+27883,27884c33595
 < hydrate's
 < hydrate/CGNDS
 ---
 > hydrate/CGNDSM
-28017c33727
+28017c33728
 < iPod/M
 ---
 > iPod/MS
-28029,28030c33739
+28029,28030c33740
 < ice's
 < ice/CDSG
 ---
 > ice/CDSGM
-28105a33815
+28105a33816
 > idolator/SM
-28227c33937
+28227c33938
 < immerse/XDSGN
 ---
 > immerse/XDSGNV
-28513c34223
+28513c34224
 < inbound
 ---
 > inbound/s
-28531,28532c34241
+28531,28532c34242
 < incentive's
 < incentive/ES
 ---
 > incentive/ESM
-28560,28561c34269
+28560,28561c34270
 < incline's
 < incline/EGDS
 ---
 > incline/EGDSM
-28590,28591c34298
+28590,28591c34299
 < incorrigibility/M
 < incorrigible
 ---
 > incorrigibleness
-28593d34299
+28593d34300
 < incorruptibly
-28650a34357
+28650a34358
 > indices
-28812d34518
+28812d34519
 < inflexion/SM
-28981,28982c34687
+28981,28982c34688
 < insert's
 < insert/AGSD
 ---
 > insert/AGSDM
-29204a34910
+29204a34911
 > intermediacy/S
-29206c34912,34914
+29206c34913,34915
 < intermediate/SMY
 ---
 > intermediate/SMYPGD
 > intermediation/SE
 > intermediator/SM
-29216a34925
+29216a34926
 > intern/GDL
-29266a34976
+29266a34977
 > interruptible/U
-29272a34983,34986
+29272a34984,34987
 > intersex
 > intersexual/MS
 > intersexualism
 > intersexuality
-29446c35160
+29446c35161
 < ironic
 ---
 > ironic/U
-29447a35162
+29447a35163
 > ironically/U
-29724c35439
+29724c35440
 < jewellery's
 ---
 > jewellery/M
-29733,29734c35448
+29733,29734c35449
 < jig's
 < jig/AS
 ---
 > jig/ASM
-29736,29737c35450
+29736,29737c35451
 < jigger's
 < jigger/ASDG
 ---
 > jigger/ASDGM
-29799,29800c35512
+29799,29800c35513
 < join's
 < join/AFDSG
 ---
 > join/AFDSGM
-29803,29804c35515
+29803,29804c35516
 < joint's
 < joint/EGSD
 ---
 > joint/EGSDM
-29869,29870c35580,35581
+29869,29870c35581,35582
 < judge's
 < judge/ADSG
 ---
 > judge/ADSGM
 > judgement/MS
-30035a35747,35748
+30035a35748,35749
 > keylogger/MS
 > keylogging/MS
-30066c35779
+30066c35780
 < kiddie/M
 ---
 > kiddie/SM
-30102,30103c35815
+30102,30103c35816
 < kind's
 < kind/UPRYT
 ---
 > kind/UPRYTM
-30262,30263c35974
+30262,30263c35975
 < kraut's
 < kraut/S!
 ---
 > kraut/MS!
-30283,30284c35994
+30283,30284c35995
 < label's
 < label/ASDG
 ---
 > label/ASDGM
-30302,30303c36012
+30302,30303c36013
 < lace's
 < lace/UGDS
 ---
 > lace/UGDSM
-30497,30498c36206
+30497,30498c36207
 < latch's
 < latch/UDSG
 ---
 > latch/UDSGM
-30637c36345
+30637c36346
 < learning's
 ---
 > learning/M
-30643,30644c36351
+30643,30644c36352
 < leash's
 < leash/UDSG
 ---
 > leash/UDSGM
-30665a36373
+30665a36374
 > lector/MS
-30700c36408
+30700c36409
 < legation's/AC
 ---
 > legation/ACM
-30927,30928c36635
+30927,30928c36636
 < light's/C
 < light/CASTGD
 ---
 > light/CASTGDM
-30938c36645
+30938c36646
 < lighting's
 ---
 > lighting/M
-30981,30982c36688
+30981,30982c36689
 < limit's
 < limit/CSZGDR
 ---
 > limit/CSZGDRM
-30986c36692
+30986c36693
 < limiter's
 ---
 > limiter/M
-30990a36697,36699
+30990a36698,36700
 > limnological
 > limnologist/MS
 > limnology/M
-31031c36740
+31031c36741
 < linguini's
 ---
 > linguini/M
-31034c36743
+31034c36744
 < linguistically
 ---
 > linguistical/Y
-31047,31048c36756
+31047,31048c36757
 < lint's
 < lint/CDSG
 ---
 > lint/CDSGM
-31058a36767
+31058a36768
 > lepidopterist/SM
-31151,31152c36860
+31151,31152c36861
 < liver's
 < liver/S
 ---
 > liver/MS
-31170,31171c36878
+31170,31171c36879
 < load's
 < load/AUGSD
 ---
 > load/AUGSDM
-31211,31212c36918
+31211,31212c36919
 < location's/A
 < location/ESM
 ---
 > location/ESMA
-31291,31292c36997
+31291,31292c36998
 < long's
 < long/KDSTG
 ---
 > long/KDSTGM
-31379,31380c37084
+31379,31380c37085
 < louse's
 < louse/CDSG
 ---
 > louse/CDSGM
-31639a37344
+31639a37345
 > mage/SM
-31741,31742c37446
+31741,31742c37447
 < make's/A
 < make/UAGS
 ---
 > make/UAGSM
-31806a37511
+31806a37512
 > malware/MS
-31822,31823c37527
+31822,31823c37528
 < man's/F
 < man/USY
 ---
 > man/USYMF
-31924,31925c37628
+31924,31925c37629
 < mantle's
 < mantle/EGDS
 ---
 > mantle/EGDSM
-31940,31941c37643
+31940,31941c37644
 < map's
 < map/AS
 ---
 > map/ASM
-32061,32062c37763
+32061,32062c37764
 < mask's
 < mask/UDSG
 ---
 > mask/UDSGM
-32084,32085c37785
+32084,32085c37786
 < master's
 < master/ADGS
 ---
 > master/ADGSM
-32230c37930
+32230c37931
 < meanie/M
 ---
 > meanie/MS
-32246,32247c37946
+32246,32247c37947
 < measure's
 < measure/ADSG
 ---
 > measure/ADSGM
-32317,32318c38016
+32317,32318c38017
 < megadeath/M
 < megadeaths
 ---
 > megadeath/SM
-32320c38018
+32320c38019
 < megajoules
 ---
 > megajoule/SM
-32329c38027
+32329c38028
 < megapixel/S
 ---
 > megapixel/MS
-32361,32362c38059
+32361,32362c38060
 < melt's
 < melt/ADSG
 ---
 > melt/ADSGM
-32365,32366c38062
+32365,32366c38063
 < member's
 < member/EAS
 ---
 > member/EASM
-32708a38405
+32708a38406
 > might've
-32717a38415
+32717a38416
 > migrator/SM
-32760a38459
+32760a38460
 > millennia
-32777d38475
+32777d38476
 < millionnaire/M
-32806,32807c38504
+32806,32807c38505
 < mind's
 < mind/ADRSZG
 ---
 > mind/ADRSZGM
-32934a38632
+32934a38633
 > miscommunication/S
-32991a38690
+32991a38691
 > misjudgement/MS
-33027,33028c38726
+33027,33028c38727
 < miss's
 < miss/EDSGV
 ---
 > miss/EDSGVM
-33051,33052c38749
+33051,33052c38750
 < mist's
 < mist/CDRSZG
 ---
 > mist/CDRSZGM
-33056c38753
+33056c38754
 < mister's
 ---
 > mister/M
-33107,33108c38804
+33107,33108c38805
 < mob's
 < mob/CS
 ---
 > mob/CSM
-33448,33449c39144
+33448,33449c39145
 < mortgage's
 < mortgage/AGDS
 ---
 > mortgage/AGDSM
-33471,33472c39166
+33471,33472c39167
 < mote's
 < mote/KCXSVN
 ---
 > mote/KCXSVNM
-33539,33540c39233
+33539,33540c39234
 < mounting's
 < mountings
 ---
 > mounting/MS
-33784a39478
+33784a39479
 > must've
-33887,33888c39581
+33887,33888c39582
 < name's
 < name/AGDS
 ---
 > name/AGDSM
-33963c39656
+33963c39657
 < native/MS
 ---
 > native/MSY
-33970,33971c39663
+33970,33971c39664
 < natural's
 < natural/UPY
 ---
 > natural/UPYM
-33979,33980c39671
+33979,33980c39672
 < nature's
 < nature/CS
 ---
 > nature/CSM
-34133,34134c39824
+34133,34134c39825
 < nerve's
 < nerve/UDSG
 ---
 > nerve/UDSGM
-34169,34171c39859,39861
+34169,34171c39860,39862
 < neurone/S
 < neurophysiology
 < neuroscience
 ---
 > neurophysiology/M
 > neuroscience/MS
 > neuroscientist/MS
-34175a39866
+34175a39867
 > neurosurgical
-34275c39966
+34275c39967
 < nightie/M
 ---
 > nightie/SM
-34388,34389c40079
+34388,34389c40080
 < nomination's/A
 < nomination/CSM
 ---
 > nomination/CSMA
-34755,34756c40445
+34755,34756c40446
 < note's
 < note/FCSDG
 ---
 > note/FCSDGM
-34840,34841c40529
+34840,34841c40530
 < number's
 < number/ASDG
 ---
 > number/ASDGM
-35104a40793
+35104a40794
 > octopi
-35137,35138c40826
+35137,35138c40827
 < offensive's
 < offensive/IYP
 ---
 > offensive/IYPM
-35219d40906
+35219d40907
 < oleomargarin/M
-35226a40914
+35226a40915
 > oligo
-35345c41033
+35345c41034
 < oppose/DSG
 ---
 > oppose/DSGRB
-35452,35453c41140
+35452,35453c41141
 < orient's
 < orient/AEDGS
 ---
 > orient/AEDGSM
-35913c41600
+35913c41601
 < oversize/D
 ---
 > oversize
-36031,36032c41718
+36031,36032c41719
 < pack's
 < pack/UADSG
 ---
 > pack/UADSGM
-36034,36035c41720
+36034,36035c41721
 < package's
 < package/AGDS
 ---
 > package/AGDSM
-36041c41726
+36041c41727
 < packing's
 ---
 > packing/M
-36056,36059d41740
+36056,36059d41741
 < paederast/S
 < paediatrician's
 < paediatricians
 < paediatrics/M
-36290a41972,41973
+36290a41973,41974
 > parallelization/SM
 > parallelize/SGD
-36291a41975
+36291a41976
 > paralyses
-36377a42062
+36377a42063
 > parkour
-36403d42087
+36403d42088
 < parrakeet/MS
-36418,36419c42102
+36418,36419c42103
 < part's
 < part/CDSG
 ---
 > part/CDSGM
-36445,36447c42128
+36445,36447c42129
 < partition's
 < partition/ADG
 < partitions
 ---
 > partition/ADGMS
-36449d42129
+36449d42130
 < partizan/SM
-36621,36622c42301
+36621,36622c42302
 < pay's
 < pay/ASGBL
 ---
 > pay/ASGBLM
-37093a42773
+37093a42774
 > petabyte/MS
-37102c42782
+37102c42783
 < petitioner/M
 ---
 > petitioner/MS
-37221a42902,42903
+37221a42903,42904
 > phlebotomist/SM
 > phlebotomize/SGD
-37228a42911
+37228a42912
 > pho
-37264a42948
+37264a42949
 > phosphorylate/DSGN
-37310,37311c42994
+37310,37311c42995
 < phrase's
 < phrase/AGDS
 ---
 > phrase/AGDSM
-37316d42998
+37316d42999
 < phrenetic
-37469,37470c43151
+37469,37470c43152
 < pine's
 < pine/AGDS
 ---
 > pine/AGDSM
-37596,37597c43277
+37596,37597c43278
 < place's
 < place/EAGLDS
 ---
 > place/EAGLDSM
-37630a43311
+37630a43312
 > plaintext
-37636,37637c43317
+37636,37637c43318
 < plane's
 < plane/CGDS
 ---
 > plane/CGDSM
-37786,37787c43466
+37786,37787c43467
 < ploy's
 < ploy/S
 ---
 > ploy/SM
-37792,37793c43471
+37792,37793c43472
 < plug's
 < plug/US
 ---
 > plug/USM
-37796a43475
+37796a43476
 > plugin/MS
-37987c43666
+37987c43667
 < polypeptide/S
 ---
 > polypeptide/MS
-38106,38107c43785
+38106,38107c43786
 < port's
 < port/CAEGDS
 ---
 > port/CAEGDSM
-38134,38135c43812
+38134,38135c43813
 < pose's/A
 < pose/CAKEGDS
 ---
 > pose/CAKEGDSM
-38140,38141c43817
+38140,38141c43818
 < position's/KC
 < position/ACKES
 ---
 > position/ACKESM
-38260,38261c43936
+38260,38261c43937
 < pound's
 < pound/KDSG
 ---
 > pound/KDSGM
-38266a43942
+38266a43943
 > poutine/S
-38291d43966
+38291d43967
 < practise's
-38451a44127
+38451a44128
 > prejudgement/MS
-38568,38569c44244
+38568,38569c44245
 < press's
 < press/ACGSD
 ---
 > press/ACGSDM
-38638,38639c44313
+38638,38639c44314
 < price's
 < price/AGDS
 ---
 > price/AGDSM
-38756,38757c44430
+38756,38757c44431
 < process's
 < process/AGDS
 ---
 > process/AGDSM
-38780,38781c44453
+38780,38781c44454
 < produce's
 < produce/AZGDRS
 ---
 > produce/AZGDRSM
-38805a44478
+38805a44479
 > profiler/SM
-38835a44509
+38835a44510
 > programmatically
-38891a44566,44567
+38891a44567,44568
 > pronate/DSGN
 > pronator/MS
-38951c44627
+38951c44628
 < proprietorship/M
 ---
 > proprietorship/MS
-39039a44716
+39039a44717
 > provender/M
-39095a44773
+39095a44774
 > pseudorandom/Y
-39564a45243
+39564a45244
 > quinoa
-39581,39582c45260
+39581,39582c45261
 < quire's
 < quire/IAS
 ---
 > quire/IASM
-39614,39615c45292
+39614,39615c45293
 < quote's
 < quote/UDSG
 ---
 > quote/UDSGM
-39653,39654c45330
+39653,39654c45331
 < racoon's
 < racoons
 ---
 > racoon/MS
-39738,39739c45414
+39738,39739c45415
 < rail's
 < rail/CGDS
 ---
 > rail/CGDSM
-39816,39817c45491
+39816,39817c45492
 < range's
 < range/CGDS
 ---
 > range/CGDSM
-39873a45548,45549
+39873a45549,45550
 > rasterization/M
 > rasterize/SGDR
-39925,39926c45601
+39925,39926c45602
 < ravel's
 < ravel/UDSG
 ---
 > ravel/UDSGM
-40036a45712
+40036a45713
 > recency
-40140a45817
+40140a45818
 > recurse/DGSV
-40141a45819
+40141a45820
 > recuse/DGS
-40204,40205c45882
+40204,40205c45883
 < reel's
 < reel/UGDS
 ---
 > reel/UGDSM
-40208a45886
+40208a45887
 > refactor/SMDG
-40244d45921
+40244d45922
 < reflexion/SM
-40659d46335
+40659d46336
 < resizing
-40829c46505
+40829c46506
 < reverie/M
 ---
 > reverie/MS
-40895a46572,46574
+40895a46573,46575
 > rheumatological
 > rheumatology/M
 > rheumatologist/SM
-40944,40945c46623
+40944,40945c46624
 < ride's
 < ride/CZGS
 ---
 > ride/CZGSM
-41104,41105c46782
+41104,41105c46783
 < robe's
 < robe/EGDS
 ---
 > robe/EGDSM
-41132,41133c46809
+41132,41133c46810
 < rogue's
 < rogue/KS
 ---
 > rogue/KSM
-41185a46862
+41185a46863
 > rootkit/MS
-41258,41259c46935
+41258,41259c46936
 < route's
 < route/ADSG
 ---
 > route/ADSGM
-41415a47092
+41415a47093
 > sabre/MS
-41447,41448c47124
+41447,41448c47125
 < saddle's
 < saddle/UDSG
 ---
 > saddle/UDSGM
-41463,41464c47139
+41463,41464c47140
 < safe's
 < safe/UYTPR
 ---
 > safe/UYTPRM
-41544,41545c47219
+41544,41545c47220
 < salt's
 < salt/CTGDS
 ---
 > salt/CTGDSM
-41765,41766c47439
+41765,41766c47440
 < say's
 < say/USG
 ---
 > say/USGM
-41787,41788c47460
+41787,41788c47461
 < scale's
 < scale/ACSDG
 ---
 > scale/ACSDGM
-41806,41807c47478
+41806,41807c47479
 < scan's
 < scan/AS
 ---
 > scan/ASM
-41880,41881c47551
+41880,41881c47552
 < schedule's
 < schedule/ADSG
 ---
 > schedule/ADSGM
-41914c47584
+41914c47585
 < schnaps's
 ---
 > schnaps/M
-41949c47619
+41949c47620
 < schrod's
 ---
 > schrod/SM
-41998a47669
+41998a47670
 > scot-free
-42016,42017c47687
+42016,42017c47688
 < scramble's
 < scramble/UGDS
 ---
 > scramble/UGDSM
-42055,42056c47725
+42055,42056c47726
 < screw's
 < screw/UDSG
 ---
 > screw/UDSGM
-42065,42066c47734
+42065,42066c47735
 < scribe's
 < scribe/IKCGSD
 ---
 > scribe/IKCGSDM
-42170,42171c47838
+42170,42171c47839
 < seal's
 < seal/AUSDG
 ---
 > seal/AUSDGM
-42204,42205c47871
+42204,42205c47872
 < seat's
 < seat/UGDS
 ---
 > seat/UGDSM
-42288,42289c47954
+42288,42289c47955
 < seed's
 < seed/AGDS
 ---
 > seed/AGDSM
-42359c48024,48025
+42359c48025,48026
 < self/M
 ---
 > self/MG
 > selfie/S
-42361a48028,48029
+42361a48029,48030
 > selfism
 > selfist/S
-42365,42367c48033,48034
+42365,42367c48034,48035
 < sell's
 < sell/AZGRS
 < seller's
 ---
 > sell/AZGRSM
 > seller/M
-42524c48191
+42524c48192
 < seraphim's
 ---
 > seraphim/M
-42558,42559c48225
+42558,42559c48226
 < serve's/AF
 < serve/FACGDS
 ---
 > serve/FACGDSM
-42574,42575c48240
+42574,42575c48241
 < serving's
 < servings
 ---
 > serving/MS
-42594,42595c48259
+42594,42595c48260
 < settle's
 < settle/AUGDS
 ---
 > settle/AUGDSM
-42647,42648c48311
+42647,42648c48312
 < shackle's
 < shackle/UGDS
 ---
 > shackle/UGDSM
-42716,42717c48379
+42716,42717c48380
 < shape's
 < shape/AGDS
 ---
 > shape/AGDSM
-42851,42852c48513
+42851,42852c48514
 < ship's
 < ship/ALS
 ---
 > ship/ALSM
-42883,42885c48544
+42883,42885c48545
 < shit's
 < shit/S!
 < shite/S!
 ---
 > shit/MS!
-42887,42888c48546,48547
+42887,42888c48547,48548
 < shithead/S!
 < shitload/!
 ---
 > shithead/MS!
 > shitload/MS!
-42891c48550
+42891c48551
 < shitty/RT!
 ---
 > shitty/TR!
-42976a48636
+42976a48637
 > should've
-43008c48668
+43008c48669
 < showtime
 ---
 > showtime/MS
-43090,43091c48750
+43090,43091c48751
 < side's
 < side/AGDS
 ---
 > side/AGDSM
-43143,43144c48802
+43143,43144c48803
 < sign's
 < sign/AFCGDS
 ---
 > sign/AFCGDSM
-43163,43164c48821
+43163,43164c48822
 < signing's/C
 < signings
 ---
 > signing/MCS
-43328c48985
+43328c48986
 < size/MGBDRS
 ---
 > size/AMGBDRS
-43368,43369c49025
+43368,43369c49026
 < skill's
 < skill/CSD
 ---
 > skill/CSDM
-43724,43726c49380
+43724,43726c49381
 < smoulder's
 < smouldered
 < smoulders
 ---
 > smoulder/GSMD
-43752,43753c49406
+43752,43753c49407
 < snap's
 < snap/US
 ---
 > snap/USM
-43767,43768c49420,49422
+43767,43768c49421,49423
 < snarl's
 < snarl/USDG
 ---
 > snarkily
 > snarky/TR
 > snarl/USDGM
-44012,44013c49666
+44012,44013c49667
 < solute's
 < solute/XN
 ---
 > solute/XNM
-44015c49668
+44015c49669
 < solution's/EA
 ---
 > solution/EAM
-44021c49674
+44021c49675
 < solver's
 ---
 > solver/M
-44041a49695
+44041a49696
 > sommelier/SM
-44062c49716
+44062c49717
 < sonofabitch
 ---
 > sonofabitch/!
-44177,44178c49831
+44177,44178c49832
 < sow's
 < sow/ASGD
 ---
 > sow/ASGDM
-44346a50000
+44346a50001
 > spelled
-44348a50003
+44348a50004
 > spelt
-44371a50027
+44371a50028
 > spick/S!
-44383c50039
+44383c50040
 < spik/S
 ---
 > spik/S!
-44413,44414c50069
+44413,44414c50070
 < spire's
 < spire/IFAS
 ---
 > spire/IFASM
-44416,44417c50071
+44416,44417c50072
 < spirit's
 < spirit/ISGD
 ---
 > spirit/ISGDM
-44475,44476c50129
+44475,44476c50130
 < spoil's
 < spoil/CSDRZG
 ---
 > spoil/CSDRZGM
-44549,44550c50202
+44549,44550c50203
 < spray's
 < spray/ASDG
 ---
 > spray/ASDGM
-44688,44689c50340
+44688,44689c50341
 < staff's
 < staff/ASDG
 ---
 > staff/ASDGM
-44729,44730c50380
+44729,44730c50381
 < stall's
 < stall/SDG
 ---
 > stall/SDGM
-44871a50522
+44871a50523
 > steampunk
-44985,44986c50636
+44985,44986c50637
 < still's
 < still/ITGSD
 ---
 > still/ITGSDM
-45024,45025c50674
+45024,45025c50675
 < stitch's
 < stitch/ADSG
 ---
 > stitch/ADSGM
-45030,45031c50679
+45030,45031c50680
 < stock's
 < stock/AGSD
 ---
 > stock/AGSDM
-45090,45091c50738
+45090,45091c50739
 < stop's
 < stop/US
 ---
 > stop/USM
-45105,45106c50752
+45105,45106c50753
 < store's
 < store/ADSG
 ---
 > store/ADSGM
-45148,45149c50794
+45148,45149c50795
 < strain's
 < strain/FADSG
 ---
 > strain/FADSGM
-45164,45165c50809
+45164,45165c50810
 < strap's
 < strap/US
 ---
 > strap/USM
-45290,45291c50934
+45290,45291c50935
 < structure's
 < structure/AGDS
 ---
 > structure/AGDSM
-45330,45331c50973
+45330,45331c50974
 < study's
 < study/AGDS
 ---
 > study/AGDSM
-45368,45369c51010
+45368,45369c51011
 < style's
 < style/ADSG
 ---
 > style/ADSGM
-45455,45456c51096
+45455,45456c51097
 < submission's
 < submission/AS
 ---
 > submission/ASM
-45872,45873c51512
+45872,45873c51513
 < surface's
 < surface/AGDS
 ---
 > surface/AGDSM
-45918,45919c51557
+45918,45919c51558
 < survey's
 < survey/ADGS
 ---
 > survey/ADGSM
-46106a51745
+46106a51746
 > syllabi
-46160c51799
+46160c51800
 < synch/GMD
 ---
 > synch/GMDS
-46167d51805
+46167d51806
 < synchs
-46178a51817,51819
+46178a51818,51820
 > synesthesia
 > synesthete/S
 > synesthetic
-46203,46204c51844,51845
+46203,46204c51845,51846
 < sysadmin/S
 < sysop/S
 ---
 > sysadmin/MS
 > sysop/MS
-46363,46364c52004
+46363,46364c52005
 < tangle's
 < tangle/UDSG
 ---
 > tangle/UDSGM
-46632a52273,52274
+46632a52274,52275
 > teleport/SGD
 > teleportation
-46675,46676c52317
+46675,46676c52318
 < template's
 < template/S
 ---
 > template/SM
-46752a52394
+46752a52395
 > terabit/MS
-46753a52396,52397
+46753a52397,52398
 > terahertz/M
 > terapixel/MS
-46806,46807c52450
+46806,46807c52451
 < test's/AFK
 < test/AKFCDGS
 ---
 > test/AKFCDGSM
-46817a52461
+46817a52462
 > testcase/MS
-46831a52476
+46831a52477
 > testsuite/MS
-46845a52491
+46845a52492
 > textbox/SM
-46925a52572
+46925a52573
 > theremin/MS
-46999c52646
+46999c52647
 < thinking's
 ---
 > thinking/M
-47095,47096c52742
+47095,47096c52743
 < throne's
 < throne/CDS
 ---
 > throne/CDSM
-47188,47189c52834
+47188,47189c52835
 < tie's
 < tie/AUSD
 ---
 > tie/AUSDM
-47213,47214c52858
+47213,47214c52859
 < till's
 < till/EDRZGS
 ---
 > till/EDRZGSM
-47303,47304c52947
+47303,47304c52948
 < tire's
 < tire/AGDS
 ---
 > tire/AGDSM
-47433,47434c53076
+47433,47434c53077
 < tone's
 < tone/IZGDRS
 ---
 > tone/IZGDRSM
-47453,47455c53095,53096
+47453,47455c53096,53097
 < tool's
 < tool/ADGS
 < toolbar
 ---
 > tool/ADGSM
 > toolbar/MS
-47540,47541c53181
+47540,47541c53182
 < tort's
 < tort/FEAS
 ---
 > tort/FEASM
-47644a53285
+47644a53286
 > traceur/SM
-47657,47658c53298
+47657,47658c53299
 < tract's
 < tract/CEKFAS
 ---
 > tract/CEKFASM
-47755a53396
+47755a53397
 > transfect/DSMG
-47774a53416,53417
+47774a53417,53418
 > transgenderism
 > transgene/MS
-47807,47808c53450
+47807,47808c53451
 < transmission's
 < transmission/AS
 ---
 > transmission/ASM
-47928,47929c53570
+47928,47929c53571
 < trench's
 < trench/AIGSD
 ---
 > trench/AIGSDM
-47951c53592
+47951c53593
 < triage/M
 ---
 > triage/MGS
-47976,47977c53617
+47976,47977c53618
 < tribute's
 < tribute/FS
 ---
 > tribute/FSM
-47997a53638
+47997a53639
 > trifecta/S
-48165,48166c53806
+48165,48166c53807
 < trust's/E
 < trust/IESGD
 ---
 > trust/IESGDM
-48180,48181c53820
+48180,48181c53821
 < try's
 < try/AGDS
 ---
 > try/AGDSM
-48271a53911
+48271a53912
 > turducken
-48334a53975
+48334a53976
 > tweep/S
-48371,48372c54012
+48371,48372c54013
 < twist's
 < twist/USDG
 ---
 > twist/USDGM
-48396,48397c54036
+48396,48397c54037
 < type's
 < type/AGDS
 ---
 > type/AGDSM
-48869a54509
+48869a54510
 > unlikeable
-49163,49164c54803
+49163,49164c54804
 < usual's
 < usual/UY
 ---
 > usual/UYM
-49211c54850
+49211c54851
 < vagina/M
 ---
 > vagina/MS
-49249,49250c54888
+49249,49250c54889
 < value's
 < value/CAGSD
 ---
 > value/CAGSDM
-49292,49293c54930
+49292,49293c54931
 < variant's
 < variant/IS
 ---
 > variant/ISM
-49356,49357c54993
+49356,49357c54994
 < veil's
 < veil/UDGS
 ---
 > veil/UDGSM
-49368,49369c55004
+49368,49369c55005
 < velour's
 < velours's
 ---
 > velour/MS
-49398,49399c55033
+49398,49399c55034
 < vent's
 < vent/DGS
 ---
 > vent/DGSM
-49435,49436c55069
+49435,49436c55070
 < verge's
 < verge/FDSG
 ---
 > verge/FDSGM
-49478a55112
+49478a55113
 > vertices
-49488,49489c55122
+49488,49489c55123
 < vest's
 < vest/ILDGS
 ---
 > vest/ILDGSM
-49681,49682c55314
+49681,49682c55315
 < visit's
 < visit/ASGD
 ---
 > visit/ASGDM
-49772a55405,55407
+49772a55406,55408
 > volcanological
 > volcanologist/MS
 > volcanology/M
-49807,49808c55442
+49807,49808c55443
 < vote's
 < vote/CGVDS
 ---
 > vote/CGVDSM
-50148a55783
+50148a55784
 > weaponize/DSG
-50215,50216c55850
+50215,50216c55851
 < weigh's
 < weigh/AGD
 ---
 > weigh/AGDM
-50260,50261d55893
+50260,50261d55894
 < werwolf/M
 < werwolves
-50555,50556c56187
+50555,50556c56188
 < wind's
 < wind/UASG
 ---
 > wind/UASGM
-50626,50627c56257
+50626,50627c56258
 < wire's
 < wire/AGDS
 ---
 > wire/AGDSM
-50728c56358
+50728c56359
 < women
 ---
 > women/M
-50794,50796c56424,56425
+50794,50796c56425,56426
 < wop/S!
 < word's
 < word/AJDSG
 ---
 > wop/MS!
 > word/AJDSGM
-50801c56430
+50801c56431
 < wording's
 ---
 > wording/M
-50808,50809c56437
+50808,50809c56438
 < work's
 < work/ADJSG
 ---
 > work/ADJSGM
-50824c56452
+50824c56453
 < working's
 ---
 > working/M
-50884,50885c56512
+50884,50885c56513
 < worthy's
 < worthy/UPRT
 ---
 > worthy/UPRTM
-50903,50904c56530
+50903,50904c56531
 < wrap's
 < wrap/US
 ---
 > wrap/USM
-50945c56571
+50945c56572
 < writing's
 ---
 > writing/M
-51118,51119c56744
+51118,51119c56745
 < yoke's
 < yoke/UGDS
 ---
 > yoke/UGDSM
-51212,51213c56837
+51212,51213c56838
 < zip's
 < zip/US
 ---
 > zip/USM
-51228,51229c56852
+51228,51229c56853
 < zone's
 < zone/AGDS
 ---
 > zone/AGDSM
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-57239
+57240
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -22250,16 +22250,17 @@ characterful
 characteristic/MS
 characteristically/U
 characterization/MS
 characterize/GDS
 characterless
 charade/SM
 charbroil/GDS
 charcoal/MS
+charcuterie
 chard/M
 chardonnay/SM
 charge/EAMGDS
 chargeable/A
 charged/U
 charger/SM
 charily
 chariness/M
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -71,34 +71,34 @@ public:
     SurfaceFormat format = mDT->mFormat;
 
     CD3D10_TEXTURE2D_DESC desc(DXGIFormat(format), size.width, size.height,
                                1, 1);
     desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
 
     HRESULT hr = mDT->mDevice->CreateTexture2D(&desc, nullptr, byRef(tmpTexture));
     if (FAILED(hr)) {
-      gfxCriticalError() << "[D2D] CreateTexture2D failure " << size << " Code: " << hr;
+      gfxCriticalError() << "[D2D] CreateTexture2D failure " << size << " Code: " << hexa(hr);
       // Crash debug builds but try to recover in release builds.
       MOZ_ASSERT(false);
       return;
     }
     mDT->mDevice->CopyResource(tmpTexture, mDT->mTexture);
 
     D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(format));
 
     RefPtr<IDXGISurface> surf;
 
     tmpTexture->QueryInterface((IDXGISurface**)byRef(surf));
 
     hr = mDT->mRT->CreateSharedBitmap(IID_IDXGISurface, surf,
                                       &props, byRef(mOldSurfBitmap));
 
     if (FAILED(hr)) {
-      gfxCriticalError() << "[D2D] CreateSharedBitmap failure " << size << " Code: " << hr;
+      gfxCriticalError() << "[D2D] CreateSharedBitmap failure " << size << " Code: " << hexa(hr);
       // Crash debug builds but try to recover in release builds.
       MOZ_ASSERT(false);
       return;
     }
 
     IntRect clipBounds;
     mClippedArea = mDT->GetClippedGeometry(&clipBounds);
 
@@ -236,17 +236,17 @@ DrawTargetD2D::Snapshot()
 void
 DrawTargetD2D::Flush()
 {
   PopAllClips();
 
   HRESULT hr = mRT->Flush();
 
   if (FAILED(hr)) {
-    gfxWarning() << "Error reported when trying to flush D2D rendertarget. Code: " << hr;
+    gfxWarning() << "Error reported when trying to flush D2D rendertarget. Code: " << hexa(hr);
   }
 
   // We no longer depend on any target.
   for (TargetSet::iterator iter = mDependingOnTargets.begin();
        iter != mDependingOnTargets.end(); iter++) {
     (*iter)->mDependentTargets.erase(this);
   }
   mDependingOnTargets.clear();
@@ -466,17 +466,17 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
 
   EnsureViews();
 
   if (!mTempRTView) {
     // This view is only needed in this path.
     HRESULT hr = mDevice->CreateRenderTargetView(mTempTexture, nullptr, byRef(mTempRTView));
 
     if (FAILED(hr)) {
-      gfxWarning() << "Failure to create RenderTargetView. Code: " << hr;
+      gfxWarning() << "Failure to create RenderTargetView. Code: " << hexa(hr);
       return;
     }
   }
 
 
   RefPtr<ID3D10RenderTargetView> destRTView = mRTView;
   RefPtr<ID3D10Texture2D> destTexture;
   HRESULT hr;
@@ -527,17 +527,17 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
                                aSurface->GetSize().height);
     desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
     desc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS;
 
     RefPtr<ID3D10Texture2D> mipTexture;
     hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(mipTexture));
 
     if (FAILED(hr)) {
-      gfxCriticalError() << "[D2D] CreateTexture2D failure " << aSurface->GetSize() << " Code: " << hr;
+      gfxCriticalError() << "[D2D] CreateTexture2D failure " << aSurface->GetSize() << " Code: " << hexa(hr);
       return;
     }
 
     IntSize dsSize = IntSize(int32_t(aSurface->GetSize().width * (1.7f / aSigma)),
                              int32_t(aSurface->GetSize().height * (1.7f / aSigma)));
 
     if (dsSize.width < 1) {
       dsSize.width = 1;
@@ -554,17 +554,17 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
     desc = CD3D10_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM,
                                  dsSize.width,
                                  dsSize.height, 1, 1);
     desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
     RefPtr<ID3D10Texture2D> tmpDSTexture;
     hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(tmpDSTexture));
 
     if (FAILED(hr)) {
-      gfxCriticalError() << "[D2D] CreateTexture2D failure " << dsSize << " Code: " << hr;
+      gfxCriticalError() << "[D2D] CreateTexture2D failure " << dsSize << " Code: " << hexa(hr);
       return;
     }
 
     D3D10_BOX box;
     box.left = box.top = box.front = 0;
     box.back = 1;
     box.right = aSurface->GetSize().width;
     box.bottom = aSurface->GetSize().height;
@@ -1263,24 +1263,24 @@ DrawTargetD2D::CreateSimilarDrawTarget(c
 
 TemporaryRef<PathBuilder>
 DrawTargetD2D::CreatePathBuilder(FillRule aFillRule) const
 {
   RefPtr<ID2D1PathGeometry> path;
   HRESULT hr = factory()->CreatePathGeometry(byRef(path));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create Direct2D Path Geometry. Code: " << hr;
+    gfxWarning() << "Failed to create Direct2D Path Geometry. Code: " << hexa(hr);
     return nullptr;
   }
 
   RefPtr<ID2D1GeometrySink> sink;
   hr = path->Open(byRef(sink));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to access Direct2D Path Geometry. Code: " << hr;
+    gfxWarning() << "Failed to access Direct2D Path Geometry. Code: " << hexa(hr);
     return nullptr;
   }
 
   if (aFillRule == FillRule::FILL_WINDING) {
     sink->SetFillMode(D2D1_FILL_MODE_WINDING);
   }
 
   return new PathBuilderD2D(sink, path, aFillRule);
@@ -1300,17 +1300,17 @@ DrawTargetD2D::CreateGradientStops(Gradi
 
   HRESULT hr =
     mRT->CreateGradientStopCollection(stops, aNumStops,
                                       D2D1_GAMMA_2_2, D2DExtend(aExtendMode),
                                       byRef(stopCollection));
   delete [] stops;
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create GradientStopCollection. Code: " << hr;
+    gfxWarning() << "Failed to create GradientStopCollection. Code: " << hexa(hr);
     return nullptr;
   }
 
   return new GradientStopsD2D(stopCollection);
 }
 
 TemporaryRef<FilterNode>
 DrawTargetD2D::CreateFilter(FilterType aType)
@@ -1357,17 +1357,17 @@ DrawTargetD2D::Init(const IntSize &aSize
                              mSize.width,
                              mSize.height,
                              1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
 
   hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
 
   if (FAILED(hr)) {
-    gfxCriticalError() << "Failed to init Direct2D DrawTarget. Size: " << mSize << " Code: " << hr;
+    gfxCriticalError() << "Failed to init Direct2D DrawTarget. Size: " << mSize << " Code: " << hexa(hr);
     return false;
   }
 
   if (!InitD2DRenderTarget()) {
     return false;
   }
 
   mRT->Clear(D2D1::ColorF(0, 0));
@@ -1427,17 +1427,17 @@ DrawTargetD2D::InitD3D10Data()
   decltype(D3D10CreateEffectFromMemory)* createD3DEffect;
   HMODULE d3dModule = LoadLibraryW(L"d3d10_1.dll");
   createD3DEffect = (decltype(D3D10CreateEffectFromMemory)*)
       GetProcAddress(d3dModule, "D3D10CreateEffectFromMemory");
 
   hr = createD3DEffect((void*)d2deffect, sizeof(d2deffect), 0, mDevice, nullptr, byRef(mPrivateData->mEffect));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to initialize Direct2D required effects. Code: " << hr;
+    gfxWarning() << "Failed to initialize Direct2D required effects. Code: " << hexa(hr);
     return false;
   }
 
   privateDataSize = sizeof(mPrivateData);
   mDevice->SetPrivateData(sPrivateDataD2D, privateDataSize, &mPrivateData);
 
   D3D10_INPUT_ELEMENT_DESC layout[] =
   {
@@ -1449,29 +1449,29 @@ DrawTargetD2D::InitD3D10Data()
 
   hr = mDevice->CreateInputLayout(layout,
                                   sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC),
                                   passDesc.pIAInputSignature,
                                   passDesc.IAInputSignatureSize,
                                   byRef(mPrivateData->mInputLayout));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to initialize Direct2D required InputLayout. Code: " << hr;
+    gfxWarning() << "Failed to initialize Direct2D required InputLayout. Code: " << hexa(hr);
     return false;
   }
 
   D3D10_SUBRESOURCE_DATA data;
   Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
   data.pSysMem = vertices;
   CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
 
   hr = mDevice->CreateBuffer(&bufferDesc, &data, byRef(mPrivateData->mVB));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to initialize Direct2D required VertexBuffer. Code: " << hr;
+    gfxWarning() << "Failed to initialize Direct2D required VertexBuffer. Code: " << hexa(hr);
     return false;
   }
 
   return true;
 }
 
 /*
  * Private helpers
@@ -1766,26 +1766,26 @@ DrawTargetD2D::FinalizeRTForOperation(Co
       HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(tmpTexture));
       if (FAILED(hr)) {
         gfxWarning() << "Failed to create temporary texture to hold surface data.";
         return;
       }
 
       mDevice->CopyResource(tmpTexture, mTexture);
       if (FAILED(hr)) {
-        gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hr;
+        gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr);
         return;
       }
 
       DrawTargetD2D::Flush();
 
       hr = mDevice->CreateShaderResourceView(tmpTexture, nullptr, byRef(mBckSRView));
 
       if (FAILED(hr)) {
-        gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hr;
+        gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr);
         return;
       }
 
       unsigned int compop = (unsigned int)aOperator - (unsigned int)CompositionOp::OP_XOR;
       mPrivateData->mEffect->GetVariableByName("bcktex")->AsShaderResource()->SetResource(mBckSRView);
       mPrivateData->mEffect->GetVariableByName("blendop")->AsScalar()->SetInt(compop);
 
       if (aOperator > CompositionOp::OP_EXCLUSION)
@@ -2000,31 +2000,31 @@ DrawTargetD2D::EnsureViews()
                              mSize.height,
                              1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
 
   hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(mTempTexture));
 
   if (FAILED(hr)) {
     gfxWarning() << *this << "Failed to create temporary texture for rendertarget. Size: "
-      << mSize << " Code: " << hr;
+      << mSize << " Code: " << hexa(hr);
     return;
   }
 
   hr = mDevice->CreateShaderResourceView(mTempTexture, nullptr, byRef(mSRView));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hr;
+    gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr);
     return;
   }
 
   hr = mDevice->CreateRenderTargetView(mTexture, nullptr, byRef(mRTView));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << "Failed to create rendertarget view for temp texture. Code: " << hr;
+    gfxWarning() << *this << "Failed to create rendertarget view for temp texture. Code: " << hexa(hr);
   }
 }
 
 void
 DrawTargetD2D::PopAllClips()
 {
   if (mClipsArePushed) {
     PopClipsFromRT(mRT);
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -615,17 +615,17 @@ DrawTargetD2D1::CreateSourceSurfaceFromD
 {
   RefPtr<ID2D1Bitmap1> bitmap;
 
   HRESULT hr = mDC->CreateBitmap(D2DIntSize(aSize), aData, aStride,
                                  D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_NONE, D2DPixelFormat(aFormat)),
                                  byRef(bitmap));
 
   if (FAILED(hr)) {
-    gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << aSize << " Code: " << hr;
+    gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << aSize << " Code: " << hexa(hr);
   }
 
   if (!bitmap) {
     return nullptr;
   }
 
   return new SourceSurfaceD2D1(bitmap.get(), mDC, aFormat, aSize);
 }
@@ -644,24 +644,24 @@ DrawTargetD2D1::CreateSimilarDrawTarget(
 
 TemporaryRef<PathBuilder>
 DrawTargetD2D1::CreatePathBuilder(FillRule aFillRule) const
 {
   RefPtr<ID2D1PathGeometry> path;
   HRESULT hr = factory()->CreatePathGeometry(byRef(path));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Failed to create Direct2D Path Geometry. Code: " << hr;
+    gfxWarning() << *this << ": Failed to create Direct2D Path Geometry. Code: " << hexa(hr);
     return nullptr;
   }
 
   RefPtr<ID2D1GeometrySink> sink;
   hr = path->Open(byRef(sink));
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Failed to access Direct2D Path Geometry. Code: " << hr;
+    gfxWarning() << *this << ": Failed to access Direct2D Path Geometry. Code: " << hexa(hr);
     return nullptr;
   }
 
   if (aFillRule == FillRule::FILL_WINDING) {
     sink->SetFillMode(D2D1_FILL_MODE_WINDING);
   }
 
   return new PathBuilderD2D(sink, path, aFillRule);
@@ -686,17 +686,17 @@ DrawTargetD2D1::CreateGradientStops(Grad
 
   HRESULT hr =
     mDC->CreateGradientStopCollection(stops, aNumStops,
                                       D2D1_GAMMA_2_2, D2DExtend(aExtendMode),
                                       byRef(stopCollection));
   delete [] stops;
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Failed to create GradientStopCollection. Code: " << hr;
+    gfxWarning() << *this << ": Failed to create GradientStopCollection. Code: " << hexa(hr);
     return nullptr;
   }
 
   return new GradientStopsD2D(stopCollection);
 }
 
 TemporaryRef<FilterNode>
 DrawTargetD2D1::CreateFilter(FilterType aType)
@@ -707,17 +707,17 @@ DrawTargetD2D1::CreateFilter(FilterType 
 bool
 DrawTargetD2D1::Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat)
 {
   HRESULT hr;
 
   hr = Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, byRef(mDC));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Error " << hr << " failed to initialize new DeviceContext.";
+    gfxWarning() << *this << ": Error " << hexa(hr) << " failed to initialize new DeviceContext.";
     return false;
   }
 
   RefPtr<IDXGISurface> dxgiSurface;
   aTexture->QueryInterface(__uuidof(IDXGISurface),
                            (void**)((IDXGISurface**)byRef(dxgiSurface)));
   if (!dxgiSurface) {
     return false;
@@ -727,33 +727,33 @@ DrawTargetD2D1::Init(ID3D11Texture2D* aT
   props.dpiX = 96;
   props.dpiY = 96;
   props.pixelFormat = D2DPixelFormat(aFormat);
   props.colorContext = nullptr;
   props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
   hr = mDC->CreateBitmapFromDxgiSurface(dxgiSurface, props, (ID2D1Bitmap1**)byRef(mBitmap));
 
   if (FAILED(hr)) {
-    gfxCriticalError() << "[D2D1.1] CreateBitmapFromDxgiSurface failure Code: " << hr;
+    gfxCriticalError() << "[D2D1.1] CreateBitmapFromDxgiSurface failure Code: " << hexa(hr);
     return false;
   }
 
   mFormat = aFormat;
   D3D11_TEXTURE2D_DESC desc;
   aTexture->GetDesc(&desc);
   desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
   mSize.width = desc.Width;
   mSize.height = desc.Height;
   props.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
   props.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
 
   hr = mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mTempBitmap));
 
   if (FAILED(hr)) {
-    gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << mSize << " Code: " << hr;
+    gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << mSize << " Code: " << hexa(hr);
     return false;
   }
 
   mDC->SetTarget(mBitmap);
 
   mDC->BeginDraw();
   return true;
 }
@@ -761,17 +761,17 @@ DrawTargetD2D1::Init(ID3D11Texture2D* aT
 bool
 DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
 {
   HRESULT hr;
 
   hr = Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, byRef(mDC));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Error " << hr << " failed to initialize new DeviceContext.";
+    gfxWarning() << *this << ": Error " << hexa(hr) << " failed to initialize new DeviceContext.";
     return false;
   }
 
   if (mDC->GetMaximumBitmapSize() < UINT32(aSize.width) ||
       mDC->GetMaximumBitmapSize() < UINT32(aSize.height)) {
     // This is 'ok'
     gfxDebug() << *this << ": Attempt to use unsupported surface size for D2D 1.1.";
     return false;
@@ -781,17 +781,17 @@ DrawTargetD2D1::Init(const IntSize &aSiz
   props.dpiX = 96;
   props.dpiY = 96;
   props.pixelFormat = D2DPixelFormat(aFormat);
   props.colorContext = nullptr;
   props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
   mDC->CreateBitmap(D2DIntSize(aSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mBitmap));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Error " << hr << " failed to create new CommandList.";
+    gfxWarning() << *this << ": Error " << hexa(hr) << " failed to create new CommandList.";
     return false;
   }
 
   props.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
   props.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
 
   mDC->CreateBitmap(D2DIntSize(aSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mTempBitmap));
 
@@ -1278,17 +1278,17 @@ DrawTargetD2D1::OptimizeSourceSurface(So
   }
 
   RefPtr<ID2D1Bitmap1> bitmap;
   HRESULT hr = mDC->CreateBitmap(D2DIntSize(data->GetSize()), map.mData, map.mStride,
                                  D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_NONE, D2DPixelFormat(data->GetFormat())),
                                  byRef(bitmap));
 
   if (FAILED(hr)) {
-    gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << data->GetSize() << " Code: " << hr;
+    gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << data->GetSize() << " Code: " << hexa(hr);
   }
 
   data->Unmap();
 
   if (!bitmap) {
     return data.forget();
   }
 
--- a/gfx/2d/FilterNodeD2D1.cpp
+++ b/gfx/2d/FilterNodeD2D1.cpp
@@ -530,17 +530,17 @@ FilterNodeD2D1::Create(DrawTarget* aDT, 
   }
 
   RefPtr<ID2D1Effect> effect;
   HRESULT hr;
 
   hr = aDC->CreateEffect(GetCLDIDForFilterType(aType), byRef(effect));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create effect for FilterType: " << hr;
+    gfxWarning() << "Failed to create effect for FilterType: " << hexa(hr);
     return nullptr;
   }
 
   switch (aType) {
     case FilterType::LINEAR_TRANSFER:
     case FilterType::GAMMA_TRANSFER:
     case FilterType::TABLE_TRANSFER:
     case FilterType::DISCRETE_TRANSFER:
--- a/gfx/2d/Logging.h
+++ b/gfx/2d/Logging.h
@@ -5,17 +5,19 @@
 
 #ifndef MOZILLA_GFX_LOGGING_H_
 #define MOZILLA_GFX_LOGGING_H_
 
 #include <string>
 #include <sstream>
 #include <stdio.h>
 
+#if defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)
 #include "nsDebug.h"
+#endif
 #include "Point.h"
 #include "BaseRect.h"
 #include "Matrix.h"
 #include "mozilla/TypedEnum.h"
 
 #ifdef WIN32
 // This file gets included from nsGlobalWindow.cpp, which doesn't like
 // having windows.h included in it. Since OutputDebugStringA is the only
@@ -64,17 +66,21 @@ struct BasicLogger
       ::OutputDebugStringA(aString.c_str());
     }
 #elif defined(PR_LOGGING) && !(defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID))
     if (PR_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) {
       PR_LogPrint(aString.c_str());
     }
 #else
     if (aLevel >= sGfxLogLevel) {
+#if defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)
       printf_stderr("%s", aString.c_str());
+#else
+      printf("%s", aString.c_str());
+#endif
     }
 #endif
   }
 };
 
 struct CriticalLogger {
   static void OutputMessage(const std::string &aString, int aLevel);
 };
@@ -96,16 +102,24 @@ public:
   template<typename T>
   NoLog &operator <<(const T &aLogText) { return *this; }
 };
 
 MOZ_BEGIN_ENUM_CLASS(LogOptions, int)
   NoNewline = 0x01
 MOZ_END_ENUM_CLASS(LogOptions)
 
+template<typename T>
+struct Hexa {
+  Hexa(T aVal) : mVal(aVal) {}
+  T mVal;
+};
+template<typename T>
+Hexa<T> hexa(T val) { return Hexa<T>(val); }
+
 template<int L, typename Logger = BasicLogger>
 class Log
 {
 public:
   explicit Log(LogOptions aOptions = LogOptions(0)) : mOptions(aOptions) {}
   ~Log() {
     Flush();
   }
@@ -140,17 +154,19 @@ public:
   template <typename T, typename Sub>
   Log &operator <<(const BaseSize<T, Sub>& aSize)
     { mMessage << "Size(" << aSize.width << "," << aSize.height << ")"; return *this; }
   template <typename T, typename Sub, typename Point, typename SizeT, typename Margin>
   Log &operator <<(const BaseRect<T, Sub, Point, SizeT, Margin>& aRect)
     { mMessage << "Rect" << aRect; return *this; }
   Log &operator<<(const Matrix& aMatrix)
     { mMessage << "Matrix(" << aMatrix._11 << " " << aMatrix._12 << " ; " << aMatrix._21 << " " << aMatrix._22 << " ; " << aMatrix._31 << " " << aMatrix._32 << ")"; return *this; }
-
+  template<typename T>
+  Log &operator<<(Hexa<T> aHex)
+    { mMessage << "0x" << std::hex << aHex.mVal << std::dec; return *this; }
 
 private:
 
   void WriteLog(const std::string &aString) {
     Logger::OutputMessage(aString, L);
   }
 
   std::stringstream mMessage;
--- a/gfx/2d/PathD2D.cpp
+++ b/gfx/2d/PathD2D.cpp
@@ -294,17 +294,17 @@ TemporaryRef<Path>
 PathBuilderD2D::Finish()
 {
   if (mFigureActive) {
     mSink->EndFigure(D2D1_FIGURE_END_OPEN);
   }
 
   HRESULT hr = mSink->Close();
   if (FAILED(hr)) {
-    gfxDebug() << "Failed to close PathSink. Code: " << hr;
+    gfxDebug() << "Failed to close PathSink. Code: " << hexa(hr);
     return nullptr;
   }
 
   return new PathD2D(mGeometry, mFigureActive, mCurrentPoint, mFillRule);
 }
 
 TemporaryRef<PathBuilder>
 PathD2D::CopyToBuilder(FillRule aFillRule) const
@@ -314,24 +314,24 @@ PathD2D::CopyToBuilder(FillRule aFillRul
 
 TemporaryRef<PathBuilder>
 PathD2D::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
 {
   RefPtr<ID2D1PathGeometry> path;
   HRESULT hr = DrawTargetD2D::factory()->CreatePathGeometry(byRef(path));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create PathGeometry. Code: " << hr;
+    gfxWarning() << "Failed to create PathGeometry. Code: " << hexa(hr);
     return nullptr;
   }
 
   RefPtr<ID2D1GeometrySink> sink;
   hr = path->Open(byRef(sink));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to open Geometry for writing. Code: " << hr;
+    gfxWarning() << "Failed to open Geometry for writing. Code: " << hexa(hr);
     return nullptr;
   }
 
   if (aFillRule == FillRule::FILL_WINDING) {
     sink->SetFillMode(D2D1_FILL_MODE_WINDING);
   }
 
   if (mEndedActive) {
@@ -362,17 +362,17 @@ PathD2D::StreamToSink(PathSink *aSink) c
   HRESULT hr;
 
   StreamingGeometrySink sink(aSink);
 
   hr = mGeometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
                            D2D1::IdentityMatrix(), &sink);
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to stream D2D path to sink. Code: " << hr;
+    gfxWarning() << "Failed to stream D2D path to sink. Code: " << hexa(hr);
     return;
   }
 }
  
 bool
 PathD2D::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
 {
   BOOL result;
@@ -413,17 +413,17 @@ Rect
 PathD2D::GetBounds(const Matrix &aTransform) const
 {
   D2D1_RECT_F d2dBounds;
 
   HRESULT hr = mGeometry->GetBounds(D2DMatrix(aTransform), &d2dBounds);
 
   Rect bounds = ToRect(d2dBounds);
   if (FAILED(hr) || !bounds.IsFinite()) {
-    gfxWarning() << "Failed to get stroked bounds for path. Code: " << hr;
+    gfxWarning() << "Failed to get stroked bounds for path. Code: " << hexa(hr);
     return Rect();
   }
 
   return bounds;
 }
 
 Rect
 PathD2D::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
@@ -433,17 +433,17 @@ PathD2D::GetStrokedBounds(const StrokeOp
 
   RefPtr<ID2D1StrokeStyle> strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions);
   HRESULT hr =
     mGeometry->GetWidenedBounds(aStrokeOptions.mLineWidth, strokeStyle,
                                 D2DMatrix(aTransform), &d2dBounds);
 
   Rect bounds = ToRect(d2dBounds);
   if (FAILED(hr) || !bounds.IsFinite()) {
-    gfxWarning() << "Failed to get stroked bounds for path. Code: " << hr;
+    gfxWarning() << "Failed to get stroked bounds for path. Code: " << hexa(hr);
     return Rect();
   }
 
   return bounds;
 }
 
 }
 }
--- a/gfx/2d/RadialGradientEffectD2D1.cpp
+++ b/gfx/2d/RadialGradientEffectD2D1.cpp
@@ -377,16 +377,16 @@ RadialGradientEffectD2D1::CreateGradient
   props.bufferPrecision = D2D1_BUFFER_PRECISION_8BPC_UNORM;
   props.filter = D2D1_FILTER_MIN_MAG_MIP_LINEAR;
   D2D1_EXTEND_MODE extendMode[] = { mStopCollection->GetExtendMode(), mStopCollection->GetExtendMode() };
   props.extendModes = extendMode;
 
   HRESULT hr = mEffectContext->CreateResourceTexture(nullptr, &props, &textureData.front(), &stride, 4096 * 4, byRef(tex));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create resource texture: " << hr;
+    gfxWarning() << "Failed to create resource texture: " << hexa(hr);
   }
 
   return tex.forget();
 }
 
 }
 }
--- a/gfx/2d/SourceSurfaceD2D.cpp
+++ b/gfx/2d/SourceSurfaceD2D.cpp
@@ -67,24 +67,24 @@ SourceSurfaceD2D::InitFromData(unsigned 
     gfxDebug() << "Bitmap does not fit in texture.";
     return false;
   }
 
   D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
   hr = aRT->CreateBitmap(D2DIntSize(aSize), props, byRef(mBitmap));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hr;
+    gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hexa(hr);
     return false;
   }
 
   hr = mBitmap->CopyFromMemory(nullptr, aData, aStride);
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to copy data to D2D bitmap. Code: " << hr;
+    gfxWarning() << "Failed to copy data to D2D bitmap. Code: " << hexa(hr);
     return false;
   }
 
   DrawTargetD2D::mVRAMUsageSS += GetByteSize();
   mDevice = Factory::GetDirect3D10Device();
 
   return true;
 }
@@ -96,31 +96,31 @@ SourceSurfaceD2D::InitFromTexture(ID3D10
 {
   HRESULT hr;
 
   RefPtr<IDXGISurface> surf;
 
   hr = aTexture->QueryInterface((IDXGISurface**)&surf);
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to QI texture to surface. Code: " << hr;
+    gfxWarning() << "Failed to QI texture to surface. Code: " << hexa(hr);
     return false;
   }
 
   D3D10_TEXTURE2D_DESC desc;
   aTexture->GetDesc(&desc);
 
   mSize = IntSize(desc.Width, desc.Height);
   mFormat = aFormat;
 
   D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
   hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create SharedBitmap. Code: " << hr;
+    gfxWarning() << "Failed to create SharedBitmap. Code: " << hexa(hr);
     return false;
   }
 
   aTexture->GetDevice(byRef(mDevice));
   DrawTargetD2D::mVRAMUsageSS += GetByteSize();
 
   return true;
 }
@@ -145,37 +145,37 @@ DataSourceSurfaceD2D::DataSourceSurfaceD
   CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
   desc.MipLevels = 1;
   desc.Usage = D3D10_USAGE_DEFAULT;
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   RefPtr<ID3D10Texture2D> sourceTexture;
   HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
                                                         byRef(sourceTexture));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create texture. Code: " << hr;
+    gfxWarning() << "Failed to create texture. Code: " << hexa(hr);
     return;
   }
 
   RefPtr<IDXGISurface> dxgiSurface;
   hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create DXGI surface. Code: " << hr;
+    gfxWarning() << "Failed to create DXGI surface. Code: " << hexa(hr);
     return;
   }
 
   D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
             D2D1_RENDER_TARGET_TYPE_DEFAULT,
             D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
 
   RefPtr<ID2D1RenderTarget> renderTarget;
   hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
                                                                &rtProps,
                                                                byRef(renderTarget));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create render target. Code: " << hr;
+    gfxWarning() << "Failed to create render target. Code: " << hexa(hr);
     return;
   }
 
   renderTarget->BeginDraw();
   renderTarget->Clear(D2D1::ColorF(0, 0.0f));
   if (aSourceSurface->GetFormat() != SurfaceFormat::A8) {
     renderTarget->DrawBitmap(aSourceSurface->mBitmap,
                              D2D1::RectF(0, 0,
@@ -184,26 +184,26 @@ DataSourceSurfaceD2D::DataSourceSurfaceD
   } else {
     RefPtr<ID2D1SolidColorBrush> brush;
     renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), byRef(brush));
     renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
     renderTarget->FillOpacityMask(aSourceSurface->mBitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
   }
   hr = renderTarget->EndDraw();
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to draw bitmap. Code: " << hr;
+    gfxWarning() << "Failed to draw bitmap. Code: " << hexa(hr);
     return;
   }
 
   desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE;
   desc.Usage = D3D10_USAGE_STAGING;
   desc.BindFlags = 0;
   hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create staging texture. Code: " << hr;
+    gfxWarning() << "Failed to create staging texture. Code: " << hexa(hr);
     mTexture = nullptr;
     return;
   }
 
   aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
 }
 
 DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
@@ -268,17 +268,17 @@ DataSourceSurfaceD2D::Map(MapType aMapTy
     mapType = D3D10_MAP_READ_WRITE;
   }
 
   D3D10_MAPPED_TEXTURE2D map;
 
   HRESULT hr = mTexture->Map(0, mapType, 0, &map);
 
   if (FAILED(hr)) {
-    gfxWarning() << "Texture map failed with code: " << hr;
+    gfxWarning() << "Texture map failed with code: " << hexa(hr);
     return false;
   }
 
   aMappedSurface->mData = (uint8_t*)map.pData;
   aMappedSurface->mStride = map.RowPitch;
   mIsMapped = true;
 
   return true;
@@ -301,17 +301,17 @@ DataSourceSurfaceD2D::EnsureMappedTextur
 
   if (mMapped ||
       !mTexture) {
     return;
   }
 
   HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to map texture. Code: " << hr;
+    gfxWarning() << "Failed to map texture. Code: " << hexa(hr);
     mTexture = nullptr;
   } else {
     mMapped = true;
   }
 }
 
 }
 }
--- a/gfx/2d/SourceSurfaceD2DTarget.cpp
+++ b/gfx/2d/SourceSurfaceD2DTarget.cpp
@@ -62,17 +62,17 @@ SourceSurfaceD2DTarget::GetDataSurface()
   desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
   desc.Usage = D3D10_USAGE_STAGING;
   desc.BindFlags = 0;
   desc.MiscFlags = 0;
 
   HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(dataSurf->mTexture));
 
   if (FAILED(hr)) {
-    gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hr;
+    gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hexa(hr);
     return nullptr;
   }
   Factory::GetDirect3D10Device()->CopyResource(dataSurf->mTexture, mTexture);
 
   return dataSurf.forget();
 }
 
 void*
@@ -89,17 +89,17 @@ SourceSurfaceD2DTarget::GetSRView()
 {
   if (mSRView) {
     return mSRView;
   }
 
   HRESULT hr = Factory::GetDirect3D10Device()->CreateShaderResourceView(mTexture, nullptr, byRef(mSRView));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to create ShaderResourceView. Code: " << hr;
+    gfxWarning() << "Failed to create ShaderResourceView. Code: " << hexa(hr);
   }
 
   return mSRView;
 }
 
 void
 SourceSurfaceD2DTarget::DrawTargetWillChange()
 {
@@ -138,31 +138,31 @@ SourceSurfaceD2DTarget::GetBitmap(ID2D1R
   mTexture->GetDesc(&desc);
 
   IntSize size(desc.Width, desc.Height);
   
   RefPtr<IDXGISurface> surf;
   hr = mTexture->QueryInterface((IDXGISurface**)byRef(surf));
 
   if (FAILED(hr)) {
-    gfxWarning() << "Failed to query interface texture to DXGISurface. Code: " << hr;
+    gfxWarning() << "Failed to query interface texture to DXGISurface. Code: " << hexa(hr);
     return nullptr;
   }
 
   D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(mFormat));
   hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, byRef(mBitmap));
 
   if (FAILED(hr)) {
     // This seems to happen for SurfaceFormat::A8 sometimes...
     hr = aRT->CreateBitmap(D2D1::SizeU(desc.Width, desc.Height),
                            D2D1::BitmapProperties(D2DPixelFormat(mFormat)),
                            byRef(mBitmap));
 
     if (FAILED(hr)) {
-      gfxWarning() << "Failed in CreateBitmap. Code: " << hr;
+      gfxWarning() << "Failed in CreateBitmap. Code: " << hexa(hr);
       return nullptr;
     }
 
     RefPtr<ID2D1RenderTarget> rt;
 
     if (mDrawTarget) {
       rt = mDrawTarget->mRT;
     }
@@ -271,17 +271,17 @@ DataSourceSurfaceD2DTarget::Map(MapType 
     mapType = D3D10_MAP_READ_WRITE;
   }
 
   D3D10_MAPPED_TEXTURE2D map;
 
   HRESULT hr = mTexture->Map(0, mapType, 0, &map);
 
   if (FAILED(hr)) {
-    gfxWarning() << "Texture map failed with code: " << hr;
+    gfxWarning() << "Texture map failed with code: " << hexa(hr);
     return false;
   }
 
   aMappedSurface->mData = (uint8_t*)map.pData;
   aMappedSurface->mStride = map.RowPitch;
   mIsMapped = true;
 
   return true;
@@ -299,17 +299,17 @@ DataSourceSurfaceD2DTarget::Unmap()
 void
 DataSourceSurfaceD2DTarget::EnsureMapped()
 {
   // Do not use GetData() after having used Map!
   MOZ_ASSERT(!mIsMapped);
   if (!mMapped) {
     HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mMap);
     if (FAILED(hr)) {
-      gfxWarning() << "Failed to map texture to memory. Code: " << hr;
+      gfxWarning() << "Failed to map texture to memory. Code: " << hexa(hr);
       return;
     }
     mMapped = true;
   }
 }
 
 }
 }
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -283,17 +283,17 @@ TextureClientD3D11::Unlock()
     desc.Usage = D3D10_USAGE_STAGING;
     desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
     desc.MiscFlags = 0;
 
     RefPtr<ID3D10Texture2D> tex;
     HRESULT hr = device->CreateTexture2D(&desc, nullptr, byRef(tex));
 
     if (FAILED(hr)) {
-      gfx::gfxCriticalError() << "[D3D11] CreateTexture2D failure " << mSize << " Code: " << hr;
+      gfx::gfxCriticalError() << "[D3D11] CreateTexture2D failure " << mSize << " Code: " << gfx::hexa(hr);
       return;
     }
 
     if (SUCCEEDED(hr)) {
       device->CopyResource(tex, mTexture10);
 
       gfxWindowsPlatform::GetPlatform()->GetReadbackManager()->PostTask(tex, mReadbackSink);
     } else {
@@ -370,17 +370,17 @@ TextureClientD3D11::AllocateForSurface(g
       D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
 
     newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
 
     hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture10));
   }
 
   if (FAILED(hr)) {
-    gfx::gfxCriticalError() << "[D3D11] CreateTexture2D failure " << aSize << " Code: " << hr;
+    gfx::gfxCriticalError() << "[D3D11] CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
     return false;
   }
 
   // Defer clearing to the next time we lock to avoid an extra (expensive) lock.
   mNeedsClear = aFlags & ALLOC_CLEAR_BUFFER;
   mNeedsClearWhite = aFlags & ALLOC_CLEAR_BUFFER_WHITE;
 
   return true;
--- a/js/public/OldDebugAPI.h
+++ b/js/public/OldDebugAPI.h
@@ -14,93 +14,33 @@
 #include "mozilla/NullPtr.h"
 
 #include "jsapi.h"
 #include "jsbytecode.h"
 
 #include "js/CallArgs.h"
 #include "js/TypeDecls.h"
 
-class JSAtom;
-struct JSFreeOp;
-
-namespace js {
-class InterpreterFrame;
-class FrameIter;
-class ScriptSource;
-}
-
-
-namespace JS {
-
-extern JS_PUBLIC_API(char *)
-FormatStackDump(JSContext *cx, char *buf, bool showArgs, bool showLocals, bool showThisProps);
-
-} // namespace JS
-
-# ifdef JS_DEBUG
-JS_FRIEND_API(void) js_DumpValue(const JS::Value &val);
-JS_FRIEND_API(void) js_DumpId(jsid id);
-JS_FRIEND_API(void) js_DumpInterpreterFrame(JSContext *cx, js::InterpreterFrame *start = nullptr);
-# endif
-
-JS_FRIEND_API(void)
-js_DumpBacktrace(JSContext *cx);
-
 typedef enum JSTrapStatus {
     JSTRAP_ERROR,
     JSTRAP_CONTINUE,
     JSTRAP_RETURN,
     JSTRAP_THROW,
     JSTRAP_LIMIT
 } JSTrapStatus;
 
-extern JS_PUBLIC_API(JSString *)
-JS_DecompileScript(JSContext *cx, JS::HandleScript script, const char *name, unsigned indent);
-
-
 /************************************************************************/
 
-// Raw JSScript* because this needs to be callable from a signal handler.
-extern JS_PUBLIC_API(unsigned)
-JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
-
-extern JS_PUBLIC_API(jsbytecode *)
-JS_LineNumberToPC(JSContext *cx, JSScript *script, unsigned lineno);
-
 extern JS_PUBLIC_API(JSScript *)
 JS_GetFunctionScript(JSContext *cx, JS::HandleFunction fun);
 
-
 /************************************************************************/
 
 extern JS_PUBLIC_API(const char *)
 JS_GetScriptFilename(JSScript *script);
 
 extern JS_PUBLIC_API(const char16_t *)
 JS_GetScriptSourceMap(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(unsigned)
 JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
 
-extern JS_PUBLIC_API(unsigned)
-JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
-
-
-/************************************************************************/
-
-/**
- * Add various profiling-related functions as properties of the given object.
- */
-extern JS_PUBLIC_API(bool)
-JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj);
-
-/* Defined in vm/Debugger.cpp. */
-extern JS_PUBLIC_API(bool)
-JS_DefineDebuggerObject(JSContext *cx, JS::HandleObject obj);
-
-extern JS_PUBLIC_API(void)
-JS_DumpPCCounts(JSContext *cx, JS::HandleScript script);
-
-extern JS_PUBLIC_API(void)
-JS_DumpCompartmentPCCounts(JSContext *cx);
-
 #endif /* js_OldDebugAPI_h */
--- a/js/src/builtin/Profilers.cpp
+++ b/js/src/builtin/Profilers.cpp
@@ -414,20 +414,18 @@ static const JSFunctionSpec profiling_fu
     JS_FN("dumpCallgrind",  DumpCallgrind,        1,0),
 #endif
     JS_FS_END
 };
 
 #endif
 
 JS_PUBLIC_API(bool)
-JS_DefineProfilingFunctions(JSContext *cx, JSObject *objArg)
+JS_DefineProfilingFunctions(JSContext *cx, HandleObject obj)
 {
-    RootedObject obj(cx, objArg);
-
     assertSameCompartment(cx, obj);
 #ifdef MOZ_PROFILING
     return JS_DefineFunctions(cx, obj, profiling_functions);
 #else
     return true;
 #endif
 }
 
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -865,16 +865,35 @@ CountHeap(JSContext *cx, unsigned argc, 
         JS_ReportOutOfMemory(cx);
         return false;
     }
 
     args.rval().setNumber(double(counter));
     return true;
 }
 
+// Stolen from jsmath.cpp
+static const uint64_t RNG_MULTIPLIER = 0x5DEECE66DLL;
+static const uint64_t RNG_MASK = (1LL << 48) - 1;
+
+static bool
+SetSavedStacksRNGState(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (!args.requireAtLeast(cx, "setSavedStacksRNGState", 1))
+        return false;
+
+    int32_t seed;
+    if (!ToInt32(cx, args[0], &seed))
+        return false;
+
+    cx->compartment()->savedStacks().setRNGState((seed ^ RNG_MULTIPLIER) & RNG_MASK);
+    return true;
+}
+
 static bool
 GetSavedFrameCount(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setNumber(cx->compartment()->savedStacks().count());
     return true;
 }
 
@@ -2052,16 +2071,20 @@ static const JSFunctionSpecWithHelp Test
 "countHeap([start[, kind[, thing]]])",
 "  Count the number of live GC things in the heap or things reachable from\n"
 "  start when it is given and is not null. kind is either 'all' (default) to\n"
 "  count all things or one of 'object', 'double', 'string', 'function'\n"
 "  to count only things of that kind. If kind is the string 'specific',\n"
 "  then you can provide an extra argument with some specific traceable\n"
 "  thing to count.\n"),
 
+    JS_FN_HELP("setSavedStacksRNGState", SetSavedStacksRNGState, 1, 0,
+"setSavedStacksRNGState(seed)",
+"  Set this compartment's SavedStacks' RNG state.\n"),
+
     JS_FN_HELP("getSavedFrameCount", GetSavedFrameCount, 0, 0,
 "getSavedFrameCount()",
 "  Return the number of SavedFrame instances stored in this compartment's\n"
 "  SavedStacks cache."),
 
     JS_FN_HELP("saveStack", SaveStack, 0, 0,
 "saveStack()",
 "  Capture a stack.\n"),
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
@@ -1315,17 +1315,17 @@ NativeRegExpMacroAssembler::CheckSpecial
       default:
         return false;
     }
 }
 
 bool
 NativeRegExpMacroAssembler::CanReadUnaligned()
 {
-#if defined(JS_CODEGEN_MIPS)
+#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
     return false;
 #else
     return true;
 #endif
 }
 
 const uint8_t
 NativeRegExpMacroAssembler::word_character_map[] =
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Memory-allocationSamplingProbability-01.js
@@ -0,0 +1,21 @@
+// Test that setting Debugger.Memory.prototype.allocationSamplingProbability to
+// a bad number throws.
+
+load(libdir + "asserts.js");
+
+const root = newGlobal();
+
+const dbg = new Debugger();
+const wrappedRoot = dbg.addDebuggee(root);
+
+// Out of range.
+
+assertThrowsInstanceOf(() => dbg.memory.allocationSamplingProbability = -1,
+                       TypeError);
+assertThrowsInstanceOf(() => dbg.memory.allocationSamplingProbability = 2,
+                       TypeError);
+
+// In range
+dbg.memory.allocationSamplingProbability = 0;
+dbg.memory.allocationSamplingProbability = 1;
+dbg.memory.allocationSamplingProbability = .5;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Memory-allocationSamplingProbability-02.js
@@ -0,0 +1,36 @@
+// Test that we only sample about allocationSamplingProbability * 100 percent of
+// allocations.
+
+const root = newGlobal();
+
+const dbg = new Debugger();
+const wrappedRoot = dbg.addDebuggee(root);
+
+root.eval(`
+  objs = [];
+  objs.push(new Object);
+`);
+
+root.eval("" + function makeSomeAllocations() {
+  for (var i = 0; i < 100; i++) {
+    objs.push(new Object);
+  }
+});
+
+function measure(P, expected) {
+  root.setSavedStacksRNGState(Number.MAX_SAFE_INTEGER - 1);
+  dbg.memory.allocationSamplingProbability = P;
+  root.makeSomeAllocations();
+  assertEq(dbg.memory.drainAllocationsLog().length, expected);
+}
+
+dbg.memory.trackingAllocationSites = true;
+
+// These are the sample counts that were correct when this test was last
+// updated; changes to SpiderMonkey may occasionally cause changes
+// here. Anything that is within a plausible range for the given sampling
+// probability is fine.
+measure(0.0, 0);
+measure(1.0, 100);
+measure(0.1, 9);
+measure(0.5, 51);
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -374,16 +374,43 @@ struct BaselineStackBuilder
 #elif defined(JS_CODEGEN_NONE)
         MOZ_CRASH();
 #else
 #  error "Bad architecture!"
 #endif
     }
 };
 
+// Ensure that all value locations are readable from the SnapshotIterator.
+// Remove RInstructionResults from the JitActivation if the frame got recovered
+// ahead of the bailout.
+class SnapshotIteratorForBailout : public SnapshotIterator
+{
+    RInstructionResults results_;
+  public:
+
+    SnapshotIteratorForBailout(const IonBailoutIterator &iter)
+      : SnapshotIterator(iter),
+        results_()
+    {
+    }
+
+    // Take previously computed result out of the activation, or compute the
+    // results of all recover instructions contained in the snapshot.
+    bool init(JSContext *cx, JitActivation *activation) {
+        activation->maybeTakeIonFrameRecovery(fp_, &results_);
+        if (!results_.isInitialized() && !computeInstructionResults(cx, &results_))
+            return false;
+
+        MOZ_ASSERT(results_.isInitialized());
+        instructionResults_ = &results_;
+        return true;
+    }
+};
+
 static inline bool
 IsInlinableFallback(ICFallbackStub *icEntry)
 {
     return icEntry->isCall_Fallback() || icEntry->isGetProp_Fallback() ||
            icEntry->isSetProp_Fallback();
 }
 
 static inline void*
@@ -1338,20 +1365,18 @@ jit::BailoutIonToBaseline(JSContext *cx,
     iter.script()->updateBaselineOrIonRaw(cx);
 
     // Allocate buffer to hold stack replacement data.
     BaselineStackBuilder builder(iter, 1024);
     if (!builder.init())
         return BAILOUT_RETURN_FATAL_ERROR;
     JitSpew(JitSpew_BaselineBailouts, "  Incoming frame ptr = %p", builder.startFrame());
 
-    AutoValueVector instructionResults(cx);
-    SnapshotIterator snapIter(iter);
-
-    if (!snapIter.initIntructionResults(instructionResults))
+    SnapshotIteratorForBailout snapIter(iter);
+    if (!snapIter.init(cx, activation))
         return BAILOUT_RETURN_FATAL_ERROR;
 
 #ifdef TRACK_SNAPSHOTS
     snapIter.spewBailingFrom();
 #endif
 
     RootedFunction callee(cx, iter.maybeCallee());
     RootedScript scr(cx, iter.script());
@@ -1375,22 +1400,18 @@ jit::BailoutIonToBaseline(JSContext *cx,
     jsbytecode *callerPC = nullptr;
     RootedFunction fun(cx, callee);
     AutoValueVector startFrameFormals(cx);
 
     RootedScript topCaller(cx);
     jsbytecode *topCallerPC = nullptr;
 
     while (true) {
-        if (!snapIter.instruction()->isResumePoint()) {
-            if (!snapIter.instruction()->recover(cx, snapIter))
-                return BAILOUT_RETURN_FATAL_ERROR;
-            snapIter.nextInstruction();
-            continue;
-        }
+        // Skip recover instructions as they are already recovered by |initInstructionResults|.
+        snapIter.settleOnFrame();
 
         if (frameNo > 0) {
             TraceLogStartEvent(logger, TraceLogCreateTextId(logger, scr));
             TraceLogStartEvent(logger, TraceLogger::Baseline);
         }
 
         JitSpew(JitSpew_BaselineBailouts, "    FrameNo %d", frameNo);
 
--- a/js/src/jit/CompileInfo.h
+++ b/js/src/jit/CompileInfo.h
@@ -439,41 +439,71 @@ class CompileInfo
         return executionMode_ == ParallelExecution;
     }
 
     // Returns true if a slot can be observed out-side the current frame while
     // the frame is active on the stack.  This implies that these definitions
     // would have to be executed and that they cannot be removed even if they
     // are unused.
     bool isObservableSlot(uint32_t slot) const {
+        if (isObservableFrameSlot(slot))
+            return true;
+
+        if (isObservableArgumentSlot(slot))
+            return true;
+
+        return false;
+    }
+
+    bool isObservableFrameSlot(uint32_t slot) const {
         if (!funMaybeLazy())
             return false;
 
         // The |this| value must always be observable.
         if (slot == thisSlot())
             return true;
 
         // If the function may need an arguments object, then make sure to
         // preserve the scope chain, because it may be needed to construct the
         // arguments object during bailout. If we've already created an
         // arguments object (or got one via OSR), preserve that as well.
         if (hasArguments() && (slot == scopeChainSlot() || slot == argsObjSlot()))
             return true;
 
+        return false;
+    }
+
+    bool isObservableArgumentSlot(uint32_t slot) const {
+        if (!funMaybeLazy())
+            return false;
+
         // Function.arguments can be used to access all arguments in non-strict
         // scripts, so we can't optimize out any arguments.
         if ((hasArguments() || !script()->strict()) &&
             firstArgSlot() <= slot && slot - firstArgSlot() < nargs())
         {
             return true;
         }
 
         return false;
     }
 
+    // Returns true if a slot can be recovered before or during a bailout.  A
+    // definition which can be observed and recovered, implies that this
+    // definition can be optimized away as long as we can compute its values.
+    bool isRecoverableOperand(uint32_t slot) const {
+        if (isObservableFrameSlot(slot))
+            return false;
+
+        if (needsArgsObj() && isObservableArgumentSlot(slot))
+            return false;
+
+        return true;
+    }
+
   private:
     unsigned nimplicit_;
     unsigned nargs_;
     unsigned nbodyfixed_;
     unsigned nlocals_;
     unsigned nstack_;
     unsigned nslots_;
     unsigned fixedLexicalBegin_;
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2900,16 +2900,27 @@ void
 jit::Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses,
                 bool cancelOffThread)
 {
     jit::Invalidate(cx->zone()->types, cx->runtime()->defaultFreeOp(), invalid, resetUses,
                     cancelOffThread);
 }
 
 bool
+jit::IonScript::invalidate(JSContext *cx, bool resetUses, const char *reason)
+{
+    JitSpew(JitSpew_IonInvalidate, " Invalidate IonScript %p: %s", this, reason);
+    Vector<types::RecompileInfo> list(cx);
+    if (!list.append(recompileInfo()))
+        return false;
+    Invalidate(cx, list, resetUses, true);
+    return true;
+}
+
+bool
 jit::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses,
                 bool cancelOffThread)
 {
     JS_ASSERT(script->hasIonScript());
 
     if (cx->runtime()->spsProfiler.enabled()) {
         // Register invalidation with profiler.
         // Format of event payload string:
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -577,16 +577,20 @@ struct IonScript
     void copyCallTargetEntries(JSScript **callTargets);
     void copyPatchableBackedges(JSContext *cx, JitCode *code,
                                 PatchableBackedgeInfo *backedges,
                                 MacroAssembler &masm);
 
     bool invalidated() const {
         return refcount_ != 0;
     }
+
+    // Invalidate the current compilation.
+    bool invalidate(JSContext *cx, bool resetUses, const char *reason);
+
     size_t refcount() const {
         return refcount_;
     }
     void incref() {
         refcount_++;
     }
     void decref(FreeOp *fop) {
         JS_ASSERT(refcount_);
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -1279,16 +1279,17 @@ MarkJitActivation(JSTracer *trc, const J
         // GC can modify spilled registers, breaking our register checks.
         // To handle this, we disable these checks for the current VM call
         // when a GC happens.
         activation->setCheckRegs(false);
     }
 #endif
 
     activation->markRematerializedFrames(trc);
+    activation->markIonRecovery(trc);
 
     for (JitFrameIterator frames(activations); !frames.done(); ++frames) {
         switch (frames.type()) {
           case JitFrame_Exit:
             MarkJitExitFrame(trc, frames);
             break;
           case JitFrame_BaselineJS:
             frames.baselineFrame()->trace(trc, frames);
@@ -1431,16 +1432,89 @@ uint32_t
 OsiIndex::returnPointDisplacement() const
 {
     // In general, pointer arithmetic on code is bad, but in this case,
     // getting the return address from a call instruction, stepping over pools
     // would be wrong.
     return callPointDisplacement_ + Assembler::PatchWrite_NearCallSize();
 }
 
+RInstructionResults::RInstructionResults()
+  : results_(nullptr),
+    fp_(nullptr)
+{
+}
+
+RInstructionResults::RInstructionResults(RInstructionResults&& src)
+  : results_(mozilla::Move(src.results_)),
+    fp_(src.fp_)
+{
+    src.fp_ = nullptr;
+}
+
+RInstructionResults&
+RInstructionResults::operator=(RInstructionResults&& rhs)
+{
+    MOZ_ASSERT(&rhs != this, "self-moves are prohibited");
+    this->~RInstructionResults();
+    new(this) RInstructionResults(mozilla::Move(rhs));
+    return *this;
+}
+
+RInstructionResults::~RInstructionResults()
+{
+    // results_ is freed by the UniquePtr.
+}
+
+bool
+RInstructionResults::init(JSContext *cx, uint32_t numResults, IonJSFrameLayout *fp)
+{
+    if (numResults) {
+        results_ = cx->make_unique<Values>();
+        if (!results_ || !results_->growBy(numResults))
+            return false;
+
+        Value guard = MagicValue(JS_ION_BAILOUT);
+        for (size_t i = 0; i < numResults; i++)
+            (*results_)[i].init(guard);
+    }
+
+    fp_ = fp;
+    return true;
+}
+
+bool
+RInstructionResults::isInitialized() const
+{
+    MOZ_ASSERT_IF(results_, fp_);
+    return fp_;
+}
+
+IonJSFrameLayout *
+RInstructionResults::frame() const
+{
+    MOZ_ASSERT(isInitialized());
+    return fp_;
+}
+
+RelocatableValue&
+RInstructionResults::operator [](size_t index)
+{
+    return (*results_)[index];
+}
+
+void
+RInstructionResults::trace(JSTracer *trc)
+{
+    // Note: The vector necessary exists, otherwise this object would not have
+    // been stored on the activation from where the trace function is called.
+    gc::MarkValueRange(trc, results_->length(), results_->begin(), "ion-recover-results");
+}
+
+
 SnapshotIterator::SnapshotIterator(IonScript *ionScript, SnapshotOffset snapshotOffset,
                                    IonJSFrameLayout *fp, const MachineState &machine)
   : snapshot_(ionScript->snapshots(),
               snapshotOffset,
               ionScript->snapshotsRVATableSize(),
               ionScript->snapshotsListSize()),
     recover_(snapshot_,
              ionScript->recovers(),
@@ -1694,43 +1768,110 @@ SnapshotIterator::skipInstruction()
     MOZ_ASSERT(snapshot_.numAllocationsRead() == 0);
     size_t numOperands = instruction()->numOperands();
     for (size_t i = 0; i < numOperands; i++)
         skip();
     nextInstruction();
 }
 
 bool
-SnapshotIterator::initIntructionResults(AutoValueVector &results)
+SnapshotIterator::initInstructionResults(MaybeReadFallback &fallback)
 {
-    MOZ_ASSERT(recover_.numInstructionsRead() == 1);
+    MOZ_ASSERT(fallback.canRecoverResults());
+    JSContext *cx = fallback.maybeCx;
 
-    // The last instruction will always be a resume point, no need to allocate
-    // space for it.
+    // If there is only one resume point in the list of instructions, then there
+    // is no instruction to recover, and thus no need to register any results.
     if (recover_.numInstructions() == 1)
         return true;
 
-    MOZ_ASSERT(recover_.numInstructions() > 1);
-    size_t numResults = recover_.numInstructions() - 1;
-    if (!results.reserve(numResults))
-        return false;
+    IonJSFrameLayout *fp = fallback.frame->jsFrame();
+    RInstructionResults *results = fallback.activation->maybeIonFrameRecovery(fp);
+    if (!results) {
+        // We do not have the result yet, which means that an observable stack
+        // slot is requested.  As we do not want to bailout every time for the
+        // same reason, we need to recompile without optimizing away the
+        // observable stack slots.  The script would later be recompiled to have
+        // support for Argument objects.
+        if (!ionScript_->invalidate(cx, /* resetUses = */ false, "Observe recovered instruction."))
+            return false;
+
+        // Register the list of result on the activation.  We need to do that
+        // before we initialize the list such as if any recover instruction
+        // cause a GC, we can ensure that the results are properly traced by the
+        // activation.
+        RInstructionResults tmp;
+        if (!fallback.activation->registerIonFrameRecovery(fallback.frame->jsFrame(),
+                                                           mozilla::Move(tmp)))
+            return false;
+
+        results = fallback.activation->maybeIonFrameRecovery(fp);
+
+        // Start a new snapshot at the beginning of the JitFrameIterator.  This
+        // SnapshotIterator is used for evaluating the content of all recover
+        // instructions.  The result is then saved on the JitActivation.
+        SnapshotIterator s(*fallback.frame);
+        if (!s.computeInstructionResults(cx, results)) {
+
+            // If the evaluation failed because of OOMs, then we discard the
+            // current set of result that we collected so far.
+            fallback.activation->maybeTakeIonFrameRecovery(fp, &tmp);
+            return false;
+        }
+    }
 
-    for (size_t i = 0; i < numResults; i++)
-        results.infallibleAppend(MagicValue(JS_ION_BAILOUT));
+    MOZ_ASSERT(results->isInitialized());
+    instructionResults_ = results;
+    return true;
+}
+
+bool
+SnapshotIterator::computeInstructionResults(JSContext *cx, RInstructionResults *results) const
+{
+    MOZ_ASSERT(!results->isInitialized());
+    MOZ_ASSERT(recover_.numInstructionsRead() == 1);
+
+    // The last instruction will always be a resume point.
+    size_t numResults = recover_.numInstructions() - 1;
+    if (!results->isInitialized()) {
+        if (!results->init(cx, numResults, fp_))
+            return false;
 
-    instructionResults_ = &results;
+        // No need to iterate over the only resume point.
+        if (!numResults) {
+            MOZ_ASSERT(results->isInitialized());
+            return true;
+        }
+
+        // Fill with the results of recover instructions.
+        SnapshotIterator s(*this);
+        s.instructionResults_ = results;
+        while (s.moreInstructions()) {
+            // Skip resume point and only interpret recover instructions.
+            if (s.instruction()->isResumePoint()) {
+                s.skipInstruction();
+                continue;
+            }
+
+            if (!s.instruction()->recover(cx, s))
+                return false;
+            s.nextInstruction();
+        }
+    }
+
+    MOZ_ASSERT(results->isInitialized());
     return true;
 }
 
 void
 SnapshotIterator::storeInstructionResult(Value v)
 {
     uint32_t currIns = recover_.numInstructionsRead() - 1;
     MOZ_ASSERT((*instructionResults_)[currIns].isMagic(JS_ION_BAILOUT));
-    (*instructionResults_)[currIns].set(v);
+    (*instructionResults_)[currIns] = v;
 }
 
 Value
 SnapshotIterator::fromInstructionResult(uint32_t index) const
 {
     MOZ_ASSERT(!(*instructionResults_)[index].isMagic(JS_ION_BAILOUT));
     return (*instructionResults_)[index];
 }
@@ -1746,16 +1887,38 @@ SnapshotIterator::settleOnFrame()
 
 void
 SnapshotIterator::nextFrame()
 {
     nextInstruction();
     settleOnFrame();
 }
 
+Value
+SnapshotIterator::maybeReadAllocByIndex(size_t index)
+{
+    while (index--) {
+        JS_ASSERT(moreAllocations());
+        skip();
+    }
+
+    Value s;
+    {
+        // This MaybeReadFallback method cannot GC.
+        JS::AutoSuppressGCAnalysis nogc;
+        MaybeReadFallback fallback(UndefinedValue());
+        s = maybeRead(fallback);
+    }
+
+    while (moreAllocations())
+        skip();
+
+    return s;
+}
+
 IonScript *
 JitFrameIterator::ionScript() const
 {
     JS_ASSERT(type() == JitFrame_IonJS);
 
     IonScript *ionScript = nullptr;
     if (checkInvalidation(&ionScript))
         return ionScript;
@@ -2119,37 +2282,38 @@ InlineFrameIterator::dump() const
     fprintf(stderr, "  script = %p, pc = %p\n", (void*) script(), pc());
     fprintf(stderr, "  current op: %s\n", js_CodeName[*pc()]);
 
     if (!more()) {
         numActualArgs();
     }
 
     SnapshotIterator si = snapshotIterator();
+    MaybeReadFallback fallback(UndefinedValue());
     fprintf(stderr, "  slots: %u\n", si.numAllocations() - 1);
     for (unsigned i = 0; i < si.numAllocations() - 1; i++) {
         if (isFunction) {
             if (i == 0)
                 fprintf(stderr, "  scope chain: ");
             else if (i == 1)
                 fprintf(stderr, "  this: ");
             else if (i - 2 < callee()->nargs())
                 fprintf(stderr, "  formal (arg %d): ", i - 2);
             else {
                 if (i - 2 == callee()->nargs() && numActualArgs() > callee()->nargs()) {
                     DumpOp d(callee()->nargs());
-                    unaliasedForEachActual(GetJSContextFromJitCode(), d, ReadFrame_Overflown);
+                    unaliasedForEachActual(GetJSContextFromJitCode(), d, ReadFrame_Overflown, fallback);
                 }
 
                 fprintf(stderr, "  slot %d: ", int(i - 2 - callee()->nargs()));
             }
         } else
             fprintf(stderr, "  slot %u: ", i);
 #ifdef DEBUG
-        js_DumpValue(si.maybeRead());
+        js_DumpValue(si.maybeRead(fallback));
 #else
         fprintf(stderr, "?\n");
 #endif
     }
 
     fputc('\n', stderr);
 }
 
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -261,30 +261,101 @@ class JitFrameIterator
 
 #ifdef DEBUG
     bool verifyReturnAddressUsingNativeToBytecodeMap();
 #else
     inline bool verifyReturnAddressUsingNativeToBytecodeMap() { return true; }
 #endif
 };
 
-class IonJSFrameLayout;
+class RInstructionResults
+{
+    // Vector of results of recover instructions.
+    typedef mozilla::Vector<RelocatableValue, 1, SystemAllocPolicy> Values;
+    mozilla::UniquePtr<Values, JS::DeletePolicy<Values> > results_;
+
+    // The frame pointer is used as a key to check if the current frame already
+    // bailed out.
+    IonJSFrameLayout *fp_;
+
+  public:
+    RInstructionResults();
+    RInstructionResults(RInstructionResults&& src);
+
+    RInstructionResults& operator=(RInstructionResults&& rhs);
+
+    ~RInstructionResults();
+
+    bool init(JSContext *cx, uint32_t numResults, IonJSFrameLayout *fp);
+    bool isInitialized() const;
+
+    IonJSFrameLayout *frame() const;
+
+    RelocatableValue& operator[](size_t index);
+
+    void trace(JSTracer *trc);
+};
+
+struct MaybeReadFallback
+{
+    enum NoGCValue {
+        NoGC_UndefinedValue,
+        NoGC_MagicOptimizedOut
+    };
+
+    JSContext *maybeCx;
+    JitActivation *activation;
+    JitFrameIterator *frame;
+    const NoGCValue unreadablePlaceholder_;
+
+    MaybeReadFallback(const Value &placeholder = UndefinedValue())
+      : maybeCx(nullptr),
+        activation(nullptr),
+        frame(nullptr),
+        unreadablePlaceholder_(noGCPlaceholder(placeholder))
+    {
+    }
+
+    MaybeReadFallback(JSContext *cx, JitActivation *activation, JitFrameIterator *frame)
+      : maybeCx(cx),
+        activation(activation),
+        frame(frame),
+        unreadablePlaceholder_(NoGC_UndefinedValue)
+    {
+    }
+
+    bool canRecoverResults() { return maybeCx; }
+
+    Value unreadablePlaceholder() const {
+        if (unreadablePlaceholder_ == NoGC_MagicOptimizedOut)
+            return MagicValue(JS_OPTIMIZED_OUT);
+        return UndefinedValue();
+    }
+
+    NoGCValue noGCPlaceholder(Value v) const {
+        if (v.isMagic(JS_OPTIMIZED_OUT))
+            return NoGC_MagicOptimizedOut;
+        return NoGC_UndefinedValue;
+    }
+};
+
 
 class RResumePoint;
 
 // Reads frame information in snapshot-encoding order (that is, outermost frame
 // to innermost frame).
 class SnapshotIterator
 {
+  protected:
     SnapshotReader snapshot_;
     RecoverReader recover_;
     IonJSFrameLayout *fp_;
     MachineState machine_;
     IonScript *ionScript_;
-    AutoValueVector *instructionResults_;
+    RInstructionResults *instructionResults_;
 
   private:
     // Read a spilled register from the machine state.
     bool hasRegister(Register reg) const {
         return machine_.has(reg);
     }
     uintptr_t fromRegister(Register reg) const {
         return machine_.read(reg);
@@ -330,16 +401,20 @@ class SnapshotIterator
 
     uint32_t numAllocations() const;
     inline bool moreAllocations() const {
         return snapshot_.numAllocationsRead() < numAllocations();
     }
 
     int32_t readOuterNumActualArgs() const;
 
+    // Used by recover instruction to store the value back into the instruction
+    // results array.
+    void storeInstructionResult(Value v);
+
   public:
     // Exhibits frame properties contained in the snapshot.
     uint32_t pcOffset() const;
     inline bool resumeAfter() const {
         // Inline frames are inlined on calls, which are considered as being
         // resumed on the Call as baseline will push the pc once we return from
         // the call.
         if (moreFrames())
@@ -362,23 +437,26 @@ class SnapshotIterator
     // Skip an Instruction by walking to the next instruction and by skipping
     // all the allocations corresponding to this instruction.
     void skipInstruction();
 
     inline bool moreInstructions() const {
         return recover_.moreInstructions();
     }
 
+  protected:
     // Register a vector used for storing the results of the evaluation of
     // recover instructions. This vector should be registered before the
     // beginning of the iteration. This function is in charge of allocating
     // enough space for all instructions results, and return false iff it fails.
-    bool initIntructionResults(AutoValueVector &results);
+    bool initInstructionResults(MaybeReadFallback &fallback);
 
-    void storeInstructionResult(Value v);
+    // This function is used internally for computing the result of the recover
+    // instructions.
+    bool computeInstructionResults(JSContext *cx, RInstructionResults *results) const;
 
   public:
     // Handle iterating over frames of the snapshots.
     void nextFrame();
     void settleOnFrame();
 
     inline bool moreFrames() const {
         // The last instruction is recovering the innermost frame, so as long as
@@ -394,23 +472,33 @@ class SnapshotIterator
                      IonJSFrameLayout *fp, const MachineState &machine);
     explicit SnapshotIterator(const JitFrameIterator &iter);
     explicit SnapshotIterator(const IonBailoutIterator &iter);
     SnapshotIterator();
 
     Value read() {
         return allocationValue(readAllocation());
     }
-    Value maybeRead(const Value &placeholder = UndefinedValue(), bool silentFailure = false) {
+
+    Value maybeRead(MaybeReadFallback &fallback) {
         RValueAllocation a = readAllocation();
         if (allocationReadable(a))
             return allocationValue(a);
-        if (!silentFailure)
-            warnUnreadableAllocation();
-        return placeholder;
+
+        if (fallback.canRecoverResults()) {
+            if (!initInstructionResults(fallback))
+                return fallback.unreadablePlaceholder();
+
+            if (allocationReadable(a))
+                return allocationValue(a);
+
+            MOZ_ASSERT_UNREACHABLE("All allocations should be readable.");
+        }
+
+        return fallback.unreadablePlaceholder();
     }
 
     void readCommonFrameSlots(Value *scopeChain, Value *rval) {
         if (scopeChain)
             *scopeChain = read();
         else
             skip();
 
@@ -418,18 +506,17 @@ class SnapshotIterator
             *rval = read();
         else
             skip();
     }
 
     template <class Op>
     void readFunctionFrameArgs(Op &op, ArgumentsObject **argsObj, Value *thisv,
                                unsigned start, unsigned end, JSScript *script,
-                               const Value &unreadablePlaceholder = UndefinedValue(),
-                               bool silentFailure = false)
+                               MaybeReadFallback &fallback)
     {
         // Assumes that the common frame arguments have already been read.
         if (script->argumentsHasVarBinding()) {
             if (argsObj) {
                 Value v = read();
                 if (v.isObject())
                     *argsObj = &v.toObject().as<ArgumentsObject>();
             } else {
@@ -447,34 +534,24 @@ class SnapshotIterator
             i = start;
 
         for (; i < start; i++)
             skip();
         for (; i < end; i++) {
             // We are not always able to read values from the snapshots, some values
             // such as non-gc things may still be live in registers and cause an
             // error while reading the machine state.
-            Value v = maybeRead(unreadablePlaceholder, silentFailure);
+            Value v = maybeRead(fallback);
             op(v);
         }
     }
 
-    Value maybeReadAllocByIndex(size_t index) {
-        while (index--) {
-            JS_ASSERT(moreAllocations());
-            skip();
-        }
-
-        Value s = maybeRead(/* placeholder = */ UndefinedValue(), true);
-
-        while (moreAllocations())
-            skip();
-
-        return s;
-    }
+    // Iterate over all the allocations and return only the value of the
+    // allocation located at one index.
+    Value maybeReadAllocByIndex(size_t index);
 
 #ifdef TRACK_SNAPSHOTS
     void spewBailingFrom() const {
         snapshot_.spewBailingFrom();
     }
 #endif
 };
 
@@ -535,18 +612,17 @@ class InlineFrameIterator
         return frame_->numActualArgs();
     }
 
     template <class ArgOp, class LocalOp>
     void readFrameArgsAndLocals(ThreadSafeContext *cx, ArgOp &argOp, LocalOp &localOp,
                                 JSObject **scopeChain, Value *rval,
                                 ArgumentsObject **argsObj, Value *thisv,
                                 ReadFrameArgsBehavior behavior,
-                                const Value &unreadablePlaceholder = UndefinedValue(),
-                                bool silentFailure = false) const
+                                MaybeReadFallback &fallback) const
     {
         SnapshotIterator s(si_);
 
         // Read frame slots common to both function and global frames.
         Value scopeChainValue;
         s.readCommonFrameSlots(&scopeChainValue, rval);
 
         if (scopeChain)
@@ -555,20 +631,18 @@ class InlineFrameIterator
         // Read arguments, which only function frames have.
         if (isFunctionFrame()) {
             unsigned nactual = numActualArgs();
             unsigned nformal = callee()->nargs();
 
             // Get the non overflown arguments, which are taken from the inlined
             // frame, because it will have the updated value when JSOP_SETARG is
             // done.
-            if (behavior != ReadFrame_Overflown) {
-                s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script(),
-                                        unreadablePlaceholder, silentFailure);
-            }
+            if (behavior != ReadFrame_Overflown)
+                s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script(), fallback);
 
             if (behavior != ReadFrame_Formals) {
                 if (more()) {
                     // There is still a parent frame of this inlined frame.  All
                     // arguments (also the overflown) are the last pushed values
                     // in the parent frame.  To get the overflown arguments, we
                     // need to take them from there.
 
@@ -587,17 +661,17 @@ class InlineFrameIterator
                     unsigned skip = parent_s.numAllocations() - nactual - 3 - argsObjAdj;
                     for (unsigned j = 0; j < skip; j++)
                         parent_s.skip();
 
                     // Get the overflown arguments
                     parent_s.readCommonFrameSlots(nullptr, nullptr);
                     parent_s.readFunctionFrameArgs(argOp, nullptr, nullptr,
                                                    nformal, nactual, it.script(),
-                                                   unreadablePlaceholder, silentFailure);
+                                                   fallback);
                 } else {
                     // There is no parent frame to this inlined frame, we can read
                     // from the frame's Value vector directly.
                     Value *argv = frame_->actualArgs();
                     for (unsigned i = nformal; i < nactual; i++)
                         argOp(argv[i]);
                 }
             }
@@ -606,26 +680,27 @@ class InlineFrameIterator
         // At this point we've read all the formals in s, and can read the
         // locals.
         for (unsigned i = 0; i < script()->nfixed(); i++) {
             // We have to use maybeRead here, some of these might be recover
             // instructions, and currently InlineFrameIter does not support
             // recovering slots.
             //
             // FIXME bug 1029963.
-            localOp(s.maybeRead(unreadablePlaceholder, silentFailure));
+            localOp(s.maybeRead(fallback));
         }
     }
 
     template <class Op>
     void unaliasedForEachActual(ThreadSafeContext *cx, Op op,
-                                ReadFrameArgsBehavior behavior) const
+                                ReadFrameArgsBehavior behavior,
+                                MaybeReadFallback &fallback) const
     {
         Nop nop;
-        readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior);
+        readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior, fallback);
     }
 
     JSScript *script() const {
         return script_;
     }
     jsbytecode *pc() const {
         return pc_;
     }
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -496,17 +496,17 @@ MDefinition::hasLiveDefUses() const
 {
     for (MUseIterator i(uses_.begin()); i != uses_.end(); i++) {
         MNode *ins = (*i)->consumer();
         if (ins->isDefinition()) {
             if (!ins->toDefinition()->isRecoveredOnBailout())
                 return true;
         } else {
             MOZ_ASSERT(ins->isResumePoint());
-            if (ins->toResumePoint()->isObservableOperand(*i))
+            if (!ins->toResumePoint()->isRecoverableOperand(*i))
                 return true;
         }
     }
 
     return false;
 }
 
 void
@@ -2703,16 +2703,22 @@ MResumePoint::isObservableOperand(MUse *
 }
 
 bool
 MResumePoint::isObservableOperand(size_t index) const
 {
     return block()->info().isObservableSlot(index);
 }
 
+bool
+MResumePoint::isRecoverableOperand(MUse *u) const
+{
+    return block()->info().isRecoverableOperand(indexOf(u));
+}
+
 MDefinition *
 MToInt32::foldsTo(TempAllocator &alloc)
 {
     MDefinition *input = getOperand(0);
     if (input->type() == MIRType_Int32)
         return input;
     return this;
 }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -10791,16 +10791,17 @@ class MResumePoint MOZ_FINAL :
         operands_[index].initUnchecked(operand, this);
     }
     void replaceOperand(size_t index, MDefinition *operand) MOZ_FINAL MOZ_OVERRIDE {
         operands_[index].replaceProducer(operand);
     }
 
     bool isObservableOperand(MUse *u) const;
     bool isObservableOperand(size_t index) const;
+    bool isRecoverableOperand(MUse *u) const;
 
     MDefinition *getOperand(size_t index) const {
         return operands_[index].producer();
     }
     jsbytecode *pc() const {
         return pc_;
     }
     uint32_t stackDepth() const {
--- a/js/src/jit/RematerializedFrame.cpp
+++ b/js/src/jit/RematerializedFrame.cpp
@@ -33,19 +33,20 @@ RematerializedFrame::RematerializedFrame
   : prevUpToDate_(false),
     top_(top),
     pc_(iter.pc()),
     frameNo_(iter.frameNo()),
     numActualArgs_(numActualArgs),
     script_(iter.script())
 {
     CopyValueToRematerializedFrame op(slots_);
+    MaybeReadFallback fallback(MagicValue(JS_OPTIMIZED_OUT));
     iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &returnValue_,
                                 &argsObj_, &thisValue_, ReadFrame_Actuals,
-                                MagicValue(JS_OPTIMIZED_OUT), /* silentFailure = */ true);
+                                fallback);
 }
 
 /* static */ RematerializedFrame *
 RematerializedFrame::New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter)
 {
     unsigned numFormals = iter.isFunctionFrame() ? iter.callee()->nargs() : 0;
     unsigned numActualArgs = Max(numFormals, iter.numActualArgs());
     size_t numBytes = sizeof(RematerializedFrame) +
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -141,18 +141,18 @@ IsObjectEscaped(MInstruction *ins)
 
     // Check if the object is escaped. If the object is not the first argument
     // of either a known Store / Load, then we consider it as escaped. This is a
     // cheap and conservative escape analysis.
     for (MUseIterator i(ins->usesBegin()); i != ins->usesEnd(); i++) {
         MNode *consumer = (*i)->consumer();
         if (!consumer->isDefinition()) {
             // Cannot optimize if it is observable from fun.arguments or others.
-            if (consumer->toResumePoint()->isObservableOperand(*i)) {
-                JitSpewDef(JitSpew_Escape, "Object is observable\n", ins);
+            if (!consumer->toResumePoint()->isRecoverableOperand(*i)) {
+                JitSpewDef(JitSpew_Escape, "Observable object cannot be recovered\n", ins);
                 return true;
             }
             continue;
         }
 
         MDefinition *def = consumer->toDefinition();
         switch (def->op()) {
           case MDefinition::Op_StoreFixedSlot:
@@ -520,18 +520,18 @@ IsArrayEscaped(MInstruction *ins)
 
     // Check if the object is escaped. If the object is not the first argument
     // of either a known Store / Load, then we consider it as escaped. This is a
     // cheap and conservative escape analysis.
     for (MUseIterator i(ins->usesBegin()); i != ins->usesEnd(); i++) {
         MNode *consumer = (*i)->consumer();
         if (!consumer->isDefinition()) {
             // Cannot optimize if it is observable from fun.arguments or others.
-            if (consumer->toResumePoint()->isObservableOperand(*i)) {
-                JitSpewDef(JitSpew_Escape, "Array is observable\n", ins);
+            if (!consumer->toResumePoint()->isRecoverableOperand(*i)) {
+                JitSpewDef(JitSpew_Escape, "Observable array cannot be recovered\n", ins);
                 return true;
             }
             continue;
         }
 
         MDefinition *def = consumer->toDefinition();
         switch (def->op()) {
           case MDefinition::Op_Elements: {
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -2522,17 +2522,17 @@ Simulator::decodeType01(SimInstruction *
                         // Store-exclusive.
                         int rn = instr->rnValue();
                         int rd = instr->rdValue();
                         int rt = instr->bits(3,0);
                         int32_t address = get_register(rn);
                         int32_t value = get_register(rt);
                         switch (instr->bits(22,21)) {
                         case 0:
-                            writeW(address, rt, instr);
+                            writeW(address, value, instr);
                             break;
                         case 1: {
                             MOZ_ASSERT((rt % 2) == 0);
                             int32_t value2 = get_register(rt+1);
                             writeDW(address, value, value2);
                             break;
                         }
                         case 2:
--- a/js/src/jsapi-tests/testScriptInfo.cpp
+++ b/js/src/jsapi-tests/testScriptInfo.cpp
@@ -17,30 +17,27 @@ try {              \n\
 	 xx += 1;  \n\
 }                  \n\
 catch (e)          \n\
 {                  \n\
 	 xx += 1;  \n\
 }\n\
 //@ sourceMappingURL=http://example.com/path/to/source-map.json";
 
-// Bug 670958 - fix JS_GetScriptLineExtent, among others
 BEGIN_TEST(testScriptInfo)
 {
     unsigned startLine = 1000;
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(__FILE__, startLine);
     JS::RootedScript script(cx);
     CHECK(JS_CompileScript(cx, global, code, strlen(code), options, &script));
     CHECK(script);
 
-    jsbytecode *start = JS_LineNumberToPC(cx, script, startLine);
     CHECK_EQUAL(JS_GetScriptBaseLineNumber(cx, script), startLine);
-    CHECK_EQUAL(JS_PCToLineNumber(cx, script, start), startLine);
     CHECK(strcmp(JS_GetScriptFilename(script), __FILE__) == 0);
     const char16_t *sourceMap = JS_GetScriptSourceMap(cx, script);
     CHECK(sourceMap);
     CHECK(CharsMatch(sourceMap, "http://example.com/path/to/source-map.json"));
 
     return true;
 }
 static bool
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1809,16 +1809,27 @@ CurrentGlobalOrNull(JSContext *cx);
 }
 
 /*
  * Initialize the 'Reflect' object on a global object.
  */
 extern JS_PUBLIC_API(JSObject *)
 JS_InitReflect(JSContext *cx, JS::HandleObject global);
 
+/*
+ * Add various profiling-related functions as properties of the given object.
+ * Defined in builtin/Profilers.cpp.
+ */
+extern JS_PUBLIC_API(bool)
+JS_DefineProfilingFunctions(JSContext *cx, JS::HandleObject obj);
+
+/* Defined in vm/Debugger.cpp. */
+extern JS_PUBLIC_API(bool)
+JS_DefineDebuggerObject(JSContext *cx, JS::HandleObject obj);
+
 #ifdef JS_HAS_CTYPES
 /*
  * Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes'
  * object will be sealed.
  */
 extern JS_PUBLIC_API(bool)
 JS_InitCTypesClass(JSContext *cx, JS::HandleObject global);
 
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -9,24 +9,26 @@
 #include "mozilla/PodOperations.h"
 
 #include <stdint.h>
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsobj.h"
+#include "jsprf.h"
 #include "jsproxy.h"
 #include "jswatchpoint.h"
 #include "jsweakmap.h"
 #include "jswrapper.h"
 #include "prmjtime.h"
 
 #include "builtin/TestingFunctions.h"
 #include "proxy/DeadObjectProxy.h"
+#include "vm/ArgumentsObject.h"
 #include "vm/WrapperObject.h"
 
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 #include "vm/ScopeObject-inl.h"
 
 using namespace js;
@@ -596,16 +598,22 @@ JS_SetProtoCalled(JSContext *)
 extern size_t sCustomIteratorCount;
 
 JS_FRIEND_API(size_t)
 JS_GetCustomIteratorCount(JSContext *cx)
 {
     return sCustomIteratorCount;
 }
 
+JS_FRIEND_API(unsigned)
+JS_PCToLineNumber(JSScript *script, jsbytecode *pc)
+{
+    return PCToLineNumber(script, pc);
+}
+
 JS_FRIEND_API(bool)
 JS_IsDeadWrapper(JSObject *obj)
 {
     return IsDeadProxyObject(obj);
 }
 
 void
 js::TraceWeakMaps(WeakMapTracer *trc)
@@ -705,16 +713,229 @@ js_DumpObject(JSObject *obj)
         fprintf(stderr, "NULL\n");
         return;
     }
     obj->dump();
 }
 
 #endif
 
+static const char *
+FormatValue(JSContext *cx, const Value &vArg, JSAutoByteString &bytes)
+{
+    RootedValue v(cx, vArg);
+
+    /*
+     * We could use Maybe<AutoCompartment> here, but G++ can't quite follow
+     * that, and warns about uninitialized members being used in the
+     * destructor.
+     */
+    RootedString str(cx);
+    if (v.isObject()) {
+        AutoCompartment ac(cx, &v.toObject());
+        str = ToString<CanGC>(cx, v);
+    } else {
+        str = ToString<CanGC>(cx, v);
+    }
+
+    if (!str)
+        return nullptr;
+    const char *buf = bytes.encodeLatin1(cx, str);
+    if (!buf)
+        return nullptr;
+    const char *found = strstr(buf, "function ");
+    if (found && (found - buf <= 2))
+        return "[function]";
+    return buf;
+}
+
+static char *
+FormatFrame(JSContext *cx, const NonBuiltinScriptFrameIter &iter, char *buf, int num,
+            bool showArgs, bool showLocals, bool showThisProps)
+{
+    JS_ASSERT(!cx->isExceptionPending());
+    RootedScript script(cx, iter.script());
+    jsbytecode* pc = iter.pc();
+
+    RootedObject scopeChain(cx, iter.scopeChain());
+    JSAutoCompartment ac(cx, scopeChain);
+
+    const char *filename = script->filename();
+    unsigned lineno = PCToLineNumber(script, pc);
+    RootedFunction fun(cx, iter.maybeCallee());
+    RootedString funname(cx);
+    if (fun)
+        funname = fun->atom();
+
+    RootedValue thisVal(cx);
+    if (iter.hasUsableAbstractFramePtr() && iter.computeThis(cx)) {
+        thisVal = iter.computedThisValue();
+    }
+
+    // print the frame number and function name
+    if (funname) {
+        JSAutoByteString funbytes;
+        buf = JS_sprintf_append(buf, "%d %s(", num, funbytes.encodeLatin1(cx, funname));
+    } else if (fun) {
+        buf = JS_sprintf_append(buf, "%d anonymous(", num);
+    } else {
+        buf = JS_sprintf_append(buf, "%d <TOP LEVEL>", num);
+    }
+    if (!buf)
+        return buf;
+
+    if (showArgs && iter.hasArgs()) {
+        BindingVector bindings(cx);
+        if (fun && fun->isInterpreted()) {
+            if (!FillBindingVector(script, &bindings))
+                return buf;
+        }
+
+
+        bool first = true;
+        for (unsigned i = 0; i < iter.numActualArgs(); i++) {
+            RootedValue arg(cx);
+            if (i < iter.numFormalArgs() && script->formalIsAliased(i)) {
+                for (AliasedFormalIter fi(script); ; fi++) {
+                    if (fi.frameIndex() == i) {
+                        arg = iter.callObj().aliasedVar(fi);
+                        break;
+                    }
+                }
+            } else if (script->argsObjAliasesFormals() && iter.hasArgsObj()) {
+                arg = iter.argsObj().arg(i);
+            } else {
+                arg = iter.unaliasedActual(i, DONT_CHECK_ALIASING);
+            }
+
+            JSAutoByteString valueBytes;
+            const char *value = FormatValue(cx, arg, valueBytes);
+
+            JSAutoByteString nameBytes;
+            const char *name = nullptr;
+
+            if (i < bindings.length()) {
+                name = nameBytes.encodeLatin1(cx, bindings[i].name());
+                if (!buf)
+                    return nullptr;
+            }
+
+            if (value) {
+                buf = JS_sprintf_append(buf, "%s%s%s%s%s%s",
+                                        !first ? ", " : "",
+                                        name ? name :"",
+                                        name ? " = " : "",
+                                        arg.isString() ? "\"" : "",
+                                        value ? value : "?unknown?",
+                                        arg.isString() ? "\"" : "");
+                if (!buf)
+                    return buf;
+
+                first = false;
+            } else {
+                buf = JS_sprintf_append(buf, "    <Failed to get argument while inspecting stack frame>\n");
+                if (!buf)
+                    return buf;
+                cx->clearPendingException();
+
+            }
+        }
+    }
+
+    // print filename and line number
+    buf = JS_sprintf_append(buf, "%s [\"%s\":%d]\n",
+                            fun ? ")" : "",
+                            filename ? filename : "<unknown>",
+                            lineno);
+    if (!buf)
+        return buf;
+
+
+    // Note: Right now we don't dump the local variables anymore, because
+    // that is hard to support across all the JITs etc.
+
+    // print the value of 'this'
+    if (showLocals) {
+        if (!thisVal.isUndefined()) {
+            JSAutoByteString thisValBytes;
+            RootedString thisValStr(cx, ToString<CanGC>(cx, thisVal));
+            const char *str = nullptr;
+            if (thisValStr &&
+                (str = thisValBytes.encodeLatin1(cx, thisValStr)))
+            {
+                buf = JS_sprintf_append(buf, "    this = %s\n", str);
+                if (!buf)
+                    return buf;
+            } else {
+                buf = JS_sprintf_append(buf, "    <failed to get 'this' value>\n");
+                cx->clearPendingException();
+            }
+        }
+    }
+
+    if (showThisProps && thisVal.isObject()) {
+        RootedObject obj(cx, &thisVal.toObject());
+
+        AutoIdVector keys(cx);
+        if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &keys)) {
+            cx->clearPendingException();
+            return buf;
+        }
+
+        RootedId id(cx);
+        for (size_t i = 0; i < keys.length(); i++) {
+            RootedId id(cx, keys[i]);
+            RootedValue key(cx, IdToValue(id));
+            RootedValue v(cx);
+
+            if (!JSObject::getGeneric(cx, obj, obj, id, &v)) {
+                buf = JS_sprintf_append(buf, "    <Failed to fetch property while inspecting stack frame>\n");
+                cx->clearPendingException();
+                continue;
+            }
+
+            JSAutoByteString nameBytes;
+            JSAutoByteString valueBytes;
+            const char *name = FormatValue(cx, key, nameBytes);
+            const char *value = FormatValue(cx, v, valueBytes);
+            if (name && value) {
+                buf = JS_sprintf_append(buf, "    this.%s = %s%s%s\n",
+                                        name,
+                                        v.isString() ? "\"" : "",
+                                        value,
+                                        v.isString() ? "\"" : "");
+                if (!buf)
+                    return buf;
+            } else {
+                buf = JS_sprintf_append(buf, "    <Failed to format values while inspecting stack frame>\n");
+                cx->clearPendingException();
+            }
+        }
+    }
+
+    JS_ASSERT(!cx->isExceptionPending());
+    return buf;
+}
+
+JS_FRIEND_API(char *)
+JS::FormatStackDump(JSContext *cx, char *buf, bool showArgs, bool showLocals, bool showThisProps)
+{
+    int num = 0;
+
+    for (NonBuiltinScriptFrameIter i(cx); !i.done(); ++i) {
+        buf = FormatFrame(cx, i, buf, num, showArgs, showLocals, showThisProps);
+        num++;
+    }
+
+    if (!num)
+        buf = JS_sprintf_append(buf, "JavaScript stack is empty\n");
+
+    return buf;
+}
+
 struct DumpHeapTracer : public JSTracer
 {
     FILE   *output;
 
     DumpHeapTracer(FILE *fp, JSRuntime *rt, JSTraceCallback callback,
                    WeakMapTraceKind weakTraceKind)
       : JSTracer(rt, callback, weakTraceKind), output(fp)
     {}
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -49,16 +49,17 @@ struct JSErrorReport;
 
 namespace JS {
 template <class T>
 class Heap;
 } /* namespace JS */
 
 namespace js {
 class JS_FRIEND_API(BaseProxyHandler);
+class InterpreterFrame;
 } /* namespace js */
 
 extern JS_FRIEND_API(void)
 JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
 
 extern JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt);
 
@@ -82,16 +83,20 @@ extern JS_FRIEND_API(size_t)
 JS_SetProtoCalled(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
 JS_GetCustomIteratorCount(JSContext *cx);
 
 extern JS_FRIEND_API(bool)
 JS_NondeterministicGetWeakMapKeys(JSContext *cx, JS::HandleObject obj, JS::MutableHandleObject ret);
 
+// Raw JSScript* because this needs to be callable from a signal handler.
+extern JS_FRIEND_API(unsigned)
+JS_PCToLineNumber(JSScript *script, jsbytecode *pc);
+
 /*
  * Determine whether the given object is backed by a DeadObjectProxy.
  *
  * Such objects hold no other objects (they have no outgoing reference edges)
  * and will throw if you touch them (e.g. by reading/writing a property).
  */
 extern JS_FRIEND_API(bool)
 JS_IsDeadWrapper(JSObject *obj);
@@ -189,18 +194,39 @@ js_DumpString(JSString *str);
 extern JS_FRIEND_API(void)
 js_DumpAtom(JSAtom *atom);
 
 extern JS_FRIEND_API(void)
 js_DumpObject(JSObject *obj);
 
 extern JS_FRIEND_API(void)
 js_DumpChars(const char16_t *s, size_t n);
+
+extern JS_FRIEND_API(void)
+js_DumpValue(const JS::Value &val);
+
+extern JS_FRIEND_API(void)
+js_DumpId(jsid id);
+
+extern JS_FRIEND_API(void)
+js_DumpInterpreterFrame(JSContext *cx, js::InterpreterFrame *start = nullptr);
+
 #endif
 
+extern JS_FRIEND_API(void)
+js_DumpBacktrace(JSContext *cx);
+
+namespace JS {
+
+// Exposed for DumpJSStack
+extern JS_FRIEND_API(char *)
+FormatStackDump(JSContext *cx, char *buf, bool showArgs, bool showLocals, bool showThisProps);
+
+} // namespace JS
+
 /*
  * Copies all own properties from |obj| to |target|. |obj| must be a "native"
  * object (that is to say, normal-ish - not an Array or a Proxy).
  *
  * This function immediately enters a compartment, and does not impose any
  * restrictions on the compartment of |cx|.
  */
 extern JS_FRIEND_API(bool)
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -737,16 +737,19 @@ random_generateSeed()
      */
     rand_s(&seed.u32[0]);
 #elif defined(XP_UNIX)
     /*
      * In the unlikely event we can't read /dev/urandom, there's not much we can
      * do, so just mix in the fd error code and the current time.
      */
     int fd = open("/dev/urandom", O_RDONLY);
+    if (fd < 0) {
+        perror("FITZGEN: error opening /dev/urandom: ");
+    }
     MOZ_ASSERT(fd >= 0, "Can't open /dev/urandom");
     if (fd >= 0) {
         (void)read(fd, seed.u8, mozilla::ArrayLength(seed.u8));
         close(fd);
     }
     seed.u32[0] ^= fd;
 #else
 # error "Platform needs to implement random_generateSeed()"
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -6481,17 +6481,17 @@ js_DumpInterpreterFrame(JSContext *cx, I
 JS_FRIEND_API(void)
 js_DumpBacktrace(JSContext *cx)
 {
     Sprinter sprinter(cx);
     sprinter.init();
     size_t depth = 0;
     for (ScriptFrameIter i(cx); !i.done(); ++i, ++depth) {
         const char *filename = JS_GetScriptFilename(i.script());
-        unsigned line = JS_PCToLineNumber(cx, i.script(), i.pc());
+        unsigned line = PCToLineNumber(i.script(), i.pc());
         JSScript *script = i.script();
         sprinter.printf("#%d %14p   %s:%d (%p @ %d)\n",
                         depth, (i.isJit() ? 0 : i.interpFrame()), filename, line,
                         script, script->pcToOffset(i.pc()));
     }
     fprintf(stdout, "%s", sprinter.string());
 }
 
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -23,16 +23,17 @@
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsprf.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jstypes.h"
 #include "jsutil.h"
 
+#include "asmjs/AsmJSModule.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/SourceNotes.h"
 #include "js/CharacterEncoding.h"
 #include "vm/Opcodes.h"
 #include "vm/ScopeObject.h"
 #include "vm/Shape.h"
 #include "vm/StringBuffer.h"
 
@@ -271,16 +272,63 @@ js_DumpPCCounts(JSContext *cx, HandleScr
     jit::IonScriptCounts *ionCounts = script->getIonCounts();
 
     while (ionCounts) {
         DumpIonScriptCounts(sp, ionCounts);
         ionCounts = ionCounts->previous();
     }
 }
 
+void
+js::DumpCompartmentPCCounts(JSContext *cx)
+{
+    for (ZoneCellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
+        RootedScript script(cx, i.get<JSScript>());
+        if (script->compartment() != cx->compartment())
+            continue;
+
+        if (script->hasScriptCounts()) {
+            Sprinter sprinter(cx);
+            if (!sprinter.init())
+                return;
+
+            fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno());
+            js_DumpPCCounts(cx, script, &sprinter);
+            fputs(sprinter.string(), stdout);
+            fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno());
+        }
+    }
+
+    for (unsigned thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) {
+        for (ZoneCellIter i(cx->zone(), (AllocKind) thingKind); !i.done(); i.next()) {
+            JSObject *obj = i.get<JSObject>();
+            if (obj->compartment() != cx->compartment())
+                continue;
+
+            if (obj->is<AsmJSModuleObject>()) {
+                AsmJSModule &module = obj->as<AsmJSModuleObject>().module();
+
+                Sprinter sprinter(cx);
+                if (!sprinter.init())
+                    return;
+
+                fprintf(stdout, "--- Asm.js Module ---\n");
+
+                for (size_t i = 0; i < module.numFunctionCounts(); i++) {
+                    jit::IonScriptCounts *counts = module.functionCounts(i);
+                    DumpIonScriptCounts(&sprinter, counts);
+                }
+
+                fputs(sprinter.string(), stdout);
+                fprintf(stdout, "--- END Asm.js Module ---\n");
+            }
+        }
+    }
+}
+
 /////////////////////////////////////////////////////////////////////
 // Bytecode Parser
 /////////////////////////////////////////////////////////////////////
 
 namespace {
 
 class BytecodeParser
 {
@@ -887,17 +935,17 @@ js_Disassemble1(JSContext *cx, HandleScr
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2);
         return 0;
     }
     const JSCodeSpec *cs = &js_CodeSpec[op];
     ptrdiff_t len = (ptrdiff_t) cs->length;
     Sprint(sp, "%05u:", loc);
     if (lines)
-        Sprint(sp, "%4u", JS_PCToLineNumber(cx, script, pc));
+        Sprint(sp, "%4u", PCToLineNumber(script, pc));
     Sprint(sp, "  %s", js_CodeName[op]);
 
     switch (JOF_TYPE(cs->format)) {
       case JOF_BYTE:
           // Scan the trynotes to find the associated catch block
           // and make the try opcode look like a jump instruction
           // with an offset. This simplifies code coverage analysis
           // based on this disassembled output.
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -834,11 +834,14 @@ js_Disassemble1(JSContext *cx, JS::Handl
 
 void
 js_DumpPCCounts(JSContext *cx, JS::Handle<JSScript*> script, js::Sprinter *sp);
 
 namespace js {
 namespace jit { struct IonScriptCounts; }
 void
 DumpIonScriptCounts(js::Sprinter *sp, jit::IonScriptCounts *ionCounts);
+
+void
+DumpCompartmentPCCounts(JSContext *cx);
 }
 
 #endif /* jsopcode_h */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1783,34 +1783,34 @@ LineToPC(JSContext *cx, unsigned argc, j
             return false;
         lineArg++;
     }
 
     uint32_t lineno;
     if (!ToUint32(cx, args.get(lineArg), &lineno))
          return false;
 
-    jsbytecode *pc = JS_LineNumberToPC(cx, script, lineno);
+    jsbytecode *pc = js_LineNumberToPC(script, lineno);
     if (!pc)
         return false;
     args.rval().setInt32(script->pcToOffset(pc));
     return true;
 }
 
 static bool
 PCToLine(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedScript script(cx);
     int32_t i;
     unsigned lineno;
 
     if (!GetScriptAndPCArgs(cx, args.length(), args.array(), &script, &i))
         return false;
-    lineno = JS_PCToLineNumber(cx, script, script->offsetToPC(i));
+    lineno = PCToLineNumber(script, script->offsetToPC(i));
     if (!lineno)
         return false;
     args.rval().setInt32(lineno);
     return true;
 }
 
 #ifdef DEBUG
 
@@ -2229,29 +2229,29 @@ DisassWithSrc(JSContext *cx, unsigned ar
 
         Sprinter sprinter(cx);
         if (!sprinter.init()) {
             ok = false;
             goto bail;
         }
 
         /* burn the leading lines */
-        line2 = JS_PCToLineNumber(cx, script, pc);
+        line2 = PCToLineNumber(script, pc);
         for (line1 = 0; line1 < line2 - 1; line1++) {
             char *tmp = fgets(linebuf, LINE_BUF_LEN, file);
             if (!tmp) {
                 JS_ReportError(cx, "failed to read %s fully", script->filename());
                 ok = false;
                 goto bail;
             }
         }
 
         bupline = 0;
         while (pc < end) {
-            line2 = JS_PCToLineNumber(cx, script, pc);
+            line2 = PCToLineNumber(script, pc);
 
             if (line2 < line1) {
                 if (bupline != line2) {
                     bupline = line2;
                     Sprint(&sprinter, "%s %3u: BACKUP\n", sep, line2);
                 }
             } else {
                 if (bupline && line1 == line2)
@@ -2673,17 +2673,17 @@ EvalInFrame(JSContext *cx, unsigned argc
         if (!sfc.save())
             return false;
     }
 
     bool ok;
     {
         AutoCompartment ac(cx, env);
         ok = EvaluateInEnv(cx, env, thisv, frame, stableChars.twoByteRange(), fpscript->filename(),
-                           JS_PCToLineNumber(cx, fpscript, fi.pc()), args.rval());
+                           PCToLineNumber(fpscript, fi.pc()), args.rval());
     }
     return ok;
 }
 
 struct WorkerInput
 {
     JSRuntime *runtime;
     char16_t *chars;
@@ -5816,17 +5816,17 @@ Shell(JSContext *cx, OptionParser *op, c
     JSAutoCompartment ac(cx, glob);
 
     if (!js::DefineOS(cx, glob))
         return 1;
 
     int result = ProcessArgs(cx, glob, op);
 
     if (enableDisassemblyDumps)
-        JS_DumpCompartmentPCCounts(cx);
+        js::DumpCompartmentPCCounts(cx);
 
     if (!op->getBoolOption("no-js-cache-per-process")) {
         if (jsCacheAsmJSPath) {
             unlink(jsCacheAsmJSPath);
             JS_free(cx, const_cast<char *>(jsCacheAsmJSPath));
         }
         if (jsCacheDir) {
             rmdir(jsCacheDir);
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -188,36 +188,42 @@ ArgumentsObject::create(JSContext *cx, H
                         numDeletedWords * sizeof(size_t) +
                         numArgs * sizeof(Value);
 
     ArgumentsData *data = reinterpret_cast<ArgumentsData *>(
             cx->zone()->pod_malloc<uint8_t>(numBytes));
     if (!data)
         return nullptr;
 
-    JSObject *obj = JSObject::create(cx, FINALIZE_KIND, GetInitialHeap(GenericObject, clasp),
-                                     shape, type);
+    RootedObject obj(cx);
+    obj = JSObject::create(cx, FINALIZE_KIND, GetInitialHeap(GenericObject, clasp), shape, type);
     if (!obj) {
         js_free(data);
         return nullptr;
     }
 
     data->numArgs = numArgs;
     data->callee.init(ObjectValue(*callee.get()));
     data->script = script;
 
+    // Initialize with dummy UndefinedValue, and attach it to the argument
+    // object such as the GC can trace ArgumentsData as they are recovered.
+    HeapValue *dst = data->args, *dstEnd = data->args + numArgs;
+    for (HeapValue *iter = dst; iter != dstEnd; iter++)
+        iter->init(UndefinedValue());
+
+    obj->initFixedSlot(DATA_SLOT, PrivateValue(data));
+
     /* Copy [0, numArgs) into data->slots. */
-    HeapValue *dst = data->args, *dstEnd = data->args + numArgs;
     copy.copyArgs(cx, dst, numArgs);
 
     data->deletedBits = reinterpret_cast<size_t *>(dstEnd);
     ClearAllBitArrayElements(data->deletedBits, numDeletedWords);
 
     obj->initFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(numActuals << PACKED_BITS_COUNT));
-    obj->initFixedSlot(DATA_SLOT, PrivateValue(data));
 
     copy.maybeForwardToCallObject(obj, data);
 
     ArgumentsObject &argsobj = obj->as<ArgumentsObject>();
     JS_ASSERT(argsobj.initialLength() == numActuals);
     JS_ASSERT(!argsobj.hasOverriddenLength());
     return &argsobj;
 }
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -338,19 +338,28 @@ Breakpoint::nextInSite()
 {
     JSCList *link = JS_NEXT_LINK(&siteLinks);
     return (link == &site->breakpoints) ? nullptr : fromSiteLinks(link);
 }
 
 /*** Debugger hook dispatch **********************************************************************/
 
 Debugger::Debugger(JSContext *cx, JSObject *dbg)
-  : object(dbg), uncaughtExceptionHook(nullptr), enabled(true), trackingAllocationSites(false),
-    allocationsLogLength(0), maxAllocationsLogLength(DEFAULT_MAX_ALLOCATIONS_LOG_LENGTH),
-    frames(cx->runtime()), scripts(cx), sources(cx), objects(cx), environments(cx)
+  : object(dbg),
+    uncaughtExceptionHook(nullptr),
+    enabled(true),
+    trackingAllocationSites(false),
+    allocationSamplingProbability(1.0),
+    allocationsLogLength(0),
+    maxAllocationsLogLength(DEFAULT_MAX_ALLOCATIONS_LOG_LENGTH),
+    frames(cx->runtime()),
+    scripts(cx),
+    sources(cx),
+    objects(cx),
+    environments(cx)
 {
     assertSameCompartment(cx, dbg);
 
     cx->runtime()->debuggerList.insertBack(this);
     JS_INIT_CLIST(&breakpoints);
     JS_INIT_CLIST(&onNewGlobalObjectWatchersLink);
 }
 
@@ -3291,17 +3300,17 @@ static bool
 DebuggerScript_getOffsetLine(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "getOffsetLine", args, obj, script);
     if (!args.requireAtLeast(cx, "Debugger.Script.getOffsetLine", 1))
         return false;
     size_t offset;
     if (!ScriptOffset(cx, script, args[0], &offset))
         return false;
-    unsigned lineno = JS_PCToLineNumber(cx, script, script->offsetToPC(offset));
+    unsigned lineno = PCToLineNumber(script, script->offsetToPC(offset));
     args.rval().setNumber(lineno);
     return true;
 }
 
 namespace {
 
 class BytecodeRangeWithPosition : private BytecodeRange
 {
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -160,16 +160,17 @@ class DebuggerWeakMap : private WeakMap<
  * environments and objects are really two different concepts.
  */
 typedef JSObject Env;
 
 class Debugger : private mozilla::LinkedListElement<Debugger>
 {
     friend class Breakpoint;
     friend class DebuggerMemory;
+    friend class SavedStacks;
     friend class mozilla::LinkedListElement<Debugger>;
     friend bool (::JS_DefineDebuggerObject)(JSContext *cx, JS::HandleObject obj);
     friend bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata);
 
   public:
     enum Hook {
         OnDebuggerStatement,
         OnExceptionUnwind,
@@ -204,16 +205,17 @@ class Debugger : private mozilla::Linked
         explicit AllocationSite(HandleObject frame) : frame(frame) {
             JS_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>());
         };
         RelocatablePtrObject frame;
     };
     typedef mozilla::LinkedList<AllocationSite> AllocationSiteList;
 
     bool trackingAllocationSites;
+    double allocationSamplingProbability;
     AllocationSiteList allocationsLog;
     size_t allocationsLogLength;
     size_t maxAllocationsLogLength;
     static const size_t DEFAULT_MAX_ALLOCATIONS_LOG_LENGTH = 5000;
     bool appendAllocationSite(JSContext *cx, HandleSavedFrame frame);
     void emptyAllocationsLog();
 
     /*
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -241,16 +241,46 @@ DebuggerMemory::setMaxAllocationsLogLeng
         js_delete(dbg->allocationsLog.getFirst());
         dbg->allocationsLogLength--;
     }
 
     args.rval().setUndefined();
     return true;
 }
 
+/* static */ bool
+DebuggerMemory::getAllocationSamplingProbability(JSContext *cx, unsigned argc, Value *vp)
+{
+    THIS_DEBUGGER_MEMORY(cx, argc, vp, "(get allocationSamplingProbability)", args, memory);
+    args.rval().setDouble(memory->getDebugger()->allocationSamplingProbability);
+    return true;
+}
+
+/* static */ bool
+DebuggerMemory::setAllocationSamplingProbability(JSContext *cx, unsigned argc, Value *vp)
+{
+    THIS_DEBUGGER_MEMORY(cx, argc, vp, "(set allocationSamplingProbability)", args, memory);
+    if (!args.requireAtLeast(cx, "(set allocationSamplingProbability)", 1))
+        return false;
+
+    double probability;
+    if (!ToNumber(cx, args[0], &probability))
+        return false;
+
+    if (probability < 0.0 || probability > 1.0) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
+                             "(set allocationSamplingProbability)'s parameter",
+                             "not a number between 0 and 1");
+        return false;
+    }
+
+    memory->getDebugger()->allocationSamplingProbability = probability;
+    args.rval().setUndefined();
+    return true;
+}
 
 
 /* Debugger.Memory.prototype.takeCensus */
 
 void
 JS::dbg::SetDebuggerMallocSizeOf(JSRuntime *rt, mozilla::MallocSizeOf mallocSizeOf) {
     rt->debuggerMallocSizeOf = mallocSizeOf;
 }
@@ -746,16 +776,17 @@ DebuggerMemory::takeCensus(JSContext *cx
 
 
 /* Debugger.Memory property and method tables. */
 
 
 /* static */ const JSPropertySpec DebuggerMemory::properties[] = {
     JS_PSGS("trackingAllocationSites", getTrackingAllocationSites, setTrackingAllocationSites, 0),
     JS_PSGS("maxAllocationsLogLength", getMaxAllocationsLogLength, setMaxAllocationsLogLength, 0),
+    JS_PSGS("allocationSamplingProbability", getAllocationSamplingProbability, setAllocationSamplingProbability, 0),
     JS_PS_END
 };
 
 /* static */ const JSFunctionSpec DebuggerMemory::methods[] = {
     JS_FN("drainAllocationsLog", DebuggerMemory::drainAllocationsLog, 0, 0),
     JS_FN("takeCensus", takeCensus, 0, 0),
     JS_FS_END
 };
--- a/js/src/vm/DebuggerMemory.h
+++ b/js/src/vm/DebuggerMemory.h
@@ -35,16 +35,18 @@ class DebuggerMemory : public JSObject {
     static const JSPropertySpec properties[];
     static const JSFunctionSpec methods[];
 
     // Accessor properties of Debugger.Memory.prototype.
     static bool setTrackingAllocationSites(JSContext *cx, unsigned argc, Value *vp);
     static bool getTrackingAllocationSites(JSContext *cx, unsigned argc, Value *vp);
     static bool setMaxAllocationsLogLength(JSContext*cx, unsigned argc, Value *vp);
     static bool getMaxAllocationsLogLength(JSContext*cx, unsigned argc, Value *vp);
+    static bool setAllocationSamplingProbability(JSContext*cx, unsigned argc, Value *vp);
+    static bool getAllocationSamplingProbability(JSContext*cx, unsigned argc, Value *vp);
 
     // Function properties of Debugger.Memory.prototype.
     static bool takeCensus(JSContext *cx, unsigned argc, Value *vp);
     static bool drainAllocationsLog(JSContext *cx, unsigned argc, Value *vp);
 };
 
 } /* namespace js */
 
--- a/js/src/vm/OldDebugAPI.cpp
+++ b/js/src/vm/OldDebugAPI.cpp
@@ -17,17 +17,16 @@
 #include "jsgc.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsprf.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jstypes.h"
 
-#include "asmjs/AsmJSModule.h"
 #include "frontend/SourceNotes.h"
 #include "vm/Debugger.h"
 #include "vm/Shape.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsscriptinlines.h"
 
@@ -105,28 +104,16 @@ js::DebugExceptionUnwind(JSContext *cx, 
         MOZ_CRASH("Invalid trap status");
     }
 
     return status;
 }
 
 /************************************************************************/
 
-JS_PUBLIC_API(unsigned)
-JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
-{
-    return js::PCToLineNumber(script, pc);
-}
-
-JS_PUBLIC_API(jsbytecode *)
-JS_LineNumberToPC(JSContext *cx, JSScript *script, unsigned lineno)
-{
-    return js_LineNumberToPC(script, lineno);
-}
-
 JS_PUBLIC_API(JSScript *)
 JS_GetFunctionScript(JSContext *cx, HandleFunction fun)
 {
     if (fun->isNative())
         return nullptr;
     if (fun->isInterpretedLazy()) {
         AutoCompartment funCompartment(cx, fun);
         JSScript *script = fun->getOrCreateScript(cx);
@@ -153,277 +140,8 @@ JS_GetScriptSourceMap(JSContext *cx, JSS
     return source->hasSourceMapURL() ? source->sourceMapURL() : nullptr;
 }
 
 JS_PUBLIC_API(unsigned)
 JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
 {
     return script->lineno();
 }
-
-/***************************************************************************/
-
-extern JS_PUBLIC_API(void)
-JS_DumpPCCounts(JSContext *cx, HandleScript script)
-{
-    JS_ASSERT(script->hasScriptCounts());
-
-    Sprinter sprinter(cx);
-    if (!sprinter.init())
-        return;
-
-    fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno());
-    js_DumpPCCounts(cx, script, &sprinter);
-    fputs(sprinter.string(), stdout);
-    fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename(), (int) script->lineno());
-}
-
-JS_PUBLIC_API(void)
-JS_DumpCompartmentPCCounts(JSContext *cx)
-{
-    for (ZoneCellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
-        RootedScript script(cx, i.get<JSScript>());
-        if (script->compartment() != cx->compartment())
-            continue;
-
-        if (script->hasScriptCounts())
-            JS_DumpPCCounts(cx, script);
-    }
-
-    for (unsigned thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) {
-        for (ZoneCellIter i(cx->zone(), (AllocKind) thingKind); !i.done(); i.next()) {
-            JSObject *obj = i.get<JSObject>();
-            if (obj->compartment() != cx->compartment())
-                continue;
-
-            if (obj->is<AsmJSModuleObject>()) {
-                AsmJSModule &module = obj->as<AsmJSModuleObject>().module();
-
-                Sprinter sprinter(cx);
-                if (!sprinter.init())
-                    return;
-
-                fprintf(stdout, "--- Asm.js Module ---\n");
-
-                for (size_t i = 0; i < module.numFunctionCounts(); i++) {
-                    jit::IonScriptCounts *counts = module.functionCounts(i);
-                    DumpIonScriptCounts(&sprinter, counts);
-                }
-
-                fputs(sprinter.string(), stdout);
-                fprintf(stdout, "--- END Asm.js Module ---\n");
-            }
-        }
-    }
-}
-
-static const char *
-FormatValue(JSContext *cx, const Value &vArg, JSAutoByteString &bytes)
-{
-    RootedValue v(cx, vArg);
-
-    /*
-     * We could use Maybe<AutoCompartment> here, but G++ can't quite follow
-     * that, and warns about uninitialized members being used in the
-     * destructor.
-     */
-    RootedString str(cx);
-    if (v.isObject()) {
-        AutoCompartment ac(cx, &v.toObject());
-        str = ToString<CanGC>(cx, v);
-    } else {
-        str = ToString<CanGC>(cx, v);
-    }
-
-    if (!str)
-        return nullptr;
-    const char *buf = bytes.encodeLatin1(cx, str);
-    if (!buf)
-        return nullptr;
-    const char *found = strstr(buf, "function ");
-    if (found && (found - buf <= 2))
-        return "[function]";
-    return buf;
-}
-
-static char *
-FormatFrame(JSContext *cx, const NonBuiltinScriptFrameIter &iter, char *buf, int num,
-            bool showArgs, bool showLocals, bool showThisProps)
-{
-    JS_ASSERT(!cx->isExceptionPending());
-    RootedScript script(cx, iter.script());
-    jsbytecode* pc = iter.pc();
-
-    RootedObject scopeChain(cx, iter.scopeChain());
-    JSAutoCompartment ac(cx, scopeChain);
-
-    const char *filename = script->filename();
-    unsigned lineno = PCToLineNumber(script, pc);
-    RootedFunction fun(cx, iter.maybeCallee());
-    RootedString funname(cx);
-    if (fun)
-        funname = fun->atom();
-
-    RootedValue thisVal(cx);
-    if (iter.hasUsableAbstractFramePtr() && iter.computeThis(cx)) {
-        thisVal = iter.computedThisValue();
-    }
-
-    // print the frame number and function name
-    if (funname) {
-        JSAutoByteString funbytes;
-        buf = JS_sprintf_append(buf, "%d %s(", num, funbytes.encodeLatin1(cx, funname));
-    } else if (fun) {
-        buf = JS_sprintf_append(buf, "%d anonymous(", num);
-    } else {
-        buf = JS_sprintf_append(buf, "%d <TOP LEVEL>", num);
-    }
-    if (!buf)
-        return buf;
-
-    if (showArgs && iter.hasArgs()) {
-        BindingVector bindings(cx);
-        if (fun && fun->isInterpreted()) {
-            if (!FillBindingVector(script, &bindings))
-                return buf;
-        }
-
-
-        bool first = true;
-        for (unsigned i = 0; i < iter.numActualArgs(); i++) {
-            RootedValue arg(cx);
-            if (i < iter.numFormalArgs() && script->formalIsAliased(i)) {
-                for (AliasedFormalIter fi(script); ; fi++) {
-                    if (fi.frameIndex() == i) {
-                        arg = iter.callObj().aliasedVar(fi);
-                        break;
-                    }
-                }
-            } else if (script->argsObjAliasesFormals() && iter.hasArgsObj()) {
-                arg = iter.argsObj().arg(i);
-            } else {
-                arg = iter.unaliasedActual(i, DONT_CHECK_ALIASING);
-            }
-
-            JSAutoByteString valueBytes;
-            const char *value = FormatValue(cx, arg, valueBytes);
-
-            JSAutoByteString nameBytes;
-            const char *name = nullptr;
-
-            if (i < bindings.length()) {
-                name = nameBytes.encodeLatin1(cx, bindings[i].name());
-                if (!buf)
-                    return nullptr;
-            }
-
-            if (value) {
-                buf = JS_sprintf_append(buf, "%s%s%s%s%s%s",
-                                        !first ? ", " : "",
-                                        name ? name :"",
-                                        name ? " = " : "",
-                                        arg.isString() ? "\"" : "",
-                                        value ? value : "?unknown?",
-                                        arg.isString() ? "\"" : "");
-                if (!buf)
-                    return buf;
-
-                first = false;
-            } else {
-                buf = JS_sprintf_append(buf, "    <Failed to get argument while inspecting stack frame>\n");
-                if (!buf)
-                    return buf;
-                cx->clearPendingException();
-
-            }
-        }
-    }
-
-    // print filename and line number
-    buf = JS_sprintf_append(buf, "%s [\"%s\":%d]\n",
-                            fun ? ")" : "",
-                            filename ? filename : "<unknown>",
-                            lineno);
-    if (!buf)
-        return buf;
-
-
-    // Note: Right now we don't dump the local variables anymore, because
-    // that is hard to support across all the JITs etc.
-
-    // print the value of 'this'
-    if (showLocals) {
-        if (!thisVal.isUndefined()) {
-            JSAutoByteString thisValBytes;
-            RootedString thisValStr(cx, ToString<CanGC>(cx, thisVal));
-            const char *str = nullptr;
-            if (thisValStr &&
-                (str = thisValBytes.encodeLatin1(cx, thisValStr)))
-            {
-                buf = JS_sprintf_append(buf, "    this = %s\n", str);
-                if (!buf)
-                    return buf;
-            } else {
-                buf = JS_sprintf_append(buf, "    <failed to get 'this' value>\n");
-                cx->clearPendingException();
-            }
-        }
-    }
-
-    if (showThisProps && thisVal.isObject()) {
-        RootedObject obj(cx, &thisVal.toObject());
-
-        AutoIdVector keys(cx);
-        if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &keys)) {
-            cx->clearPendingException();
-            return buf;
-        }
-
-        RootedId id(cx);
-        for (size_t i = 0; i < keys.length(); i++) {
-            RootedId id(cx, keys[i]);
-            RootedValue key(cx, IdToValue(id));
-            RootedValue v(cx);
-
-            if (!JSObject::getGeneric(cx, obj, obj, id, &v)) {
-                buf = JS_sprintf_append(buf, "    <Failed to fetch property while inspecting stack frame>\n");
-                cx->clearPendingException();
-                continue;
-            }
-
-            JSAutoByteString nameBytes;
-            JSAutoByteString valueBytes;
-            const char *name = FormatValue(cx, key, nameBytes);
-            const char *value = FormatValue(cx, v, valueBytes);
-            if (name && value) {
-                buf = JS_sprintf_append(buf, "    this.%s = %s%s%s\n",
-                                        name,
-                                        v.isString() ? "\"" : "",
-                                        value,
-                                        v.isString() ? "\"" : "");
-                if (!buf)
-                    return buf;
-            } else {
-                buf = JS_sprintf_append(buf, "    <Failed to format values while inspecting stack frame>\n");
-                cx->clearPendingException();
-            }
-        }
-    }
-
-    JS_ASSERT(!cx->isExceptionPending());
-    return buf;
-}
-
-JS_PUBLIC_API(char *)
-JS::FormatStackDump(JSContext *cx, char *buf, bool showArgs, bool showLocals, bool showThisProps)
-{
-    int num = 0;
-
-    for (NonBuiltinScriptFrameIter i(cx); !i.done(); ++i) {
-        buf = FormatFrame(cx, i, buf, num, showArgs, showLocals, showThisProps);
-        num++;
-    }
-
-    if (!num)
-        buf = JS_sprintf_append(buf, "JavaScript stack is empty\n");
-
-    return buf;
-}
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -4,20 +4,23 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "vm/SavedStacks.h"
 
 #include "mozilla/Attributes.h"
 
+#include <math.h>
+
 #include "jsapi.h"
 #include "jscompartment.h"
 #include "jsfriendapi.h"
 #include "jshashutil.h"
+#include "jsmath.h"
 #include "jsnum.h"
 
 #include "gc/Marking.h"
 #include "js/Vector.h"
 #include "vm/Debugger.h"
 #include "vm/GlobalObject.h"
 #include "vm/StringBuffer.h"
 
@@ -698,16 +701,41 @@ SavedStacks::getLocation(JSContext *cx, 
         if (!pcLocationMap.add(p, key, value))
             return false;
     }
 
     locationp.set(p->value());
     return true;
 }
 
+void
+SavedStacks::chooseSamplingProbability(JSContext *cx)
+{
+    GlobalObject::DebuggerVector *dbgs = cx->global()->getDebuggers();
+    if (!dbgs || dbgs->empty())
+        return;
+
+    Debugger *allocationTrackingDbg = nullptr;
+    mozilla::DebugOnly<Debugger **> begin = dbgs->begin();
+
+    for (Debugger **dbgp = dbgs->begin(); dbgp < dbgs->end(); dbgp++) {
+        // The set of debuggers had better not change while we're iterating,
+        // such that the vector gets reallocated.
+        JS_ASSERT(dbgs->begin() == begin);
+
+        if ((*dbgp)->trackingAllocationSites && (*dbgp)->enabled)
+            allocationTrackingDbg = *dbgp;
+    }
+
+    if (!allocationTrackingDbg)
+        return;
+
+    allocationSamplingProbability = allocationTrackingDbg->allocationSamplingProbability;
+}
+
 SavedStacks::FrameState::FrameState(const FrameIter &iter)
     : principals(iter.compartment()->principals),
       name(iter.isNonEvalFunctionFrame() ? iter.functionDisplayAtom() : nullptr),
       location()
 {
     if (principals)
         JS_HoldPrincipals(principals);
 }
@@ -731,18 +759,53 @@ SavedStacks::FrameState::trace(JSTracer 
     if (name)
         gc::MarkStringUnbarriered(trc, &name, "SavedStacks::FrameState::name");
     location.trace(trc);
 }
 
 bool
 SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata)
 {
+    SavedStacks &stacks = cx->compartment()->savedStacks();
+    if (stacks.allocationSkipCount > 0) {
+        stacks.allocationSkipCount--;
+        return true;
+    }
+
+    stacks.chooseSamplingProbability(cx);
+    if (stacks.allocationSamplingProbability == 0.0)
+        return true;
+
+    // If the sampling probability is set to 1.0, we are always taking a sample
+    // and can therefore leave allocationSkipCount at 0.
+    if (stacks.allocationSamplingProbability != 1.0) {
+        // Rather than generating a random number on every allocation to decide
+        // if we want to sample that particular allocation (which would be
+        // expensive), we calculate the number of allocations to skip before
+        // taking the next sample.
+        //
+        // P = the probability we sample any given event.
+        //
+        // ~P = 1-P, the probability we don't sample a given event.
+        //
+        // (~P)^n = the probability that we skip at least the next n events.
+        //
+        // let X = random between 0 and 1.
+        //
+        // floor(log base ~P of X) = n, aka the number of events we should skip
+        // until we take the next sample. Any value for X less than (~P)^n
+        // yields a skip count greater than n, so the likelihood of a skip count
+        // greater than n is (~P)^n, as required.
+        double notSamplingProb = 1.0 - stacks.allocationSamplingProbability;
+        stacks.allocationSkipCount = std::floor(std::log(random_nextDouble(&stacks.rngState)) /
+                                                std::log(notSamplingProb));
+    }
+
     RootedSavedFrame frame(cx);
-    if (!cx->compartment()->savedStacks().saveCurrentStack(cx, &frame))
+    if (!stacks.saveCurrentStack(cx, &frame))
         return false;
     *pmetadata = frame;
 
     return Debugger::onLogAllocationSite(cx, frame);
 }
 
 #ifdef JS_CRASH_DIAGNOSTICS
 void
--- a/js/src/vm/SavedStacks.h
+++ b/js/src/vm/SavedStacks.h
@@ -3,16 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_SavedStacks_h
 #define vm_SavedStacks_h
 
 #include "jscntxt.h"
+#include "jsmath.h"
 #include "js/HashTable.h"
 #include "vm/Stack.h"
 
 namespace js {
 
 class SavedFrame : public JSObject {
     friend class SavedStacks;
 
@@ -95,40 +96,57 @@ struct SavedFrame::HashPolicy
     static HashNumber hash(const Lookup &lookup);
     static bool       match(SavedFrame *existing, const Lookup &lookup);
 
     typedef ReadBarriered<SavedFrame*> Key;
     static void rekey(Key &key, const Key &newKey);
 };
 
 class SavedStacks {
+    friend bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata);
+
   public:
-    SavedStacks() : frames(), savedFrameProto(nullptr) { }
+    SavedStacks()
+      : frames(),
+        savedFrameProto(nullptr),
+        allocationSamplingProbability(1.0),
+        allocationSkipCount(0),
+        // XXX: Initialize the RNG state to 0 so that random_initSeed is lazily
+        // called for us on the first call to random_next (via
+        // random_nextDouble). We need to do this here because /dev/urandom
+        // doesn't exist on Android, resulting in assertion failures.
+        rngState(0)
+    { }
 
     bool     init();
     bool     initialized() const { return frames.initialized(); }
     bool     saveCurrentStack(JSContext *cx, MutableHandleSavedFrame frame, unsigned maxFrameCount = 0);
     void     sweep(JSRuntime *rt);
     void     trace(JSTracer *trc);
     uint32_t count();
     void     clear();
+    void     setRNGState(uint64_t state) { rngState = state; }
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
   private:
-    SavedFrame::Set frames;
+    SavedFrame::Set     frames;
     ReadBarrieredObject savedFrameProto;
+    double              allocationSamplingProbability;
+    uint32_t            allocationSkipCount;
+    uint64_t            rngState;
 
     bool       insertFrames(JSContext *cx, FrameIter &iter, MutableHandleSavedFrame frame,
                             unsigned maxFrameCount = 0);
     SavedFrame *getOrCreateSavedFrame(JSContext *cx, SavedFrame::HandleLookup lookup);
     // |SavedFrame.prototype| is created lazily and held weakly. It should only
     // be accessed through this method.
     JSObject   *getOrCreateSavedFramePrototype(JSContext *cx);
     SavedFrame *createFrameFromLookup(JSContext *cx, SavedFrame::HandleLookup lookup);
+    void       chooseSamplingProbability(JSContext* cx);
 
     // Cache for memoizing PCToLineNumber lookups.
 
     struct PCKey {
         PCKey(JSScript *script, jsbytecode *pc) : script(script), pc(pc) { }
 
         PreBarrieredScript script;
         jsbytecode         *pc;
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -344,17 +344,18 @@ FrameIter::unaliasedForEachActual(JSCont
       case DONE:
       case ASMJS:
         break;
       case INTERP:
         interpFrame()->unaliasedForEachActual(op);
         return;
       case JIT:
         if (data_.jitFrames_.isIonJS()) {
-            ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals);
+            jit::MaybeReadFallback recover(cx, activation()->asJit(), &data_.jitFrames_);
+            ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals, recover);
         } else {
             JS_ASSERT(data_.jitFrames_.isBaselineJS());
             data_.jitFrames_.unaliasedForEachActual(op, jit::ReadFrame_Actuals);
         }
         return;
     }
     MOZ_CRASH("Unexpected state");
 }
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1396,46 +1396,50 @@ js::CheckLocalUnaliased(MaybeCheckAliasi
         // current frame, and so they do not know the block scope.
     }
 }
 #endif
 
 jit::JitActivation::JitActivation(JSContext *cx, bool active)
   : Activation(cx, Jit),
     active_(active),
-    rematerializedFrames_(nullptr)
+    rematerializedFrames_(nullptr),
+    ionRecovery_(cx)
 {
     if (active) {
         prevJitTop_ = cx->mainThread().jitTop;
         prevJitJSContext_ = cx->mainThread().jitJSContext;
         cx->mainThread().jitJSContext = cx;
     } else {
         prevJitTop_ = nullptr;
         prevJitJSContext_ = nullptr;
     }
 }
 
 jit::JitActivation::JitActivation(ForkJoinContext *cx)
   : Activation(cx, Jit),
     active_(true),
-    rematerializedFrames_(nullptr)
+    rematerializedFrames_(nullptr),
+    ionRecovery_(cx)
 {
     prevJitTop_ = cx->perThreadData->jitTop;
     prevJitJSContext_ = cx->perThreadData->jitJSContext;
     cx->perThreadData->jitJSContext = nullptr;
 }
 
 jit::JitActivation::~JitActivation()
 {
     if (active_) {
         cx_->perThreadData->jitTop = prevJitTop_;
         cx_->perThreadData->jitJSContext = prevJitJSContext_;
     }
 
     clearRematerializedFrames();
+    // All reocvered value are taken from activation during the bailout.
+    MOZ_ASSERT(ionRecovery_.empty());
     js_delete(rematerializedFrames_);
 }
 
 // setActive() is inlined in GenerateFFIIonExit() with explicit masm instructions so
 // changes to the logic here need to be reflected in GenerateFFIIonExit() in the enable
 // and disable activation instruction sequences.
 void
 jit::JitActivation::setActive(JSContext *cx, bool active)
@@ -1540,16 +1544,60 @@ void
 jit::JitActivation::markRematerializedFrames(JSTracer *trc)
 {
     if (!rematerializedFrames_)
         return;
     for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty(); e.popFront())
         RematerializedFrame::MarkInVector(trc, e.front().value());
 }
 
+bool
+jit::JitActivation::registerIonFrameRecovery(IonJSFrameLayout *fp, RInstructionResults&& results)
+{
+#ifdef DEBUG
+    // Check that there is no entry in the vector yet.
+    RInstructionResults *tmp = maybeIonFrameRecovery(fp);
+    MOZ_ASSERT_IF(tmp, tmp->isInitialized());
+#endif
+
+    if (!ionRecovery_.append(mozilla::Move(results)))
+        return false;
+
+    return true;
+}
+
+jit::RInstructionResults *
+jit::JitActivation::maybeIonFrameRecovery(IonJSFrameLayout *fp)
+{
+    for (RInstructionResults *it = ionRecovery_.begin(); it != ionRecovery_.end(); ) {
+        if (it->frame() == fp)
+            return it;
+    }
+
+    return nullptr;
+}
+
+void
+jit::JitActivation::maybeTakeIonFrameRecovery(IonJSFrameLayout *fp, RInstructionResults *results)
+{
+    RInstructionResults *elem = maybeIonFrameRecovery(fp);
+    if (!elem)
+        return;
+
+    *results = mozilla::Move(*elem);
+    ionRecovery_.erase(elem);
+}
+
+void
+jit::JitActivation::markIonRecovery(JSTracer *trc)
+{
+    for (RInstructionResults *it = ionRecovery_.begin(); it != ionRecovery_.end(); it++)
+        it->trace(trc);
+}
+
 AsmJSActivation::AsmJSActivation(JSContext *cx, AsmJSModule &module)
   : Activation(cx, AsmJS),
     module_(module),
     entrySP_(nullptr),
     profiler_(nullptr),
     resumePC_(nullptr),
     fp_(nullptr),
     exitReason_(AsmJSExit::None)
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1313,16 +1313,26 @@ class JitActivation : public Activation
     // frame pointers (i.e. jitTop) to a vector of rematerializations of all
     // inline frames associated with that frame.
     //
     // This table is lazily initialized by calling getRematerializedFrame.
     typedef Vector<RematerializedFrame *> RematerializedFrameVector;
     typedef HashMap<uint8_t *, RematerializedFrameVector> RematerializedFrameTable;
     RematerializedFrameTable *rematerializedFrames_;
 
+    // This vector is used to remember the outcome of the evaluation of recover
+    // instructions.
+    //
+    // RInstructionResults are appended into this vector when Snapshot values
+    // have to be read, or when the evaluation has to run before some mutating
+    // code.  Each RInstructionResults belongs to one frame which has to bailout
+    // as soon as we get back to it.
+    typedef Vector<RInstructionResults, 1> IonRecoveryMap;
+    IonRecoveryMap ionRecovery_;
+
     void clearRematerializedFrames();
 
 #ifdef CHECK_OSIPOINT_REGISTERS
   protected:
     // Used to verify that live registers don't change between a VM call and
     // the OsiPoint that follows it. Protected to silence Clang warning.
     uint32_t checkRegs_;
     RegisterDump regs_;
@@ -1387,16 +1397,30 @@ class JitActivation : public Activation
     bool hasRematerializedFrame(uint8_t *top, size_t inlineDepth = 0) {
         return !!lookupRematerializedFrame(top, inlineDepth);
     }
 
     // Remove a previous rematerialization by fp.
     void removeRematerializedFrame(uint8_t *top);
 
     void markRematerializedFrames(JSTracer *trc);
+
+
+    // Register the results of on Ion frame recovery.
+    bool registerIonFrameRecovery(IonJSFrameLayout *fp, RInstructionResults&& results);
+
+    // Return the pointer to the Ion frame recovery, if it is already registered.
+    RInstructionResults *maybeIonFrameRecovery(IonJSFrameLayout *fp);
+
+    // If an Ion frame recovery exists for the |fp| frame exists on the
+    // activation, then move its content to the |results| argument, and remove
+    // it from the activation.
+    void maybeTakeIonFrameRecovery(IonJSFrameLayout *fp, RInstructionResults *results);
+
+    void markIonRecovery(JSTracer *trc);
 };
 
 // A filtering of the ActivationIterator to only stop at JitActivations.
 class JitActivationIterator : public ActivationIterator
 {
     void settle() {
         while (!done() && !activation_->isJit())
             ActivationIterator::operator++();
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -810,24 +810,24 @@ nsDisplayScrollLayer::ComputeFrameMetric
         widget->GetBounds(widgetBounds);
         metrics.mCompositionBounds = ParentLayerRect(ViewAs<ParentLayerPixel>(widgetBounds));
 #ifdef MOZ_WIDGET_ANDROID
         if (frameBounds.height < metrics.mCompositionBounds.height) {
           metrics.mCompositionBounds.height = frameBounds.height;
         }
 #endif
       } else {
-        LayoutDeviceIntRect contentBounds;
-        if (nsLayoutUtils::GetContentViewerBounds(presContext, contentBounds)) {
+        LayoutDeviceIntSize contentSize;
+        if (nsLayoutUtils::GetContentViewerSize(presContext, contentSize)) {
           LayoutDeviceToParentLayerScale scale(1.0f);
           if (presContext->GetParentPresContext()) {
             gfxSize res = presContext->GetParentPresContext()->PresShell()->GetCumulativeResolution();
             scale = LayoutDeviceToParentLayerScale(res.width, res.height);
           }
-          metrics.mCompositionBounds = LayoutDeviceRect(contentBounds) * scale;
+          metrics.mCompositionBounds.SizeTo(contentSize * scale);
         }
       }
     }
   }
 
   // Adjust composition bounds for the size of scroll bars.
   if (scrollableFrame && !LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars)) {
     nsMargin sizes = scrollableFrame->GetActualScrollbarSizes();
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6693,33 +6693,33 @@ nsLayoutUtils::UpdateImageVisibilityForF
   if (visible) {
     presShell->EnsureImageInVisibleList(content);
   } else {
     presShell->RemoveImageFromVisibleList(content);
   }
 }
 
 /* static */ bool
-nsLayoutUtils::GetContentViewerBounds(nsPresContext* aPresContext,
-                                      LayoutDeviceIntRect& aOutRect)
+nsLayoutUtils::GetContentViewerSize(nsPresContext* aPresContext,
+                                    LayoutDeviceIntSize& aOutSize)
 {
   nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
   if (!docShell) {
     return false;
   }
 
   nsCOMPtr<nsIContentViewer> cv;
   docShell->GetContentViewer(getter_AddRefs(cv));
   if (!cv) {
     return false;
   }
 
   nsIntRect bounds;
   cv->GetBounds(bounds);
-  aOutRect = LayoutDeviceIntRect::FromUntyped(bounds);
+  aOutSize = LayoutDeviceIntRect::FromUntyped(bounds).Size();
   return true;
 }
 
 /* static */ nsSize
 nsLayoutUtils::CalculateCompositionSizeForFrame(nsIFrame* aFrame)
 {
   nsSize size(aFrame->GetSize());
 
@@ -6747,19 +6747,19 @@ nsLayoutUtils::CalculateCompositionSizeF
                       widgetBounds.height * auPerDevPixel);
 #ifdef MOZ_WIDGET_ANDROID
         nsSize frameSize = aFrame->GetSize();
         if (frameSize.height < size.height) {
           size.height = frameSize.height;
         }
 #endif
       } else {
-        LayoutDeviceIntRect contentBounds;
-        if (nsLayoutUtils::GetContentViewerBounds(presContext, contentBounds)) {
-          size = LayoutDevicePixel::ToAppUnits(contentBounds.Size(), auPerDevPixel);
+        LayoutDeviceIntSize contentSize;
+        if (nsLayoutUtils::GetContentViewerSize(presContext, contentSize)) {
+          size = LayoutDevicePixel::ToAppUnits(contentSize, auPerDevPixel);
         }
       }
     }
   }
 
   // Adjust composition bounds for the size of scroll bars.
   nsIScrollableFrame* scrollableFrame = aFrame->GetScrollTargetFrame();
   if (scrollableFrame && !LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars)) {
@@ -6815,24 +6815,24 @@ nsLayoutUtils::CalculateRootCompositionS
         widget->GetBounds(widgetBounds);
         rootCompositionSize = LayerSize(ViewAs<LayerPixel>(widgetBounds.Size()));
 #ifdef MOZ_WIDGET_ANDROID
         if (frameSize.height < rootCompositionSize.height) {
           rootCompositionSize.height = frameSize.height;
         }
 #endif
       } else {
-        LayoutDeviceIntRect contentBounds;
-        if (nsLayoutUtils::GetContentViewerBounds(rootPresContext, contentBounds)) {
+        LayoutDeviceIntSize contentSize;
+        if (nsLayoutUtils::GetContentViewerSize(rootPresContext, contentSize)) {
           LayoutDeviceToLayerScale scale(1.0f);
           if (rootPresContext->GetParentPresContext()) {
             gfxSize res = rootPresContext->GetParentPresContext()->PresShell()->GetCumulativeResolution();
             scale = LayoutDeviceToLayerScale(res.width, res.height);
           }
-          rootCompositionSize = contentBounds.Size() * scale;
+          rootCompositionSize = contentSize * scale;
         }
       }
     }
   } else {
     nsIWidget* widget = aFrame->GetNearestWidget();
     nsIntRect widgetBounds;
     widget->GetBounds(widgetBounds);
     rootCompositionSize = LayerSize(ViewAs<LayerPixel>(widgetBounds.Size()));
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -125,17 +125,17 @@ class nsLayoutUtils
   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
 
 public:
   typedef mozilla::layers::FrameMetrics FrameMetrics;
   typedef FrameMetrics::ViewID ViewID;
   typedef mozilla::CSSPoint CSSPoint;
   typedef mozilla::CSSSize CSSSize;
   typedef mozilla::LayerMargin LayerMargin;
-  typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
+  typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize;
 
   /**
    * Finds previously assigned ViewID for the given content element, if any.
    * Returns whether a ViewID was previously assigned.
    */
   static bool FindIDFor(const nsIContent* aContent, ViewID* aOutViewId);
 
   /**
@@ -2170,23 +2170,23 @@ public:
    * Determine if aImageFrame (which is an nsImageFrame, nsImageControlFrame, or
    * nsSVGImageFrame) is visible or close to being visible via scrolling and
    * update the presshell with this knowledge.
    */
   static void
   UpdateImageVisibilityForFrame(nsIFrame* aImageFrame);
 
   /**
-   * Populate aOutRect with the bounds of the content viewer corresponding
-   * to the given prescontext. Return true if the bounds were set, false
+   * Populate aOutSize with the size of the content viewer corresponding
+   * to the given prescontext. Return true if the size was set, false
    * otherwise.
    */
   static bool
-  GetContentViewerBounds(nsPresContext* aPresContext,
-                         LayoutDeviceIntRect& aOutRect);
+  GetContentViewerSize(nsPresContext* aPresContext,
+                       LayoutDeviceIntSize& aOutSize);
 
  /**
   * Calculate the compostion size for a frame. See FrameMetrics.h for
   * defintion of composition size (or bounds).
   */
   static nsSize
   CalculateCompositionSizeForFrame(nsIFrame* aFrame);
 
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -1317,17 +1317,17 @@ public class BrowserApp extends GeckoApp
             }
         });
     }
 
     private void updateSideBarState() {
         if (mMainLayoutAnimator != null)
             mMainLayoutAnimator.stop();
 
-        boolean isSideBar = (HardwareUtils.isTablet() && getOrientation() == Configuration.ORIENTATION_LANDSCAPE);
+        boolean isSideBar = !NewTabletUI.isEnabled(this) && (HardwareUtils.isTablet() && getOrientation() == Configuration.ORIENTATION_LANDSCAPE);
         final int sidebarWidth = getResources().getDimensionPixelSize(R.dimen.tabs_sidebar_width);
 
         ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mTabsPanel.getLayoutParams();
         lp.width = (isSideBar ? sidebarWidth : ViewGroup.LayoutParams.MATCH_PARENT);
         mTabsPanel.requestLayout();
 
         final boolean sidebarIsShown = (isSideBar && mTabsPanel.isShown());
         final int mainLayoutScrollX = (sidebarIsShown ? -sidebarWidth : 0);
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -43,16 +43,17 @@ DEFINES += \
   $(NULL)
 
 GARBAGE += \
   AndroidManifest.xml  \
   WebappManifestFragment.xml.frag \
   classes.dex  \
   gecko.ap_  \
   res/values/strings.xml \
+  res/raw/browsersearch.json \
   res/raw/suggestedsites.json \
   .aapt.deps \
   fennec_ids.txt \
   javah.out \
   jni-stubs.inc \
   GeneratedJNIWrappers.cpp \
   GeneratedJNIWrappers.h \
   $(NULL)
@@ -255,21 +256,22 @@ android_re