Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 26 Sep 2012 18:55:56 -0400
changeset 108277 ec079fd92224ad7ad835cce297781a2b6334cc40
parent 108221 a425ea4f16c947ab198f5329165cf6582b50cc4f (current diff)
parent 108276 294e9ee46579d8c366868b046a044da182dc4dcb (diff)
child 108278 cc0a9e9c737014d387f9ef5bdd38626a4aa61e79
child 108315 a7b11eac359f044ea0a14ab09199377caf996c38
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
milestone18.0a1
Merge the last PGO-green inbound changeset to m-c.
build/valgrind/x86_64-redhat-linux-gnu.sup
layout/svg/base/src/Makefile.in
layout/svg/base/src/SVGFEContainerFrame.cpp
layout/svg/base/src/SVGFEImageFrame.cpp
layout/svg/base/src/SVGFELeafFrame.cpp
layout/svg/base/src/SVGFEUnstyledLeafFrame.cpp
layout/svg/base/src/SVGViewFrame.cpp
layout/svg/base/src/nsISVGChildFrame.h
layout/svg/base/src/nsISVGGlyphFragmentNode.h
layout/svg/base/src/nsISVGSVGFrame.h
layout/svg/base/src/nsSVGAFrame.cpp
layout/svg/base/src/nsSVGClipPathFrame.cpp
layout/svg/base/src/nsSVGClipPathFrame.h
layout/svg/base/src/nsSVGContainerFrame.cpp
layout/svg/base/src/nsSVGContainerFrame.h
layout/svg/base/src/nsSVGEffects.cpp
layout/svg/base/src/nsSVGEffects.h
layout/svg/base/src/nsSVGFilterFrame.cpp
layout/svg/base/src/nsSVGFilterFrame.h
layout/svg/base/src/nsSVGFilterInstance.cpp
layout/svg/base/src/nsSVGFilterInstance.h
layout/svg/base/src/nsSVGFilterPaintCallback.h
layout/svg/base/src/nsSVGForeignObjectFrame.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.h
layout/svg/base/src/nsSVGGFrame.cpp
layout/svg/base/src/nsSVGGFrame.h
layout/svg/base/src/nsSVGGenericContainerFrame.cpp
layout/svg/base/src/nsSVGGenericContainerFrame.h
layout/svg/base/src/nsSVGGeometryFrame.cpp
layout/svg/base/src/nsSVGGeometryFrame.h
layout/svg/base/src/nsSVGGlyphFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.h
layout/svg/base/src/nsSVGGradientFrame.cpp
layout/svg/base/src/nsSVGGradientFrame.h
layout/svg/base/src/nsSVGImageFrame.cpp
layout/svg/base/src/nsSVGInnerSVGFrame.cpp
layout/svg/base/src/nsSVGInnerSVGFrame.h
layout/svg/base/src/nsSVGIntegrationUtils.cpp
layout/svg/base/src/nsSVGIntegrationUtils.h
layout/svg/base/src/nsSVGMarkerFrame.cpp
layout/svg/base/src/nsSVGMarkerFrame.h
layout/svg/base/src/nsSVGMaskFrame.cpp
layout/svg/base/src/nsSVGMaskFrame.h
layout/svg/base/src/nsSVGOuterSVGFrame.cpp
layout/svg/base/src/nsSVGOuterSVGFrame.h
layout/svg/base/src/nsSVGPaintServerFrame.cpp
layout/svg/base/src/nsSVGPaintServerFrame.h
layout/svg/base/src/nsSVGPathGeometryFrame.cpp
layout/svg/base/src/nsSVGPathGeometryFrame.h
layout/svg/base/src/nsSVGPatternFrame.cpp
layout/svg/base/src/nsSVGPatternFrame.h
layout/svg/base/src/nsSVGStopFrame.cpp
layout/svg/base/src/nsSVGSwitchFrame.cpp
layout/svg/base/src/nsSVGTSpanFrame.cpp
layout/svg/base/src/nsSVGTSpanFrame.h
layout/svg/base/src/nsSVGTextContainerFrame.cpp
layout/svg/base/src/nsSVGTextContainerFrame.h
layout/svg/base/src/nsSVGTextFrame.cpp
layout/svg/base/src/nsSVGTextFrame.h
layout/svg/base/src/nsSVGTextPathFrame.cpp
layout/svg/base/src/nsSVGTextPathFrame.h
layout/svg/base/src/nsSVGUseFrame.cpp
layout/svg/base/src/nsSVGUtils.cpp
layout/svg/base/src/nsSVGUtils.h
layout/svg/base/src/resources/content/svgBindings.xml
layout/svg/base/src/svg.css
mobile/android/base/AboutHomeContent.java
--- a/accessible/src/atk/nsMaiInterfaceEditableText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceEditableText.cpp
@@ -7,163 +7,122 @@
 #include "InterfaceInitFuncs.h"
 
 #include "HyperTextAccessible.h"
 #include "nsMai.h"
 
 #include "nsString.h"
 
 extern "C" {
-
-static gboolean
-setRunAttributesCB(AtkEditableText *aText, AtkAttributeSet *aAttribSet,
-                   gint aStartOffset, gint aEndOffset)
-{
-  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
-  if (!accWrap)
-    return FALSE;
-
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
-
-    nsCOMPtr<nsISupports> attrSet;
-    /* how to insert attributes into nsISupports ??? */
-
-    nsresult rv = accText->SetAttributes(aStartOffset, aEndOffset,
-                                         attrSet);
-    return NS_FAILED(rv) ? FALSE : TRUE;
-}
-
 static void
 setTextContentsCB(AtkEditableText *aText, const gchar *aString)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: setTextContentsCB, aString=%s", aString));
+  MAI_LOG_DEBUG(("EditableText: setTextContentsCB, aString=%s", aString));
 
-    NS_ConvertUTF8toUTF16 strContent(aString);
-    accText->SetTextContents(strContent);
+  NS_ConvertUTF8toUTF16 strContent(aString);
+  text->SetTextContents(strContent);
 }
 
 static void
 insertTextCB(AtkEditableText *aText,
              const gchar *aString, gint aLength, gint *aPosition)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
-
-    NS_ConvertUTF8toUTF16 strContent(aString, aLength);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    // interface changed in nsIAccessibleEditableText.idl ???
-    //
-    // int32_t pos = *aPosition;
-    // nsresult rv = accText->InsertText(strContent, aLength, &pos);
-    // *aPosition = pos;
+  NS_ConvertUTF8toUTF16 strContent(aString, aLength);
+  text->InsertText(strContent, *aPosition);
 
-    accText->InsertText(strContent, *aPosition);
-
-    MAI_LOG_DEBUG(("EditableText: insert aString=%s, aLength=%d, aPosition=%d",
-                   aString, aLength, *aPosition));
+  MAI_LOG_DEBUG(("EditableText: insert aString=%s, aLength=%d, aPosition=%d",
+                 aString, aLength, *aPosition));
 }
 
 static void
 copyTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: copyTextCB, aStartPos=%d, aEndPos=%d",
-                   aStartPos, aEndPos));
-    accText->CopyText(aStartPos, aEndPos);
+  MAI_LOG_DEBUG(("EditableText: copyTextCB, aStartPos=%d, aEndPos=%d",
+                 aStartPos, aEndPos));
+  text->CopyText(aStartPos, aEndPos);
 }
 
 static void
 cutTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
-    MAI_LOG_DEBUG(("EditableText: cutTextCB, aStartPos=%d, aEndPos=%d",
-                   aStartPos, aEndPos));
-    accText->CutText(aStartPos, aEndPos);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
+
+  MAI_LOG_DEBUG(("EditableText: cutTextCB, aStartPos=%d, aEndPos=%d",
+                 aStartPos, aEndPos));
+  text->CutText(aStartPos, aEndPos);
 }
 
 static void
 deleteTextCB(AtkEditableText *aText, gint aStartPos, gint aEndPos)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: deleteTextCB, aStartPos=%d, aEndPos=%d",
-                   aStartPos, aEndPos));
-    accText->DeleteText(aStartPos, aEndPos);
+  MAI_LOG_DEBUG(("EditableText: deleteTextCB, aStartPos=%d, aEndPos=%d",
+                 aStartPos, aEndPos));
+  text->DeleteText(aStartPos, aEndPos);
 }
 
 static void
 pasteTextCB(AtkEditableText *aText, gint aPosition)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleEditableText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
-    MAI_LOG_DEBUG(("EditableText: pasteTextCB, aPosition=%d", aPosition));
-    accText->PasteText(aPosition);
+  MAI_LOG_DEBUG(("EditableText: pasteTextCB, aPosition=%d", aPosition));
+  text->PasteText(aPosition);
 }
 }
 
 void
 editableTextInterfaceInitCB(AtkEditableTextIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
   if (NS_UNLIKELY(!aIface))
     return;
 
-  aIface->set_run_attributes = setRunAttributesCB;
   aIface->set_text_contents = setTextContentsCB;
   aIface->insert_text = insertTextCB;
   aIface->copy_text = copyTextCB;
   aIface->cut_text = cutTextCB;
   aIface->delete_text = deleteTextCB;
   aIface->paste_text = pasteTextCB;
 }
--- a/accessible/src/atk/nsMaiInterfaceText.cpp
+++ b/accessible/src/atk/nsMaiInterfaceText.cpp
@@ -29,23 +29,22 @@ extern "C" {
 
 static gchar*
 getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsAutoString autoStr;
-    nsresult rv = accText->GetText(aStartOffset, aEndOffset, autoStr);
+    nsresult rv = text->GetText(aStartOffset, aEndOffset, autoStr);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
 
     //copy and return, libspi will free it.
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
@@ -54,55 +53,54 @@ static gchar*
 getTextAfterOffsetCB(AtkText *aText, gint aOffset,
                      AtkTextBoundary aBoundaryType,
                      gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
-    nsAutoString autoStr;
-    int32_t startOffset = 0, endOffset = 0;
-    nsresult rv =
-        accText->GetTextAfterOffset(aOffset, aBoundaryType,
-                                    &startOffset, &endOffset, autoStr);
-    *aStartOffset = startOffset;
-    *aEndOffset = endOffset;
+  nsAutoString autoStr;
+  int32_t startOffset = 0, endOffset = 0;
+  nsresult rv =
+    text->GetTextAfterOffset(aOffset, aBoundaryType,
+                             &startOffset, &endOffset, autoStr);
 
-    NS_ENSURE_SUCCESS(rv, nullptr);
+  *aStartOffset = startOffset;
+  *aEndOffset = endOffset;
+
+  NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
 }
 
 static gchar*
 getTextAtOffsetCB(AtkText *aText, gint aOffset,
                   AtkTextBoundary aBoundaryType,
                   gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsAutoString autoStr;
     int32_t startOffset = 0, endOffset = 0;
     nsresult rv =
-        accText->GetTextAtOffset(aOffset, aBoundaryType,
-                                 &startOffset, &endOffset, autoStr);
+        text->GetTextAtOffset(aOffset, aBoundaryType,
+                              &startOffset, &endOffset, autoStr);
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
@@ -110,25 +108,24 @@ getTextAtOffsetCB(AtkText *aText, gint a
 
 static gunichar
 getCharacterAtOffsetCB(AtkText* aText, gint aOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return 0;
 
-  nsCOMPtr<nsIAccessibleText> accText;
-  accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                          getter_AddRefs(accText));
-  NS_ENSURE_TRUE(accText, 0);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return 0;
 
   // PRUnichar is unsigned short in Mozilla
   // gnuichar is guint32 in glib
   PRUnichar uniChar = 0;
-  nsresult rv = accText->GetCharacterAtOffset(aOffset, &uniChar);
+  nsresult rv = text->GetCharacterAtOffset(aOffset, &uniChar);
   if (NS_FAILED(rv))
     return 0;
 
   // Convert char to "*" when it's "password text".
   if (accWrap->NativeRole() == roles::PASSWORD_TEXT)
     uniChar = '*';
 
   return static_cast<gunichar>(uniChar);
@@ -138,26 +135,25 @@ static gchar*
 getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
                       AtkTextBoundary aBoundaryType,
                       gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsAutoString autoStr;
     int32_t startOffset = 0, endOffset = 0;
     nsresult rv =
-        accText->GetTextBeforeOffset(aOffset, aBoundaryType,
-                                     &startOffset, &endOffset, autoStr);
+        text->GetTextBeforeOffset(aOffset, aBoundaryType,
+                                  &startOffset, &endOffset, autoStr);
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     ConvertTexttoAsterisks(accWrap, autoStr);
     NS_ConvertUTF16toUTF8 cautoStr(autoStr);
     return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
@@ -165,145 +161,138 @@ getTextBeforeOffsetCB(AtkText *aText, gi
 
 static gint
 getCaretOffsetCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return 0;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, 0);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return 0;
 
     int32_t offset;
-    nsresult rv = accText->GetCaretOffset(&offset);
+    nsresult rv = text->GetCaretOffset(&offset);
     return (NS_FAILED(rv)) ? 0 : static_cast<gint>(offset);
 }
 
 static AtkAttributeSet*
 getRunAttributesCB(AtkText *aText, gint aOffset,
                    gint *aStartOffset,
                    gint *aEndOffset)
 {
   *aStartOffset = -1;
   *aEndOffset = -1;
 
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsCOMPtr<nsIPersistentProperties> attributes;
     int32_t startOffset = 0, endOffset = 0;
-    nsresult rv = accText->GetTextAttributes(false, aOffset,
-                                             &startOffset, &endOffset,
-                                             getter_AddRefs(attributes));
+    nsresult rv = text->GetTextAttributes(false, aOffset,
+                                          &startOffset, &endOffset,
+                                          getter_AddRefs(attributes));
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     return ConvertToAtkAttributeSet(attributes);
 }
 
 static AtkAttributeSet*
 getDefaultAttributesCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     nsCOMPtr<nsIPersistentProperties> attributes;
-    nsresult rv = accText->GetDefaultTextAttributes(getter_AddRefs(attributes));
+    nsresult rv = text->GetDefaultTextAttributes(getter_AddRefs(attributes));
     if (NS_FAILED(rv))
         return nullptr;
 
     return ConvertToAtkAttributeSet(attributes);
 }
 
 static void
 getCharacterExtentsCB(AtkText *aText, gint aOffset,
                       gint *aX, gint *aY,
                       gint *aWidth, gint *aHeight,
                       AtkCoordType aCoords)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if(!accWrap || !aX || !aY || !aWidth || !aHeight)
     return;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
     int32_t extY = 0, extX = 0;
     int32_t extWidth = 0, extHeight = 0;
 
     uint32_t geckoCoordType;
     if (aCoords == ATK_XY_SCREEN)
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
     else
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
 
 #ifdef DEBUG
     nsresult rv =
 #endif
-    accText->GetCharacterExtents(aOffset, &extX, &extY,
-                                 &extWidth, &extHeight,
-                                 geckoCoordType);
+    text->GetCharacterExtents(aOffset, &extX, &extY,
+                              &extWidth, &extHeight,
+                              geckoCoordType);
     *aX = extX;
     *aY = extY;
     *aWidth = extWidth;
     *aHeight = extHeight;
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "MaiInterfaceText::GetCharacterExtents, failed\n");
 }
 
 static void
 getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
                   AtkCoordType aCoords, AtkTextRectangle *aRect)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if(!accWrap || !aRect)
     return;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    if (!accText)
-        return;
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return;
 
     int32_t extY = 0, extX = 0;
     int32_t extWidth = 0, extHeight = 0;
 
     uint32_t geckoCoordType;
     if (aCoords == ATK_XY_SCREEN)
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
     else
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
 
 #ifdef DEBUG
     nsresult rv =
 #endif
-    accText->GetRangeExtents(aStartOffset, aEndOffset,
-                             &extX, &extY,
-                             &extWidth, &extHeight,
-                             geckoCoordType);
+    text->GetRangeExtents(aStartOffset, aEndOffset,
+                          &extX, &extY,
+                          &extWidth, &extHeight,
+                          geckoCoordType);
     aRect->x = extX;
     aRect->y = extY;
     aRect->width = extWidth;
     aRect->height = extHeight;
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "MaiInterfaceText::GetRangeExtents, failed\n");
 }
 
@@ -323,66 +312,63 @@ static gint
 getOffsetAtPointCB(AtkText *aText,
                    gint aX, gint aY,
                    AtkCoordType aCoords)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return -1;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, -1);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return -1;
 
     int32_t offset = 0;
     uint32_t geckoCoordType;
     if (aCoords == ATK_XY_SCREEN)
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
     else
         geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
 
-    accText->GetOffsetAtPoint(aX, aY, geckoCoordType, &offset);
+    text->GetOffsetAtPoint(aX, aY, geckoCoordType, &offset);
     return static_cast<gint>(offset);
 }
 
 static gint
 getTextSelectionCountCB(AtkText *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return 0;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, 0);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return 0;
 
     int32_t selectionCount;
-    nsresult rv = accText->GetSelectionCount(&selectionCount);
+    nsresult rv = text->GetSelectionCount(&selectionCount);
  
     return NS_FAILED(rv) ? 0 : selectionCount;
 }
 
 static gchar*
 getTextSelectionCB(AtkText *aText, gint aSelectionNum,
                    gint *aStartOffset, gint *aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return nullptr;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, nullptr);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return nullptr;
 
     int32_t startOffset = 0, endOffset = 0;
-    nsresult rv = accText->GetSelectionBounds(aSelectionNum,
-                                              &startOffset, &endOffset);
+    nsresult rv = text->GetSelectionBounds(aSelectionNum,
+                                           &startOffset, &endOffset);
 
     *aStartOffset = startOffset;
     *aEndOffset = endOffset;
 
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     return getTextCB(aText, *aStartOffset, *aEndOffset);
 }
@@ -392,75 +378,71 @@ static gboolean
 addTextSelectionCB(AtkText *aText,
                    gint aStartOffset,
                    gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->AddSelection(aStartOffset, aEndOffset);
+    nsresult rv = text->AddSelection(aStartOffset, aEndOffset);
 
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 
 static gboolean
 removeTextSelectionCB(AtkText *aText,
                       gint aSelectionNum)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->RemoveSelection(aSelectionNum);
+    nsresult rv = text->RemoveSelection(aSelectionNum);
 
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 
 static gboolean
 setTextSelectionCB(AtkText *aText, gint aSelectionNum,
                    gint aStartOffset, gint aEndOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->SetSelectionBounds(aSelectionNum,
-                                              aStartOffset, aEndOffset);
+    nsresult rv = text->SetSelectionBounds(aSelectionNum,
+                                           aStartOffset, aEndOffset);
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 
 static gboolean
 setCaretOffsetCB(AtkText *aText, gint aOffset)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleText> accText;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
-                            getter_AddRefs(accText));
-    NS_ENSURE_TRUE(accText, FALSE);
+  HyperTextAccessible* text = accWrap->AsHyperText();
+  if (!text || !text->IsTextRole())
+    return false;
 
-    nsresult rv = accText->SetCaretOffset(aOffset);
+    nsresult rv = text->SetCaretOffset(aOffset);
     return NS_SUCCEEDED(rv) ? TRUE : FALSE;
 }
 }
 
 void
 textInterfaceInitCB(AtkTextIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -541,10 +541,14 @@ pref("dom.ipc.processPrelauch.delayMs", 
 #endif
 
 // Ignore the "dialog=1" feature in window.open.
 pref("dom.disable_window_open_dialog_feature", true);
 
 // Screen reader support
 pref("accessibility.accessfu.activate", 2);
 
+// Enable hit-target fluffing
+pref("ui.touch.radius.enabled", true);
+pref("ui.mouse.radius.enabled", true);
+
 // Disable native prompt
 pref("browser.prompt.allowNative", false);
--- a/b2g/chrome/content/forms.js
+++ b/b2g/chrome/content/forms.js
@@ -107,19 +107,24 @@ let FormAssistant = {
   receiveMessage: function fa_receiveMessage(msg) {
     let target = this.previousTarget;
     if (!target) {
       return;
     }
 
     let json = msg.json;
     switch (msg.name) {
-      case "Forms:Input:Value":
+      case "Forms:Input:Value": {
         target.value = json.value;
+
+        let event = content.document.createEvent('HTMLEvents');
+        event.initEvent('input', true, false);
+        target.dispatchEvent(event);
         break;
+      }
 
       case "Forms:Select:Choice":
         let options = target.options;
         let valueChanged = false;
         if ("index" in json) {
           if (options.selectedIndex != json.index) {
             options.selectedIndex = json.index;
             valueChanged = true;
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -177,17 +177,17 @@
 
           let [, preDomain, domain] = matchedURL;
           let baseDomain = domain;
           let subDomain = "";
           // getBaseDomainFromHost doesn't recognize IPv6 literals in brackets as IPs (bug 667159)
           if (domain[0] != "[") {
             try {
               baseDomain = Services.eTLD.getBaseDomainFromHost(domain);
-              if (!domain.contains(baseDomain)) {
+              if (!domain.endsWith(baseDomain)) {
                 // getBaseDomainFromHost converts its resultant to ACE.
                 let IDNService = Cc["@mozilla.org/network/idn-service;1"]
                                  .getService(Ci.nsIIDNService);
                 baseDomain = IDNService.convertACEtoUTF8(baseDomain);
               }
             } catch (e) {}
           }
           if (baseDomain != domain) {
--- a/browser/modules/WindowsPreviewPerTab.jsm
+++ b/browser/modules/WindowsPreviewPerTab.jsm
@@ -67,18 +67,24 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyServiceGetter(this, "imgTools",
                                    "@mozilla.org/image/tools;1",
                                    "imgITools");
 XPCOMUtils.defineLazyServiceGetter(this, "faviconSvc",
                                    "@mozilla.org/browser/favicon-service;1",
                                    "nsIFaviconService");
 
 // nsIURI -> imgIContainer
-function _imageFromURI(uri, callback) {
+function _imageFromURI(uri, privateMode, callback) {
   let channel = ioSvc.newChannelFromURI(uri);
+  try {
+    channel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
+    channel.setPrivate(privateMode);
+  } catch (e) {
+    // Ignore channels which do not support nsIPrivateBrowsingChannel
+  }
   NetUtil.asyncFetch(channel, function(inputStream, resultCode) {
     if (!Components.isSuccessCode(resultCode))
       return;
     try {
       let out_img = { value: null };
       imgTools.decodeImageData(inputStream, channel.contentType, out_img);
       callback(out_img.value);
     } catch (e) {
@@ -87,21 +93,21 @@ function _imageFromURI(uri, callback) {
       let defaultURI = faviconSvc.defaultFavicon;
       if (!defaultURI.equals(uri))
         _imageFromURI(defaultURI, callback);
     }
   });
 }
 
 // string? -> imgIContainer
-function getFaviconAsImage(iconurl, callback) {
+function getFaviconAsImage(iconurl, privateMode, callback) {
   if (iconurl)
-    _imageFromURI(NetUtil.newURI(iconurl), callback);
+    _imageFromURI(NetUtil.newURI(iconurl), privateMode, callback);
   else
-    _imageFromURI(faviconSvc.defaultFavicon, callback);
+    _imageFromURI(faviconSvc.defaultFavicon, privateMode, callback);
 }
 
 // Snaps the given rectangle to be pixel-aligned at the given scale
 function snapRectAtScale(r, scale) {
   let x = Math.floor(r.x * scale);
   let y = Math.floor(r.y * scale);
   let width = Math.ceil((r.x + r.width) * scale) - x;
   let height = Math.ceil((r.y + r.height) * scale) - y;
@@ -431,17 +437,17 @@ TabWindow.prototype = {
     let docShell = this.win
                   .QueryInterface(Ci.nsIInterfaceRequestor)
                   .getInterface(Ci.nsIWebNavigation)
                   .QueryInterface(Ci.nsIDocShell);
     let preview = AeroPeek.taskbar.createTaskbarTabPreview(docShell, controller);
     preview.visible = AeroPeek.enabled;
     preview.active = this.tabbrowser.selectedTab == tab;
     // Grab the default favicon
-    getFaviconAsImage(null, function (img) {
+    getFaviconAsImage(null, this.win.gPrivateBrowsingUI.privateWindow, function (img) {
       // It is possible that we've already gotten the real favicon, so make sure
       // we have not set one before setting this default one.
       if (!preview.icon)
         preview.icon = img;
     });
 
     // It's OK to add the preview now while the favicon still loads.
     this.previews.splice(tab._tPos, 0, preview);
@@ -530,17 +536,17 @@ TabWindow.prototype = {
         this.enabled = true;
         break;
     }
   },
 
   //// Browser progress listener
   onLinkIconAvailable: function (aBrowser, aIconURL) {
     let self = this;
-    getFaviconAsImage(aIconURL, function (img) {
+    getFaviconAsImage(aIconURL, this.win.gPrivateBrowsingUI.privateWindow, function (img) {
       let index = self.tabbrowser.browsers.indexOf(aBrowser);
       // Only add it if we've found the index.  The tab could have closed!
       if (index != -1)
         self.previews[index].icon = img;
     });
   }
 }
 
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -78,18 +78,22 @@ nsSecurityNameSet::InitializeNameSet(nsI
 
     /*
      * Find Object.prototype's class by walking up the global object's
      * prototype chain.
      */
     JSObject *obj = global;
     JSObject *proto;
     JSAutoRequest ar(cx);
-    while ((proto = JS_GetPrototype(obj)) != nullptr)
+    for (;;) {
+        MOZ_ALWAYS_TRUE(JS_GetPrototype(cx, obj, &proto));
+        if (!proto)
+            break;
         obj = proto;
+    }
     JSClass *objectClass = JS_GetClass(obj);
 
     JS::Value v;
     if (!JS_GetProperty(cx, global, "netscape", &v))
         return NS_ERROR_FAILURE;
 
     JSObject *securityObj;
     if (v.isObject()) {
--- a/configure.in
+++ b/configure.in
@@ -180,17 +180,17 @@ if test -n "$gonkdir" ; then
     CC="$gonk_toolchain_prefix"gcc
     CXX="$gonk_toolchain_prefix"g++
     CPP="$gonk_toolchain_prefix"cpp
     LD="$gonk_toolchain_prefix"ld
     AR="$gonk_toolchain_prefix"ar
     RANLIB="$gonk_toolchain_prefix"ranlib
     STRIP="$gonk_toolchain_prefix"strip
 
-    STLPORT_CPPFLAGS="-I$gonkdir/ndk/sources/cxx-stl/stlport/stlport/"
+    STLPORT_CPPFLAGS="-I$gonkdir/ndk/sources/cxx-stl/stlport/stlport/ -I$gonkdir/external/stlport/stlport/"
     STLPORT_LIBS="-lstlport"
 
     case "$target_cpu" in
     arm)
         ARCH_DIR=arch-arm
         ;;
     i?86)
         ARCH_DIR=arch-x86
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -177,17 +177,17 @@ LOCAL_INCLUDES += \
   -I$(topsrcdir)/content/xul/content/src \
   -I$(topsrcdir)/content/xul/document/src \
   -I$(topsrcdir)/dom/base \
   -I$(topsrcdir)/dom/ipc \
   -I$(topsrcdir)/image/src \
   -I$(topsrcdir)/js/xpconnect/src \
   -I$(topsrcdir)/layout/generic \
   -I$(topsrcdir)/layout/style \
-  -I$(topsrcdir)/layout/svg/base/src \
+  -I$(topsrcdir)/layout/svg \
   -I$(topsrcdir)/layout/xul/base/src \
   -I$(topsrcdir)/netwerk/base/src \
   $(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
 DEFINES += -DHB_DONT_DEFINE_STDINT
 
 # gcc requires -msse2 for this file since it uses SSE2 intrinsics.  (See bug
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -900,17 +900,17 @@ nsFrameScriptExecutor::TryCacheLoadAndCo
       JSObject* global = nullptr;
       mGlobal->GetJSObject(&global);
       if (global) {
         JSAutoCompartment ac(mCx, global);
         JS::CompileOptions options(mCx);
         options.setNoScriptRval(true)
                .setFileAndLine(url.get(), 1)
                .setPrincipals(nsJSPrincipals::get(mPrincipal));
-        JS::RootedObject empty(mCx, NULL);
+        js::RootedObject empty(mCx, NULL);
         JSScript* script = JS::Compile(mCx, empty, options,
                                        dataString.get(), dataString.Length());
 
         if (script) {
           nsAutoCString scheme;
           uri->GetScheme(scheme);
           // We don't cache data: scripts!
           if (!scheme.EqualsLiteral("data")) {
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -1587,17 +1587,16 @@ WebGLContext::GetSupportedExtensions(Nul
     nsTArray<nsString>& arr = retval.SetValue();
     
     if (IsExtensionSupported(OES_texture_float))
         arr.AppendElement(NS_LITERAL_STRING("OES_texture_float"));
     if (IsExtensionSupported(OES_standard_derivatives))
         arr.AppendElement(NS_LITERAL_STRING("OES_standard_derivatives"));
     if (IsExtensionSupported(EXT_texture_filter_anisotropic)) {
         arr.AppendElement(NS_LITERAL_STRING("EXT_texture_filter_anisotropic"));
-        arr.AppendElement(NS_LITERAL_STRING("MOZ_EXT_texture_filter_anisotropic"));
     }
     if (IsExtensionSupported(WEBGL_lose_context))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
     if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
     if (IsExtensionSupported(WEBGL_compressed_texture_atc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
     if (IsExtensionSupported(WEBGL_compressed_texture_pvrtc))
--- a/content/canvas/src/WebGLContextNotSupported.cpp
+++ b/content/canvas/src/WebGLContextNotSupported.cpp
@@ -19,9 +19,11 @@ DOMCI_DATA(WebGLRenderbuffer, void)
 DOMCI_DATA(WebGLUniformLocation, void)
 DOMCI_DATA(WebGLShaderPrecisionFormat, void)
 DOMCI_DATA(WebGLActiveInfo, void)
 DOMCI_DATA(WebGLExtension, void)
 DOMCI_DATA(WebGLExtensionStandardDerivatives, void)
 DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, void)
 DOMCI_DATA(WebGLExtensionLoseContext, void)
 DOMCI_DATA(WebGLExtensionCompressedTextureS3TC, void)
+DOMCI_DATA(WebGLExtensionCompressedTextureATC, void)
+DOMCI_DATA(WebGLExtensionCompressedTexturePVRTC, void)
 DOMCI_DATA(WebGLExtensionDepthTexture, void)
--- a/content/media/webaudio/AudioBuffer.cpp
+++ b/content/media/webaudio/AudioBuffer.cpp
@@ -57,29 +57,29 @@ AudioBuffer::~AudioBuffer()
   if (mChannels.Length()) {
     NS_DROP_JS_OBJECTS(this, AudioBuffer);
   }
 }
 
 bool
 AudioBuffer::InitializeBuffers(uint32_t aNumberOfChannels, JSContext* aJSContext)
 {
+  NS_HOLD_JS_OBJECTS(this, AudioBuffer);
+
   if (!mChannels.SetCapacity(aNumberOfChannels)) {
     return false;
   }
   for (uint32_t i = 0; i < aNumberOfChannels; ++i) {
     JSObject* array = JS_NewFloat32Array(aJSContext, mLength);
     if (!array) {
       return false;
     }
     mChannels.AppendElement(array);
   }
 
-  NS_HOLD_JS_OBJECTS(this, AudioBuffer);
-
   return true;
 }
 
 JSObject*
 AudioBuffer::WrapObject(JSContext* aCx, JSObject* aScope,
                         bool* aTriedToWrap)
 {
   return AudioBufferBinding::Wrap(aCx, aScope, this, aTriedToWrap);
--- a/content/smil/nsSMILAnimationController.cpp
+++ b/content/smil/nsSMILAnimationController.cpp
@@ -208,17 +208,17 @@ nsSMILAnimationController::Traverse(
 {
   // Traverse last compositor table
   if (mLastCompositorTable) {
     mLastCompositorTable->EnumerateEntries(CompositorTableEntryTraverse,
                                            aCallback);
   }
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::CompositorTableEntryTraverse(
                                       nsSMILCompositor* aCompositor,
                                       void* aArg)
 {
   nsCycleCollectionTraversalCallback* cb =
     static_cast<nsCycleCollectionTraversalCallback*>(aArg);
   aCompositor->Traverse(cb);
   return PL_DHASH_NEXT;
@@ -298,51 +298,51 @@ nsSMILAnimationController::MaybeStartSam
   } else {
     mDeferredStartSampling = true;
   }
 }
 
 //----------------------------------------------------------------------
 // Sample-related methods and callbacks
 
-PR_CALLBACK PLDHashOperator
+PLDHashOperator
 TransferCachedBaseValue(nsSMILCompositor* aCompositor,
                         void* aData)
 {
   nsSMILCompositorTable* lastCompositorTable =
     static_cast<nsSMILCompositorTable*>(aData);
   nsSMILCompositor* lastCompositor =
     lastCompositorTable->GetEntry(aCompositor->GetKey());
 
   if (lastCompositor) {
     aCompositor->StealCachedBaseValue(lastCompositor);
   }
 
   return PL_DHASH_NEXT;  
 }
 
-PR_CALLBACK PLDHashOperator
+PLDHashOperator
 RemoveCompositorFromTable(nsSMILCompositor* aCompositor,
                           void* aData)
 {
   nsSMILCompositorTable* lastCompositorTable =
     static_cast<nsSMILCompositorTable*>(aData);
   lastCompositorTable->RemoveEntry(aCompositor->GetKey());
   return PL_DHASH_NEXT;
 }
 
-PR_CALLBACK PLDHashOperator
+PLDHashOperator
 DoClearAnimationEffects(nsSMILCompositor* aCompositor,
                         void* /*aData*/)
 {
   aCompositor->ClearAnimationEffects();
   return PL_DHASH_NEXT;
 }
 
-PR_CALLBACK PLDHashOperator
+PLDHashOperator
 DoComposeAttribute(nsSMILCompositor* aCompositor,
                    void* /*aData*/)
 {
   aCompositor->ComposeAttribute();
   return PL_DHASH_NEXT;
 }
 
 void
@@ -462,47 +462,47 @@ nsSMILAnimationController::RewindElement
   mChildContainerTable.EnumerateEntries(RewindNeeded, &rewindNeeded);
   if (!rewindNeeded)
     return;
 
   mAnimationElementTable.EnumerateEntries(RewindAnimation, nullptr);
   mChildContainerTable.EnumerateEntries(ClearRewindNeeded, nullptr);
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::RewindNeeded(TimeContainerPtrKey* aKey,
                                         void* aData)
 {
   NS_ABORT_IF_FALSE(aData,
       "Null data pointer during time container enumeration");
   bool* rewindNeeded = static_cast<bool*>(aData);
 
   nsSMILTimeContainer* container = aKey->GetKey();
   if (container->NeedsRewind()) {
     *rewindNeeded = true;
     return PL_DHASH_STOP;
   }
 
   return PL_DHASH_NEXT;
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::RewindAnimation(AnimationElementPtrKey* aKey,
                                            void* aData)
 {
   nsISMILAnimationElement* animElem = aKey->GetKey();
   nsSMILTimeContainer* timeContainer = animElem->GetTimeContainer();
   if (timeContainer && timeContainer->NeedsRewind()) {
     animElem->TimedElement().Rewind();
   }
 
   return PL_DHASH_NEXT;
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::ClearRewindNeeded(TimeContainerPtrKey* aKey,
                                              void* aData)
 {
   aKey->GetKey()->ClearNeedsRewind();
   return PL_DHASH_NEXT;
 }
 
 void
@@ -577,17 +577,17 @@ nsSMILAnimationController::DoMilestoneSa
         elem->TimedElement().SampleEndAt(containerTime);
       } else {
         elem->TimedElement().SampleAt(containerTime);
       }
     }
   }
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::GetNextMilestone(TimeContainerPtrKey* aKey,
                                             void* aData)
 {
   NS_ABORT_IF_FALSE(aKey, "Null hash key for time container hash table");
   NS_ABORT_IF_FALSE(aKey->GetKey(), "Null time container key in hash table");
   NS_ABORT_IF_FALSE(aData,
       "Null data pointer during time container enumeration");
 
@@ -602,17 +602,17 @@ nsSMILAnimationController::GetNextMilest
     container->GetNextMilestoneInParentTime(thisMilestone);
   if (didGetMilestone && thisMilestone < *nextMilestone) {
     *nextMilestone = thisMilestone;
   }
 
   return PL_DHASH_NEXT;
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::GetMilestoneElements(TimeContainerPtrKey* aKey,
                                                 void* aData)
 {
   NS_ABORT_IF_FALSE(aKey, "Null hash key for time container hash table");
   NS_ABORT_IF_FALSE(aKey->GetKey(), "Null time container key in hash table");
   NS_ABORT_IF_FALSE(aData,
       "Null data pointer during time container enumeration");
 
@@ -624,17 +624,17 @@ nsSMILAnimationController::GetMilestoneE
     return PL_DHASH_NEXT;
 
   container->PopMilestoneElementsAtMilestone(params->mMilestone,
                                              params->mElements);
 
   return PL_DHASH_NEXT;
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::SampleTimeContainer(TimeContainerPtrKey* aKey,
                                                void* aData)
 {
   NS_ENSURE_TRUE(aKey, PL_DHASH_NEXT);
   NS_ENSURE_TRUE(aKey->GetKey(), PL_DHASH_NEXT);
   NS_ENSURE_TRUE(aData, PL_DHASH_NEXT);
 
   SampleTimeContainerParams* params =
@@ -647,17 +647,17 @@ nsSMILAnimationController::SampleTimeCon
     container->Sample();
     container->MarkSeekFinished();
     params->mActiveContainers->PutEntry(container);
   }
 
   return PL_DHASH_NEXT;
 }
 
-/*static*/ PR_CALLBACK PLDHashOperator
+/*static*/ PLDHashOperator
 nsSMILAnimationController::SampleAnimation(AnimationElementPtrKey* aKey,
                                            void* aData)
 {
   NS_ENSURE_TRUE(aKey, PL_DHASH_NEXT);
   NS_ENSURE_TRUE(aKey->GetKey(), PL_DHASH_NEXT);
   NS_ENSURE_TRUE(aData, PL_DHASH_NEXT);
 
   nsISMILAnimationElement* animElem = aKey->GetKey();
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -2313,17 +2313,17 @@ nsSMILTimedElement::AreEndTimesDependent
     }
   }
   return true;
 }
 
 //----------------------------------------------------------------------
 // Hashtable callback functions
 
-/* static */ PR_CALLBACK PLDHashOperator
+/* static */ PLDHashOperator
 nsSMILTimedElement::NotifyNewIntervalCallback(TimeValueSpecPtrKey* aKey,
                                               void* aData)
 {
   NS_ABORT_IF_FALSE(aKey, "Null hash key for time container hash table");
   NS_ABORT_IF_FALSE(aKey->GetKey(),
                     "null nsSMILTimeValueSpec in set of time dependents");
 
   NotifyTimeDependentsParams* params =
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -146,17 +146,17 @@ EXPORTS =  			\
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES += 	\
 		-I$(srcdir)/../../../xml/content/src \
 		-I$(srcdir)/../../../../dom \
 		-I$(srcdir)/../../../base/src \
 		-I$(srcdir)/../../../../layout/generic \
 		-I$(srcdir)/../../../../layout/xul/base/src \
-		-I$(srcdir)/../../../../layout/svg/base/src \
+		-I$(srcdir)/../../../../layout/svg \
 		-I$(srcdir)/../../../../layout/style \
 		-I$(srcdir)/../../../events/src \
 		-I$(srcdir)/../../../html/content/src \
 		-I$(topsrcdir)/content/xbl/src \
 		-I$(srcdir)/../../../smil \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -166,17 +166,17 @@ InstallXBLField(JSContext* cx,
   // because in this method we've entered |this|'s compartment (see in
   // Field[GS]etter where we attempt a cross-compartment call), we must enter
   // the callee's compartment to access its reserved slots.
   nsXBLPrototypeBinding* protoBinding;
   nsDependentJSString fieldName;
   {
     JSAutoCompartment ac(cx, callee);
 
-    JS::Rooted<JSObject*> xblProto(cx);
+    js::Rooted<JSObject*> xblProto(cx);
     xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();
 
     JS::Value name = js::GetFunctionNativeReserved(callee, FIELD_SLOT);
     JSFlatString* fieldStr = JS_ASSERT_STRING_IS_FLAT(name.toString());
     fieldName.init(fieldStr);
 
     MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp));
 
@@ -212,31 +212,31 @@ InstallXBLField(JSContext* cx,
 }
 
 bool
 FieldGetterImpl(JSContext *cx, JS::CallArgs args)
 {
   const JS::Value &thisv = args.thisv();
   MOZ_ASSERT(ValueHasISupportsPrivate(thisv));
 
-  JS::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
+  js::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
 
   bool installed = false;
-  JS::Rooted<JSObject*> callee(cx, &args.calleev().toObject());
-  JS::Rooted<jsid> id(cx);
+  js::Rooted<JSObject*> callee(cx, &args.calleev().toObject());
+  js::Rooted<jsid> id(cx);
   if (!InstallXBLField(cx, callee, thisObj, id.address(), &installed)) {
     return false;
   }
 
   if (!installed) {
     args.rval().setUndefined();
     return true;
   }
 
-  JS::Rooted<JS::Value> v(cx);
+  js::Rooted<JS::Value> v(cx);
   if (!JS_GetPropertyById(cx, thisObj, id, v.address())) {
     return false;
   }
   args.rval().set(v);
   return true;
 }
 
 static JSBool
@@ -248,26 +248,26 @@ FieldGetter(JSContext *cx, unsigned argc
 }
 
 bool
 FieldSetterImpl(JSContext *cx, JS::CallArgs args)
 {
   const JS::Value &thisv = args.thisv();
   MOZ_ASSERT(ValueHasISupportsPrivate(thisv));
 
-  JS::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
+  js::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
 
   bool installed = false;
-  JS::Rooted<JSObject*> callee(cx, &args.calleev().toObject());
-  JS::Rooted<jsid> id(cx);
+  js::Rooted<JSObject*> callee(cx, &args.calleev().toObject());
+  js::Rooted<jsid> id(cx);
   if (!InstallXBLField(cx, callee, thisObj, id.address(), &installed)) {
     return false;
   }
 
-  JS::Rooted<JS::Value> v(cx,
+  js::Rooted<JS::Value> v(cx,
                           args.length() > 0 ? args[0] : JS::UndefinedValue());
   return JS_SetPropertyById(cx, thisObj, id, v.address());
 }
 
 static JSBool
 FieldSetter(JSContext *cx, unsigned argc, JS::Value *vp)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
@@ -295,30 +295,30 @@ XBLResolve(JSContext *cx, JSHandleObject
   nsDependentJSString fieldName(id);
   nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
   if (!field || field->IsEmpty()) {
     return true;
   }
 
   // We have a field: now install a getter/setter pair which will resolve the
   // field onto the actual object, when invoked.
-  JS::Rooted<JSObject*> global(cx, JS_GetGlobalForObject(cx, obj));
+  js::Rooted<JSObject*> global(cx, JS_GetGlobalForObject(cx, obj));
 
-  JS::Rooted<JSObject*> get(cx);
+  js::Rooted<JSObject*> get(cx);
   get = ::JS_GetFunctionObject(js::NewFunctionByIdWithReserved(cx, FieldGetter,
                                                                0, 0, global,
                                                                id));
   if (!get) {
     return false;
   }
   js::SetFunctionNativeReserved(get, XBLPROTO_SLOT, JS::ObjectValue(*obj));
   js::SetFunctionNativeReserved(get, FIELD_SLOT,
                                 JS::StringValue(JSID_TO_STRING(id)));
 
-  JS::Rooted<JSObject*> set(cx);
+  js::Rooted<JSObject*> set(cx);
   set = ::JS_GetFunctionObject(js::NewFunctionByIdWithReserved(cx, FieldSetter,
                                                                1, 0, global,
                                                                id));
   if (!set) {
     return false;
   }
   js::SetFunctionNativeReserved(set, XBLPROTO_SLOT, JS::ObjectValue(*obj));
   js::SetFunctionNativeReserved(set, FIELD_SLOT,
@@ -1212,17 +1212,19 @@ nsXBLBinding::ChangeDocument(nsIDocument
 
               // Find the right prototype.
               JSObject* base = scriptObject;
               JSObject* proto;
               JSAutoRequest ar(cx);
               JSAutoCompartment ac(cx, scriptObject);
 
               for ( ; true; base = proto) { // Will break out on null proto
-                proto = ::JS_GetPrototype(base);
+                if (!JS_GetPrototype(cx, base, &proto)) {
+                  return;
+                }
                 if (!proto) {
                   break;
                 }
 
                 JSClass* clazz = ::JS_GetClass(proto);
                 if (!clazz ||
                     (~clazz->flags &
                      (JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS)) ||
@@ -1244,17 +1246,20 @@ nsXBLBinding::ChangeDocument(nsIDocument
 
                 if (JSVAL_TO_PRIVATE(protoBinding) != mPrototypeBinding) {
                   // Not the right binding
                   continue;
                 }
 
                 // Alright!  This is the right prototype.  Pull it out of the
                 // proto chain.
-                JSObject* grandProto = ::JS_GetPrototype(proto);
+                JSObject* grandProto;
+                if (!JS_GetPrototype(cx, proto, &grandProto)) {
+                  return;
+                }
                 ::JS_SetPrototype(cx, base, grandProto);
                 break;
               }
 
               mPrototypeBinding->UndefineFields(cx, scriptObject);
 
               // Don't remove the reference from the document to the
               // wrapper here since it'll be removed by the element
@@ -1341,17 +1346,19 @@ nsXBLBinding::DoInitJSClass(JSContext *c
   nsAutoCString className(aClassName);
   JSObject* parent_proto = nullptr;  // If we have an "obj" we can set this
   JSAutoRequest ar(cx);
 
   JSAutoCompartment ac(cx, global);
 
   if (obj) {
     // Retrieve the current prototype of obj.
-    parent_proto = ::JS_GetPrototype(obj);
+    if (!JS_GetPrototype(cx, obj, &parent_proto)) {
+      return NS_ERROR_FAILURE;
+    }
     if (parent_proto) {
       // We need to create a unique classname based on aClassName and
       // parent_proto.  Append a space (an invalid URI character) to ensure that
       // we don't have accidental collisions with the case when parent_proto is
       // null and aClassName ends in some bizarre numbers (yeah, it's unlikely).
       jsid parent_proto_id;
       if (!::JS_GetObjectId(cx, parent_proto, &parent_proto_id)) {
         // Probably OOM
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -93,17 +93,19 @@ nsXBLDocGlobalObject::doCheckAccess(JSCo
   if (!ssm) {
     ::JS_ReportError(cx, "Unable to verify access to a global object property.");
     return JS_FALSE;
   }
 
   // Make sure to actually operate on our object, and not some object further
   // down on the proto chain.
   while (JS_GetClass(obj) != &nsXBLDocGlobalObject::gSharedGlobalClass) {
-    obj = ::JS_GetPrototype(obj);
+    if (!::JS_GetPrototype(cx, obj, &obj)) {
+      return JS_FALSE;
+    }
     if (!obj) {
       ::JS_ReportError(cx, "Invalid access to a global object property.");
       return JS_FALSE;
     }
   }
 
   nsresult rv = ssm->CheckPropertyAccess(cx, obj, JS_GetClass(obj)->name,
                                          id, accessType);
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -492,20 +492,30 @@ let DOMApplicationRegistry = {
   // Webapps:RemoveApp
   // Webapps:Install:Return:OK
   // Webapps:Uninstall:Return:OK
   // Webapps:OfflineCache
   broadcastMessage: function broadcastMessage(aMsgName, aContent) {
     if (!(aMsgName in this.children)) {
       return;
     }
-
-    this.children[aMsgName].forEach(function _doBroadcast(aMsgMgr) {
-      aMsgMgr.sendAsyncMessage(aMsgName, aContent);
-    });
+    let i;
+    for (i = this.children[aMsgName].length - 1; i >= 0; i -= 1) {
+      let msgMgr = this.children[aMsgName][i];
+      try {
+        msgMgr.sendAsyncMessage(aMsgName, aContent);
+      } catch (e) {
+        // Remove once 777508 lands.
+        let index;
+        if ((index = this.children[aMsgName].indexOf(msgMgr)) != -1) {
+          this.children[aMsgName].splice(index, 1);
+          dump("Remove dead MessageManager!\n");
+        }
+      }
+    };
   },
 
   _getAppDir: function(aId) {
     return FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
   },
 
   _writeFile: function ss_writeFile(aFile, aData, aCallbak) {
     // Initialize the file output stream.
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1900,24 +1900,24 @@ jsid nsDOMClassInfo::sOnload_id         
 jsid nsDOMClassInfo::sOnerror_id         = JSID_VOID;
 
 static const JSClass *sObjectClass = nullptr;
 
 /**
  * Set our JSClass pointer for the Object class
  */
 static void
-FindObjectClass(JSObject* aGlobalObject)
+FindObjectClass(JSContext* cx, JSObject* aGlobalObject)
 {
   NS_ASSERTION(!sObjectClass,
                "Double set of sObjectClass");
   JSObject *obj, *proto = aGlobalObject;
   do {
     obj = proto;
-    proto = js::GetObjectProto(obj);
+    js::GetObjectProto(cx, obj, &proto);
   } while (proto);
 
   sObjectClass = js::GetObjectJSClass(obj);
 }
 
 static void
 PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
 {
@@ -5121,24 +5121,27 @@ nsDOMClassInfo::PostCreatePrototype(JSCo
   if (!xpc::DOM_DefineQuickStubs(cx, proto, flags, count, mData->mInterfaces)) {
     JS_ClearPendingException(cx);
   }
 
   // This is called before any other location that requires
   // sObjectClass, so compute it here. We assume that nobody has had a
   // chance to monkey around with proto's prototype chain before this.
   if (!sObjectClass) {
-    FindObjectClass(proto);
+    FindObjectClass(cx, proto);
     NS_ASSERTION(sObjectClass && !strcmp(sObjectClass->name, "Object"),
                  "Incorrect object class!");
   }
 
-  NS_ASSERTION(::JS_GetPrototype(proto) &&
-               JS_GetClass(::JS_GetPrototype(proto)) == sObjectClass,
-               "Hmm, somebody did something evil?");
+#ifdef DEBUG
+    JSObject *proto2;
+    JS_GetPrototype(cx, proto, &proto2);
+    NS_ASSERTION(proto2 && JS_GetClass(proto2) == sObjectClass,
+                 "Hmm, somebody did something evil?");
+#endif
 
 #ifdef DEBUG
   if (mData->mHasClassInterface && mData->mProtoChainInterface &&
       mData->mProtoChainInterface != &NS_GET_IID(nsISupports)) {
     nsCOMPtr<nsIInterfaceInfoManager>
       iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
 
     if (iim) {
@@ -5457,17 +5460,20 @@ nsWindowSH::GlobalScopePolluterNewResolv
   nsHTMLDocument *document = GetDocument(obj);
 
   if (!document) {
     // If we don't have a document, return early.
 
     return JS_TRUE;
   }
 
-  JSObject *proto = ::JS_GetPrototype(obj);
+  JSObject *proto;
+  if (!::JS_GetPrototype(cx, obj, &proto)) {
+    return JS_FALSE;
+  }
   JSBool hasProp;
 
   if (!proto || !::JS_HasPropertyById(cx, proto, id, &hasProp) ||
       hasProp) {
     // No prototype, or the property exists on the prototype. Do
     // nothing.
 
     return JS_TRUE;
@@ -5500,40 +5506,54 @@ nsWindowSH::GlobalScopePolluterNewResolv
 
     objp.set(obj);
   }
 
   return JS_TRUE;
 }
 
 // static
-void
+JSBool
 nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
 {
   JSObject *proto;
 
   JSAutoRequest ar(cx);
 
-  while ((proto = ::JS_GetPrototype(obj))) {
+  for (;;) {
+    if (!::JS_GetPrototype(cx, obj, &proto)) {
+      return JS_FALSE;
+    }
+    if (!proto) {
+      break;
+    }
+
     if (JS_GetClass(proto) == &sGlobalScopePolluterClass) {
       nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(proto);
 
       NS_IF_RELEASE(doc);
 
       ::JS_SetPrivate(proto, nullptr);
 
+      JSObject *proto_proto;
+      if (!::JS_GetPrototype(cx, proto, &proto_proto)) {
+        return JS_FALSE;
+      }
+
       // Pull the global scope polluter out of the prototype chain so
       // that it can be freed.
-      ::JS_SplicePrototype(cx, obj, ::JS_GetPrototype(proto));
+      ::JS_SplicePrototype(cx, obj, proto_proto);
 
       break;
     }
 
     obj = proto;
   }
+
+  return JS_TRUE;
 }
 
 // static
 nsresult
 nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
                                        nsIHTMLDocument *doc)
 {
   // If global scope pollution is disabled, or if our document is not
@@ -5549,17 +5569,23 @@ nsWindowSH::InstallGlobalScopePolluter(J
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JSObject *o = obj, *proto;
 
   // Find the place in the prototype chain where we want this global
   // scope polluter (right before Object.prototype).
 
-  while ((proto = ::JS_GetPrototype(o))) {
+  for (;;) {
+    if (!::JS_GetPrototype(cx, o, &proto)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    if (!proto) {
+      break;
+    }
     if (JS_GetClass(proto) == sObjectClass) {
       // Set the global scope polluters prototype to Object.prototype
       ::JS_SplicePrototype(cx, gsp, proto);
 
       break;
     }
 
     o = proto;
@@ -6317,18 +6343,24 @@ nsDOMConstructor::HasInstance(nsIXPConne
     }
 
     if (JSVAL_IS_PRIMITIVE(val)) {
       return NS_OK;
     }
 
     JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
 
-    JSObject *proto = JS_GetPrototype(dom_obj);
-    for ( ; proto; proto = JS_GetPrototype(proto)) {
+    JSObject *proto = dom_obj;
+    for (;;) {
+      if (!JS_GetPrototype(cx, proto, &proto)) {
+        return NS_ERROR_UNEXPECTED;
+      }
+      if (!proto) {
+        break;
+      }
       if (proto == dot_prototype) {
         *bp = true;
         break;
       }
     }
 
     return NS_OK;
   }
@@ -6677,17 +6709,20 @@ ResolvePrototype(nsIXPConnect *aXPConnec
         if (val.isObject()) {
           proto = &val.toObject();
         }
       }
     }
 
     if (dot_prototype) {
       JSAutoCompartment ac(cx, dot_prototype);
-      JSObject *xpc_proto_proto = ::JS_GetPrototype(dot_prototype);
+      JSObject *xpc_proto_proto;
+      if (!::JS_GetPrototype(cx, dot_prototype, &xpc_proto_proto)) {
+        return NS_ERROR_UNEXPECTED;
+      }
 
       if (proto &&
           (!xpc_proto_proto ||
            JS_GetClass(xpc_proto_proto) == sObjectClass)) {
         if (!JS_WrapObject(cx, &proto) ||
             !JS_SetPrototype(cx, dot_prototype, proto)) {
           return NS_ERROR_UNEXPECTED;
         }
@@ -7071,33 +7106,33 @@ LocationSetter(JSContext *cx, JSHandleOb
 
   return JS_TRUE;
 }
 
 static JSBool
 LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBool strict,
                         JSMutableHandleValue vp)
 {
-  JS::RootedObject obj(cx, obj_);
+  js::RootedObject obj(cx, obj_);
 
   JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
   if (wrapped) {
     obj = wrapped;
   }
 
   return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp);
 }
 
 NS_IMETHODIMP
 nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj_, jsid id_, uint32_t flags,
                        JSObject **objp, bool *_retval)
 {
-  JS::RootedObject obj(cx, obj_);
-  JS::RootedId id(cx, id_);
+  js::RootedObject obj(cx, obj_);
+  js::RootedId id(cx, id_);
 
   nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
 
   if (!JSID_IS_STRING(id)) {
     if (JSID_IS_INT(id) && JSID_TO_INT(id) >= 0 && !(flags & JSRESOLVE_ASSIGNING)) {
       // If we're resolving a numeric property, treat that as if
       // window.frames[n] is resolved (since window.frames ===
       // window), if window.frames[n] is a child frame, define a
@@ -7309,17 +7344,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
   // It is not worth calling GlobalResolve() if we are resolving
   // for assignment, since only read-write properties get dealt
   // with there.
   if (!(flags & JSRESOLVE_ASSIGNING)) {
     JSAutoRequest ar(cx);
 
     // Resolve special classes.
     for (uint32_t i = 0; i < ArrayLength(sOtherResolveFuncs); i++) {
-      JS::RootedObject tmp(cx, *objp);
+      js::RootedObject tmp(cx, *objp);
       if (!sOtherResolveFuncs[i](cx, obj, id, flags, &tmp)) {
         return NS_ERROR_FAILURE;
       }
       *objp = tmp;
       if (*objp) {
         return NS_OK;
       }
     }
@@ -7495,17 +7530,21 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
   // binding a name) a new undefined property that's not already
   // defined on our prototype chain. This way we can access this
   // expando w/o ever getting back into XPConnect.
   if (flags & JSRESOLVE_ASSIGNING) {
     JSObject *realObj;
     wrapper->GetJSObject(&realObj);
 
     if (obj == realObj) {
-      JSObject *proto = js::GetObjectProto(obj);
+      JSObject *proto;
+      if (!js::GetObjectProto(cx, obj, &proto)) {
+          *_retval = JS_FALSE;
+          return NS_OK;
+      }
       if (proto) {
         JSObject *pobj = NULL;
         jsval val;
 
         if (!::JS_LookupPropertyWithFlagsById(cx, proto, id, flags,
                                               &pobj, &val)) {
           *_retval = JS_FALSE;
 
@@ -8419,17 +8458,20 @@ nsNamedArraySH::NewResolve(nsIXPConnectW
 
       if (wrapper) {
         wrapper->GetJSObject(&realObj);
       } else {
         realObj = obj;
       }
 
       JSAutoCompartment ac(cx, realObj);
-      JSObject *proto = ::JS_GetPrototype(realObj);
+      JSObject *proto;
+      if (!::JS_GetPrototype(cx, realObj, &proto)) {
+        return NS_ERROR_FAILURE;
+      }
 
       if (proto) {
         JSBool hasProp;
         if (!::JS_HasPropertyById(cx, proto, id, &hasProp)) {
           *_retval = false;
           return NS_ERROR_FAILURE;
         }
 
@@ -8934,17 +8976,19 @@ nsHTMLDocumentSH::DocumentAllGetProperty
   // newResolve hook, so nothing to do for those properties here. And
   // we need to return early to prevent <div id="item"> from shadowing
   // document.all.item(), etc.
   if (sItem_id == id || sNamedItem_id == id) {
     return JS_TRUE;
   }
 
   while (js::GetObjectJSClass(obj) != &sHTMLDocumentAllClass) {
-    obj = js::GetObjectProto(obj);
+    if (!js::GetObjectProto(cx, obj, &obj)) {
+      return JS_FALSE;
+    }
 
     if (!obj) {
       NS_ERROR("The JS engine lies!");
 
       return JS_TRUE;
     }
   }
 
@@ -9028,17 +9072,17 @@ nsHTMLDocumentSH::DocumentAllNewResolve(
                                         unsigned flags, JSMutableHandleObject objp)
 {
   if (flags & JSRESOLVE_ASSIGNING) {
     // Nothing to do here if we're assigning
 
     return JS_TRUE;
   }
 
-  JS::RootedValue v(cx);
+  js::RootedValue v(cx);
 
   if (sItem_id == id || sNamedItem_id == id) {
     // Define the item() or namedItem() method.
 
     JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallToGetPropMapper,
                                               0, JSPROP_ENUMERATE);
     objp.set(obj);
 
@@ -9133,24 +9177,27 @@ nsHTMLDocumentSH::CallToGetPropMapper(JS
   if (!chars) {
     return JS_FALSE;
   }
 
   return ::JS_GetUCProperty(cx, self, chars, length, vp);
 }
 
 
-static inline JSObject *
-GetDocumentAllHelper(JSObject *obj)
+static inline bool
+GetDocumentAllHelper(JSContext *cx, JSObject *obj, JSObject **result)
 {
   while (obj && JS_GetClass(obj) != &sHTMLDocumentAllHelperClass) {
-    obj = ::JS_GetPrototype(obj);
-  }
-
-  return obj;
+    if (!::JS_GetPrototype(cx, obj, &obj)) {
+      return false;
+    }
+  }
+
+  *result = obj;
+  return true;
 }
 
 static inline void *
 FlagsToPrivate(uint32_t flags)
 {
   MOZ_ASSERT((flags & (1 << 31)) == 0);
   return reinterpret_cast<void*>(static_cast<uintptr_t>(flags << 1));
 }
@@ -9166,17 +9213,20 @@ PrivateToFlags(void *priv)
 JSBool
 nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
                                                JSHandleId id, JSMutableHandleValue vp)
 {
   if (nsDOMClassInfo::sAll_id != id) {
     return JS_TRUE;
   }
 
-  JSObject *helper = GetDocumentAllHelper(obj);
+  JSObject *helper;
+  if (!GetDocumentAllHelper(cx, obj, &helper)) {
+    return JS_FALSE;
+  }
 
   if (!helper) {
     NS_ERROR("Uh, how'd we get here?");
 
     // Let scripts continue, if we somehow did get here...
 
     return JS_TRUE;
   }
@@ -9224,17 +9274,20 @@ nsHTMLDocumentSH::DocumentAllHelperGetPr
 
 JSBool
 nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
                                               JSHandleId id, unsigned flags,
                                               JSMutableHandleObject objp)
 {
   if (nsDOMClassInfo::sAll_id == id) {
     // document.all is resolved for the first time. Define it.
-    JSObject *helper = GetDocumentAllHelper(obj);
+    JSObject *helper;
+    if (!GetDocumentAllHelper(cx, obj, &helper)) {
+      return JS_FALSE;
+    }
 
     if (helper) {
       if (!::JS_DefineProperty(cx, helper, "all", JSVAL_VOID, nullptr, nullptr,
                                JSPROP_ENUMERATE)) {
         return JS_FALSE;
       }
 
       objp.set(helper);
@@ -9248,17 +9301,20 @@ nsHTMLDocumentSH::DocumentAllHelperNewRe
 JSBool
 nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
                                             JSHandleId id, unsigned flags,
                                             JSMutableHandleObject objp)
 {
   if (JSID_IS_STRING(id)) {
     nsDocument *doc = GetDocument(obj);
 
-    JSObject *proto = ::JS_GetPrototype(obj);
+    JSObject *proto;
+    if (!::JS_GetPrototype(cx, obj, &proto)) {
+      return JS_FALSE;
+    }
     if (NS_UNLIKELY(!proto)) {
       return JS_TRUE;
     }
 
     JSBool found;
     if (!::JS_HasPropertyById(cx, proto, id, &found)) {
       return JS_FALSE;
     }
@@ -9327,53 +9383,69 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnec
       }
     }
 
     if (id == sAll_id && !sDisableDocumentAllSupport &&
         !ObjectIsNativeWrapper(cx, obj)) {
       nsIDocument *doc = static_cast<nsIDocument*>(wrapper->Native());
 
       if (doc->GetCompatibilityMode() == eCompatibility_NavQuirks) {
-        JSObject *helper = GetDocumentAllHelper(::JS_GetPrototype(obj));
-
-        JSObject *proto = ::JS_GetPrototype(helper ? helper : obj);
+        JSObject *proto;
+        if (!::JS_GetPrototype(cx, obj, &proto)) {
+          return NS_ERROR_FAILURE;
+        }
+
+        JSObject *helper;
+        if (!GetDocumentAllHelper(cx, proto, &helper)) {
+          return NS_ERROR_FAILURE;
+        }
+
+        if (!::JS_GetPrototype(cx, helper ? helper : obj, &proto)) {
+          return NS_ERROR_FAILURE;
+        }
 
         // Check if the property all is defined on obj's (or helper's
         // if obj doesn't exist) prototype, if it is, don't expose our
         // document.all helper.
 
         JSBool hasAll = JS_FALSE;
         if (proto && !JS_HasProperty(cx, proto, "all", &hasAll)) {
           return NS_ERROR_UNEXPECTED;
         }
 
         if (hasAll && helper) {
           // Our helper's prototype now has an "all" property, remove
           // the helper out of the prototype chain to prevent
           // shadowing of the now defined "all" property.
-          JSObject *tmp = obj, *tmpProto;
-
-          while ((tmpProto = ::JS_GetPrototype(tmp)) != helper) {
+          JSObject *tmp = obj, *tmpProto = tmp;
+
+          do {
             tmp = tmpProto;
-          }
+            if (!::JS_GetPrototype(cx, tmp, &tmpProto)) {
+              return NS_ERROR_UNEXPECTED;
+            }
+          } while (tmpProto != helper);
 
           ::JS_SetPrototype(cx, tmp, proto);
         }
 
         // If we don't already have a helper, and we're resolving
         // document.all qualified, and we're *not* detecting
         // document.all, e.g. if (document.all), and "all" isn't
         // already defined on our prototype, create a helper.
         if (!helper && flags & JSRESOLVE_QUALIFIED &&
             !(flags & JSRESOLVE_DETECTING) && !hasAll) {
           // Print a warning so developers can stop using document.all
           PrintWarningOnConsole(cx, "DocumentAllUsed");
 
+          if (!::JS_GetPrototype(cx, obj, &proto)) {
+            return NS_ERROR_UNEXPECTED;
+          }
           helper = ::JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
-                                  ::JS_GetPrototype(obj),
+                                  proto,
                                   ::JS_GetGlobalForObject(cx, obj));
 
           if (!helper) {
             return NS_ERROR_OUT_OF_MEMORY;
           }
 
           // Insert the helper into our prototype chain. helper's prototype
           // is already obj's current prototype.
@@ -9933,17 +10005,20 @@ nsHTMLPluginObjElementSH::PostTransplant
 
 NS_IMETHODIMP
 nsHTMLPluginObjElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
                                       JSContext *cx, JSObject *obj, jsid id,
                                       jsval *vp, bool *_retval)
 {
   JSAutoRequest ar(cx);
 
-  JSObject *pi_obj = ::JS_GetPrototype(obj);
+  JSObject *pi_obj;
+  if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
+    return NS_ERROR_UNEXPECTED;
+  }
   if (NS_UNLIKELY(!pi_obj)) {
     return NS_OK;
   }
 
   JSBool found = false;
 
   if (!ObjectIsNativeWrapper(cx, obj)) {
     *_retval = ::JS_HasPropertyById(cx, pi_obj, id, &found);
@@ -9962,17 +10037,20 @@ nsHTMLPluginObjElementSH::GetProperty(ns
 
 NS_IMETHODIMP
 nsHTMLPluginObjElementSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
                                       JSContext *cx, JSObject *obj, jsid id,
                                       jsval *vp, bool *_retval)
 {
   JSAutoRequest ar(cx);
 
-  JSObject *pi_obj = ::JS_GetPrototype(obj);
+  JSObject *pi_obj;
+  if (!::JS_GetPrototype(cx, obj, &pi_obj)) {
+    return NS_ERROR_UNEXPECTED;
+  }
   if (NS_UNLIKELY(!pi_obj)) {
     return NS_OK;
   }
 
   JSBool found = false;
 
   if (!ObjectIsNativeWrapper(cx, obj)) {
     *_retval = ::JS_HasPropertyById(cx, pi_obj, id, &found);
@@ -10038,17 +10116,19 @@ nsHTMLPluginObjElementSH::GetPluginJSObj
   // NB: We need an AutoEnterCompartment because we can be called from
   // nsObjectFrame when the plugin loads after the JS object for our content
   // node has been created.
   JSAutoCompartment ac(cx, obj);
 
   if (plugin_inst) {
     plugin_inst->GetJSObject(cx, plugin_obj);
     if (*plugin_obj) {
-      *plugin_proto = ::JS_GetPrototype(*plugin_obj);
+      if (!::JS_GetPrototype(cx, *plugin_obj, plugin_proto)) {
+        return NS_ERROR_UNEXPECTED;
+      }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLPluginObjElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
@@ -10383,17 +10463,20 @@ nsStorage2SH::NewResolve(nsIXPConnectWra
   // First check to see if the property is defined on our prototype,
   // after converting id to a string if it's an integer.
 
   JSString *jsstr = IdToString(cx, id);
   if (!jsstr) {
     return NS_OK;
   }
 
-  JSObject *proto = ::JS_GetPrototype(realObj);
+  JSObject *proto;
+  if (!::JS_GetPrototype(cx, realObj, &proto)) {
+    return NS_ERROR_FAILURE;
+  }
   JSBool hasProp;
 
   if (proto &&
       (::JS_HasPropertyById(cx, proto, id, &hasProp) &&
        hasProp)) {
     // We found the property we're resolving on the prototype,
     // nothing left to do here then.
 
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -415,17 +415,17 @@ public:
                                               JSHandleId id, unsigned flags,
                                               JSMutableHandleObject objp);
   static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
                                                JSHandleId id, JSMutableHandleValue vp);
   static JSBool SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                           JSMutableHandleValue vp);
   static JSBool SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                        JSBool strict, JSMutableHandleValue vp);
-  static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
+  static JSBool InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
   static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
                                              nsIHTMLDocument *doc);
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsWindowSH(aData);
   }
 };
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1962,17 +1962,17 @@ nsDOMWindowUtils::GetParent(const JS::Va
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   // First argument must be an object.
   if (JSVAL_IS_PRIMITIVE(aObject)) {
     return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
 
-  JS::Rooted<JSObject*> parent(aCx, JS_GetParent(JSVAL_TO_OBJECT(aObject)));
+  js::Rooted<JSObject*> parent(aCx, JS_GetParent(JSVAL_TO_OBJECT(aObject)));
   *aParent = OBJECT_TO_JSVAL(parent);
 
   // Outerize if necessary.
   if (parent) {
     if (JSObjectOp outerize = js::GetObjectClass(parent)->ext.outerObject) {
       *aParent = OBJECT_TO_JSVAL(outerize(aCx, parent));
     }
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -620,17 +620,21 @@ nsOuterWindowProxy::finalize(JSFreeOp *f
 
 nsOuterWindowProxy
 nsOuterWindowProxy::singleton;
 
 static JSObject*
 NewOuterWindowProxy(JSContext *cx, JSObject *parent)
 {
   JSAutoCompartment ac(cx, parent);
-  JSObject *obj = js::Wrapper::New(cx, parent, js::GetObjectProto(parent), parent,
+  JSObject *proto;
+  if (!js::GetObjectProto(cx, parent, &proto))
+    return nullptr;
+
+  JSObject *obj = js::Wrapper::New(cx, parent, proto, parent,
                                    &nsOuterWindowProxy::singleton);
   NS_ASSERTION(js::GetObjectClass(obj)->ext.innerObject, "bad class");
   return obj;
 }
 
 //*****************************************************************************
 //***    nsGlobalWindow: Object Management
 //*****************************************************************************
@@ -1678,17 +1682,21 @@ nsresult
 nsGlobalWindow::SetOuterObject(JSContext* aCx, JSObject* aOuterObject)
 {
   // Force our context's global object to be the outer.
   // NB: JS_SetGlobalObject sets aCx->compartment.
   JS_SetGlobalObject(aCx, aOuterObject);
 
   // Set up the prototype for the outer object.
   JSObject* inner = JS_GetParent(aOuterObject);
-  JS_SetPrototype(aCx, aOuterObject, JS_GetPrototype(inner));
+  JSObject* proto;
+  if (!JS_GetPrototype(aCx, inner, &proto)) {
+    return NS_ERROR_FAILURE;
+  }
+  JS_SetPrototype(aCx, aOuterObject, proto);
 
   return NS_OK;
 }
 
 /**
  * Create a new global object that will be used for an inner window.
  * Return the native global and an nsISupports 'holder' that can be used
  * to manage the lifetime of it.
@@ -1847,17 +1855,19 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   if (reUseInnerWindow) {
     // We're reusing the current inner window.
     NS_ASSERTION(!currentInner->IsFrozen(),
                  "We should never be reusing a shared inner window");
     newInnerWindow = currentInner;
 
     if (aDocument != oldDoc) {
       xpc_UnmarkGrayObject(currentInner->mJSObject);
-      nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
+      if (!nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject)) {
+        return NS_ERROR_FAILURE;
+      }
     }
 
     // We're reusing the inner window, but this still counts as a navigation,
     // so all expandos and such defined on the outer window should go away. Force
     // all Xray wrappers to be recomputed.
     xpc_UnmarkGrayObject(mJSObject);
     if (!JS_RefreshCrossCompartmentWrappers(cx, mJSObject)) {
       return NS_ERROR_FAILURE;
@@ -1983,17 +1993,18 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       mJSObject = outerObject;
       SetWrapper(mJSObject);
 
       {
         JSAutoCompartment ac(cx, mJSObject);
 
         JS_SetParent(cx, mJSObject, newInnerWindow->mJSObject);
 
-        SetOuterObject(cx, mJSObject);
+        rv = SetOuterObject(cx, mJSObject);
+        NS_ENSURE_SUCCESS(rv, rv);
 
         JSCompartment *compartment = js::GetObjectCompartment(mJSObject);
         xpc::CompartmentPrivate *priv =
           static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
         if (priv && priv->waiverWrapperMap) {
           NS_ASSERTION(!JS_IsExceptionPending(cx),
                        "We might overwrite a pending exception!");
           priv->waiverWrapperMap->Reparent(cx, newInnerWindow->mJSObject);
@@ -2040,19 +2051,23 @@ nsGlobalWindow::SetNewDocument(nsIDocume
     JSObject* newInnerJSObject = newInnerWindow->FastGetGlobalJSObject();
 #endif
 
     // Now that we're connecting the outer global to the inner one,
     // we must have transplanted it. The JS engine tries to maintain
     // the global object's compartment as its default compartment,
     // so update that now since it might have changed.
     JS_SetGlobalObject(cx, mJSObject);
-    NS_ASSERTION(JS_GetPrototype(mJSObject) ==
-                 JS_GetPrototype(newInnerJSObject),
+#ifdef DEBUG
+    JSObject *proto1, *proto2;
+    JS_GetPrototype(cx, mJSObject, &proto1);
+    JS_GetPrototype(cx, newInnerJSObject, &proto2);
+    NS_ASSERTION(proto1 == proto2,
                  "outer and inner globals should have the same prototype");
+#endif
 
     nsCOMPtr<nsIContent> frame = do_QueryInterface(GetFrameElementInternal());
     if (frame) {
       nsPIDOMWindow* parentWindow = frame->OwnerDoc()->GetWindow();
       if (parentWindow && parentWindow->TimeoutSuspendCount()) {
         SuspendTimeouts(parentWindow->TimeoutSuspendCount());
       }
     }
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1302,17 +1302,17 @@ nsJSContext::EvaluateStringWithValue(con
     JSAutoCompartment ac(mContext, aScopeObject);
 
     ++mExecuteDepth;
 
     JS::CompileOptions options(mContext);
     options.setFileAndLine(aURL, aLineNo)
            .setVersion(JSVersion(aVersion))
            .setPrincipals(nsJSPrincipals::get(principal));
-    JS::RootedObject rootedScope(mContext, aScopeObject);
+    js::RootedObject rootedScope(mContext, aScopeObject);
     ok = JS::Evaluate(mContext, rootedScope, options, PromiseFlatString(aScript).get(),
                       aScript.Length(), &val);
 
     --mExecuteDepth;
 
     if (!ok) {
       // Tell XPConnect about any pending exceptions. This is needed
       // to avoid dropping JS exceptions in case we got here through
@@ -1490,17 +1490,17 @@ nsJSContext::EvaluateString(const nsAStr
 
   // SecurityManager said "ok", but don't compile if aVersion is unknown.
   // Since the caller is responsible for parsing the version strings, we just
   // check it isn't JSVERSION_UNKNOWN.
   if (ok && JSVersion(aVersion) != JSVERSION_UNKNOWN) {
     XPCAutoRequest ar(mContext);
     JSAutoCompartment ac(mContext, aScopeObject);
 
-    JS::RootedObject rootedScope(mContext, aScopeObject);
+    js::RootedObject rootedScope(mContext, aScopeObject);
     JS::CompileOptions options(mContext);
     options.setFileAndLine(aURL, aLineNo)
            .setPrincipals(nsJSPrincipals::get(principal))
            .setOriginPrincipals(nsJSPrincipals::get(aOriginPrincipal))
            .setVersion(JSVersion(aVersion));
     ok = JS::Evaluate(mContext, rootedScope, options,
                       PromiseFlatString(aScript).get(),
                       aScript.Length(), vp);
@@ -1580,17 +1580,17 @@ nsJSContext::CompileScript(const PRUnich
   JS::CompileOptions options(mContext);
   JS::CompileOptions::SourcePolicy sp = aSaveSource ?
     JS::CompileOptions::SAVE_SOURCE :
     JS::CompileOptions::LAZY_SOURCE;
   options.setPrincipals(nsJSPrincipals::get(aPrincipal))
          .setFileAndLine(aURL, aLineNo)
          .setVersion(JSVersion(aVersion))
          .setSourcePolicy(sp);
-  JS::RootedObject rootedScope(mContext, scopeObject);
+  js::RootedObject rootedScope(mContext, scopeObject);
   JSScript* script = JS::Compile(mContext,
                                  rootedScope,
                                  options,
                                  static_cast<const jschar*>(aText),
                                  aTextLength);
   if (!script) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -1758,17 +1758,17 @@ nsJSContext::CompileEventHandler(nsIAtom
 
   // Event handlers are always shared, and must be bound before use.
   // Therefore we don't bother compiling with principals.
   XPCAutoRequest ar(mContext);
 
   JS::CompileOptions options(mContext);
   options.setVersion(JSVersion(aVersion))
          .setFileAndLine(aURL, aLineNo);
-  JS::RootedObject empty(mContext, NULL);
+  js::RootedObject empty(mContext, NULL);
   JSFunction* fun = JS::CompileFunction(mContext, empty, options, nsAtomCString(aName).get(),
                                         aArgCount, aArgNames,
                                         PromiseFlatString(aBody).get(), aBody.Length());
 
   if (!fun) {
     ReportPendingException();
     return NS_ERROR_ILLEGAL_VALUE;
   }
@@ -1811,17 +1811,17 @@ nsJSContext::CompileFunction(JSObject* a
     nsCOMPtr<nsIScriptObjectPrincipal> globalData = do_QueryInterface(global);
     if (globalData) {
       principal = globalData->GetPrincipal();
       if (!principal)
         return NS_ERROR_FAILURE;
     }
   }
 
-  JS::RootedObject target(mContext, aShared ? NULL : aTarget);
+  js::RootedObject target(mContext, aShared ? NULL : aTarget);
 
   XPCAutoRequest ar(mContext);
 
   JS::CompileOptions options(mContext);
   options.setPrincipals(nsJSPrincipals::get(principal))
          .setVersion(JSVersion(aVersion))
          .setFileAndLine(aURL, aLineNo);
   JSFunction* fun = JS::CompileFunction(mContext, target,
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -586,17 +586,20 @@ XrayEnumerateProperties(JS::AutoIdVector
 
   return true;
 }
 
 bool
 GetPropertyOnPrototype(JSContext* cx, JSObject* proxy, jsid id, bool* found,
                        JS::Value* vp)
 {
-  JSObject* proto = js::GetObjectProto(proxy);
+  JSObject* proto;
+  if (!js::GetObjectProto(cx, proxy, &proto)) {
+    return false;
+  }
   if (!proto) {
     *found = false;
     return true;
   }
 
   JSBool hasProp;
   if (!JS_HasPropertyById(cx, proto, id, &hasProp)) {
     return false;
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -754,23 +754,26 @@ class CGClassHasInstanceHook(CGAbstractS
   if (!protov.isObject()) {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE,
                          "%s");
     return false;
   }
   JSObject *objProto = &protov.toObject();
 
   JSObject* instance = &vp.toObject();
-  JSObject* proto = JS_GetPrototype(instance);
+  JSObject* proto;
+  if (!JS_GetPrototype(cx, instance, &proto))
+    return false;
   while (proto) {
     if (proto == objProto) {
       *bp = true;
       return true;
     }
-    proto = JS_GetPrototype(proto);
+    if (!JS_GetPrototype(cx, proto, &proto))
+      return false;
   }
 
   nsISupports* native =
     nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, instance);
   nsCOMPtr<%s> qiResult = do_QueryInterface(native);
   *bp = !!qiResult;
   return true;
 """ % (self.descriptor.name, self.descriptor.hasInstanceInterface)
@@ -3445,17 +3448,17 @@ class CGAbstractBindingMethod(CGAbstract
             str(CastableObjectUnwrapper(
                         FakeCastableDescriptor(self.descriptor),
                         "obj", "self", self.unwrapFailureCode))))
         return CGList([ self.getThis(), unwrapThis,
                         self.generate_code() ], "\n").define()
 
     def getThis(self):
         return CGIndenter(
-            CGGeneric("JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n"
+            CGGeneric("js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n"
                       "if (!obj) {\n"
                       "  return false;\n"
                       "}\n"
                       "\n"
                       "%s* self;" % self.descriptor.nativeType))
 
     def generate_code(self):
         assert(False) # Override me
@@ -5012,17 +5015,20 @@ if (expando) {
 """
 
         return """MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
              "Should not have a XrayWrapper here");
 
 """ + get + """
 // No need to worry about name getters here, so just check the proto.
 
-JSObject *proto = js::GetObjectProto(proxy);
+JSObject *proto;
+if (!js::GetObjectProto(cx, proxy, &proto)) {
+  return false;
+}
 if (proto) {
   JSBool isPresent;
   if (!JS_GetElementIfPresent(cx, proto, index, proxy, vp, &isPresent)) {
     return false;
   }
   *present = isPresent;
   return true;
 }
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -92,17 +92,20 @@ DOMProxyHandler::getPropertyDescriptor(J
 {
   if (!getOwnPropertyDescriptor(cx, proxy, id, set, desc)) {
     return false;
   }
   if (desc->obj) {
     return true;
   }
 
-  JSObject* proto = js::GetObjectProto(proxy);
+  JSObject* proto;
+  if (!js::GetObjectProto(cx, proxy, &proto)) {
+    return false;
+  }
   if (!proto) {
     desc->obj = NULL;
     return true;
   }
 
   return JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, desc);
 }
 
@@ -146,17 +149,20 @@ DOMProxyHandler::delete_(JSContext* cx, 
 
   *bp = !!b;
   return true;
 }
 
 bool
 DOMProxyHandler::enumerate(JSContext* cx, JSObject* proxy, AutoIdVector& props)
 {
-  JSObject* proto = JS_GetPrototype(proxy);
+  JSObject* proto;
+  if (!JS_GetPrototype(cx, proxy, &proto)) {
+    return false;
+  }
   return getOwnPropertyNames(cx, proxy, props) &&
          (!proto || js::GetPropertyNames(cx, proto, 0, &props));
 }
 
 bool
 DOMProxyHandler::fix(JSContext* cx, JSObject* proxy, Value* vp)
 {
   vp->setUndefined();
@@ -172,17 +178,20 @@ DOMProxyHandler::has(JSContext* cx, JSOb
 
   if (*bp) {
     // We have the property ourselves; no need to worry about our prototype
     // chain.
     return true;
   }
 
   // OK, now we have to look at the proto
-  JSObject *proto = js::GetObjectProto(proxy);
+  JSObject *proto;
+  if (!js::GetObjectProto(cx, proxy, &proto)) {
+    return false;
+  }
   if (!proto) {
     return true;
   }
   JSBool protoHasProp;
   bool ok = JS_HasPropertyById(cx, proto, id, &protoHasProp);
   if (ok) {
     *bp = protoHasProp;
   }
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -0,0 +1,80 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* 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 "BluetoothHfpManager.h"
+
+#include "BluetoothReplyRunnable.h"
+#include "BluetoothService.h"
+#include "BluetoothServiceUuid.h"
+
+USING_BLUETOOTH_NAMESPACE
+using namespace mozilla::ipc;
+
+static nsRefPtr<BluetoothHfpManager> sInstance = nullptr;
+
+BluetoothHfpManager::BluetoothHfpManager()
+{
+}
+
+BluetoothHfpManager::~BluetoothHfpManager()
+{
+}
+
+//static
+BluetoothHfpManager*
+BluetoothHfpManager::Get()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (sInstance == nullptr) {
+    sInstance = new BluetoothHfpManager();
+  }
+
+  return sInstance;
+}
+
+// Virtual function of class SocketConsumer
+void
+BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+bool
+BluetoothHfpManager::Connect(const nsAString& aDeviceObjectPath,
+                             BluetoothReplyRunnable* aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return false;
+  }
+
+  nsString serviceUuidStr =
+    NS_ConvertUTF8toUTF16(mozilla::dom::bluetooth::BluetoothServiceUuidStr::Handsfree);
+
+  nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
+
+  nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
+                                        serviceUuidStr,
+                                        BluetoothSocketType::RFCOMM,
+                                        true,
+                                        false,
+                                        this,
+                                        runnable);
+
+  runnable.forget();
+  return NS_FAILED(rv) ? false : true;
+}
+
+void
+BluetoothHfpManager::Disconnect()
+{
+  CloseSocket();
+}
+
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -0,0 +1,35 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* 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_dom_bluetooth_bluetoothhfpmanager_h__
+#define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
+
+#include "BluetoothCommon.h"
+#include "mozilla/ipc/UnixSocket.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothReplyRunnable;
+
+class BluetoothHfpManager : public mozilla::ipc::UnixSocketConsumer
+{
+public:
+  ~BluetoothHfpManager();
+
+  static BluetoothHfpManager* Get();
+  void ReceiveSocketData(mozilla::ipc::UnixSocketRawData* aMessage);
+
+  bool Connect(const nsAString& aDeviceObjectPath,
+               BluetoothReplyRunnable* aRunnable);
+  void Disconnect();
+
+private:
+  BluetoothHfpManager();
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -47,16 +47,17 @@ CPPSRCS += \
   BluetoothPropertyEvent.cpp \
   BluetoothReplyRunnable.cpp \
   BluetoothPropertyContainer.cpp \
   BluetoothUtils.cpp \
   BluetoothChild.cpp \
   BluetoothParent.cpp \
   BluetoothServiceChildProcess.cpp \
   BluetoothUnixSocketConnector.cpp \
+  BluetoothHfpManager.cpp \
   $(NULL)
 
 XPIDLSRCS = \
   nsIDOMNavigatorBluetooth.idl \
   nsIDOMBluetoothManager.idl \
   nsIDOMBluetoothAdapter.idl \
   nsIDOMBluetoothDevice.idl \
   nsIDOMBluetoothDeviceEvent.idl \
--- a/dom/fm/DOMFMRadioChild.js
+++ b/dom/fm/DOMFMRadioChild.js
@@ -41,23 +41,20 @@ DOMFMRadioChild.prototype = {
                flags: Ci.nsIClassInfo.DOM_OBJECT
              }),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMFMRadio,
                                          Ci.nsIDOMGlobalPropertyInitializer]),
 
   // nsIDOMGlobalPropertyInitializer implementation
   init: function(aWindow) {
-    let principal = aWindow.document.nodePrincipal;
     let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
                    .getService(Ci.nsIScriptSecurityManager);
 
-    let perm = (principal == secMan.getSystemPrincipal()) ?
-                 Ci.nsIPermissionManager.ALLOW_ACTION :
-                 Services.perms.testExactPermission(principal.URI, "fmradio");
+    let perm = Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "fmradio");
     this._hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
 
     if (!this._hasPrivileges) {
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     }
 
     const messages = ["DOMFMRadio:enable:Return:OK",
                       "DOMFMRadio:enable:Return:NO",
--- a/dom/indexedDB/KeyPath.cpp
+++ b/dom/indexedDB/KeyPath.cpp
@@ -343,17 +343,17 @@ KeyPath::ExtractKeyAsJSVal(JSContext* aC
   NS_ASSERTION(IsValid(), "This doesn't make sense!");
 
   if (IsString()) {
     return GetJSValFromKeyPathString(aCx, aValue, mStrings[0], aOutVal,
                                      DoNotCreateProperties, nullptr, nullptr);
   }
  
   const uint32_t len = mStrings.Length();
-  JS::RootedObject arrayObj(aCx, JS_NewArrayObject(aCx, len, nullptr));
+  js::RootedObject arrayObj(aCx, JS_NewArrayObject(aCx, len, nullptr));
   if (!arrayObj) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Value value;
   for (uint32_t i = 0; i < len; ++i) {
     nsresult rv = GetJSValFromKeyPathString(aCx, aValue, mStrings[i], &value,
                                             DoNotCreateProperties, nullptr,
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -45,22 +45,34 @@ function SystemMessageInternal() {
     ppmm.addMessageListener(aMsg, this);
   }).bind(this));
 }
 
 SystemMessageInternal.prototype = {
   sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
     debug("Broadcasting " + aType + " " + JSON.stringify(aMessage));
     if (this._listeners[aManifestURI.spec]) {
-      this._listeners[aManifestURI.spec].forEach(function sendMsg(aListener) {
-        aListener.sendAsyncMessage("SystemMessageManager:Message",
-                                   { type: aType,
-                                     msg: aMessage,
-                                     manifest: aManifestURI.spec })
-      });
+      let i;
+      let listener;
+      for (i = this._listeners[aManifestURI.spec].length - 1; i >= 0; i -= 1) {
+        listener = this._listeners[aManifestURI.spec][i];
+        try {
+          listener.sendAsyncMessage("SystemMessageManager:Message",
+                                     { type: aType,
+                                       msg: aMessage,
+                                       manifest: aManifestURI.spec })
+        } catch (e) {
+          // Remove once 777508 lands.
+          let index;
+          if ((index = this._listeners[aManifestURI.spec].indexOf(listener)) != -1) {
+            this._listeners[aManifestURI.spec].splice(index, 1);
+            dump("Remove dead MessageManager!\n");
+          }
+        }
+      };
     }
 
     this._pages.forEach(function sendMess_openPage(aPage) {
       if (aPage.type != aType ||
           aPage.manifest != aManifestURI.spec ||
           aPage.uri != aPageURI.spec) {
         return;
       }
@@ -70,22 +82,33 @@ SystemMessageInternal.prototype = {
   },
 
   broadcastMessage: function broadcastMessage(aType, aMessage) {
     debug("Broadcasting " + aType + " " + JSON.stringify(aMessage));
     // Find pages that registered an handler for this type.
     this._pages.forEach(function(aPage) {
       if (aPage.type == aType) {
         if (this._listeners[aPage.manifest]) {
-          this._listeners[aPage.manifest].forEach(function sendMsg(aListener) {
-            aListener.sendAsyncMessage("SystemMessageManager:Message",
-                                       { type: aType,
-                                         msg: aMessage,
-                                         manifest: aPage.manifest})
-          });
+          let i;
+          for (i = this._listeners[aPage.manifest].length - 1; i >= 0; i -= 1) {
+            let listener = this._listeners[aPage.manifest][i];
+            try {
+              listener.sendAsyncMessage("SystemMessageManager:Message",
+                                         { type: aType,
+                                           msg: aMessage,
+                                           manifest: aPage.manifest})
+            } catch (e) {
+              // Remove once 777508 lands.
+              let index;
+              if ((index = this._listeners[aPage.manifest].indexOf(listener)) != -1) {
+                this._listeners[aPage.manifest].splice(index, 1);
+                dump("Remove dead MessageManager!\n");
+              }
+            }
+          };
         }
         this._processPage(aPage, aMessage);
       }
     }.bind(this))
   },
 
   registerPage: function registerPage(aType, aPageURI, aManifestURI) {
     if (!aPageURI || !aManifestURI) {
--- a/dom/plugins/base/android/ANPSystem.cpp
+++ b/dom/plugins/base/android/ANPSystem.cpp
@@ -53,16 +53,19 @@ jclass anp_system_loadJavaClass(NPP inst
   mozilla::PluginPRLibrary* lib = static_cast<mozilla::PluginPRLibrary*>(pinst->GetPlugin()->GetLibrary());
 
   nsCString libName;
   lib->GetLibraryPath(libName);
 
   jstring jclassName = env->NewStringUTF(className);
   jstring jlibName = env->NewStringUTF(libName.get());
   jobject obj = env->CallStaticObjectMethod(cls, method, jclassName, jlibName);
+  env->DeleteLocalRef(jlibName);
+  env->DeleteLocalRef(jclassName);
+  env->DeleteLocalRef(cls);
   return reinterpret_cast<jclass>(obj);
 }
 
 void anp_system_setPowerState(NPP instance, ANPPowerState powerState)
 {
   nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
 
   pinst->SetWakeLock(powerState == kScreenOn_ANPPowerState);
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -1137,17 +1137,19 @@ GetNPObjectWrapper(JSContext *cx, JSObje
 {
   while (obj && (obj = js::UnwrapObjectChecked(cx, obj))) {
     if (JS_GetClass(obj) == &sNPObjectJSWrapperClass) {
       if (wrapResult && !JS_WrapObject(cx, &obj)) {
         return NULL;
       }
       return obj;
     }
-    obj = ::JS_GetPrototype(obj);
+    if (!::JS_GetPrototype(cx, obj, &obj)) {
+      return NULL;
+    }
   }
   return NULL;
 }
 
 static NPObject *
 GetNPObject(JSContext *cx, JSObject *obj)
 {
   obj = GetNPObjectWrapper(cx, obj, /* wrapResult = */ false);
@@ -2049,22 +2051,30 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp)
     ac.construct(cx, obj);
   }
 
   // Loop over the DOM element's JS object prototype chain and remove
   // all JS objects of the class sNPObjectJSWrapperClass (there should
   // be only one, but remove all instances found in case the page put
   // more than one of the plugin's scriptable objects on the prototype
   // chain).
-  while (obj && (proto = ::JS_GetPrototype(obj))) {
+  while (obj) {
+    if (!::JS_GetPrototype(cx, obj, &proto)) {
+      return;
+    }
+    if (!proto) {
+      break;
+    }
     // Unwrap while checking the jsclass - if the prototype is a wrapper for
     // an NP object, that counts too.
     if (JS_GetClass(js::UnwrapObject(proto)) == &sNPObjectJSWrapperClass) {
       // We found an NPObject on the proto chain, get its prototype...
-      proto = ::JS_GetPrototype(proto);
+      if (!::JS_GetPrototype(cx, proto, &proto)) {
+        return;
+      }
 
       // ... and pull it out of the chain.
       ::JS_SetPrototype(cx, obj, proto);
     }
 
     obj = proto;
   }
 }
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2218,16 +2218,17 @@ NPError NP_CALLBACK
       JNIEnv* env = GetJNIForThread();
       if (!env)
         return NPERR_GENERIC_ERROR;
 
       jclass cls     = env->FindClass("org/mozilla/gecko/GeckoApp");
       jfieldID field = env->GetStaticFieldID(cls, "mAppContext",
                                              "Lorg/mozilla/gecko/GeckoApp;");
       jobject ret = env->GetStaticObjectField(cls, field);
+      env->DeleteLocalRef(cls);
       int32_t* i  = reinterpret_cast<int32_t*>(result);
       *i = reinterpret_cast<int32_t>(ret);
       return NPERR_NO_ERROR;
     }
 
     case kAudioTrackInterfaceV1_ANPGetValue: {
       LOG("get audio interface v1");
       ANPAudioTrackInterfaceV1 *i = (ANPAudioTrackInterfaceV1 *) result;
--- a/dom/sms/tests/marionette/manifest.ini
+++ b/dom/sms/tests/marionette/manifest.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
 [test_between_emulators.py]
 [test_incoming.js]
 [test_outgoing.js]
+[test_message_classes.js]
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_message_classes.js
@@ -0,0 +1,235 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+
+const PDU_SMSC = "00"; // No SMSC Address
+const PDU_FIRST_OCTET = "00"; // RP:no, UDHI:no, SRI:no, MMS:no, MTI:SMS-DELIVER
+const PDU_SENDER = "0191F1"; // +1
+const PDU_PID_NORMAL = "00";
+const PDU_PID_ANSI_136_R_DATA = "7C";
+const PDU_PID_USIM_DATA_DOWNLOAD = "7F";
+const PDU_TIMESTAMP = "00101000000000"; // 2000/01/01
+const PDU_UDL = "01";
+const PDU_UD = "41";
+
+SpecialPowers.addPermission("sms", true, document);
+
+let sms = window.navigator.mozSms;
+ok(sms instanceof MozSmsManager);
+
+let pendingEmulatorCmdCount = 0;
+function sendSmsPduToEmulator(pdu) {
+  ++pendingEmulatorCmdCount;
+
+  let cmd = "sms pdu " + pdu;
+  runEmulatorCmd(cmd, function (result) {
+    --pendingEmulatorCmdCount;
+
+    is(result[0], "OK", "Emulator response");
+  });
+}
+
+const TIMESTAMP = Date.UTC(2000, 0, 1);
+function checkMessage(message, id) {
+  ok(message instanceof MozSmsMessage,
+     "message is instanceof " + message.constructor);
+  if (id == null) {
+    ok(message.id > 0, "message.id");
+  } else {
+    is(message.id, -1, "message.id");
+  }
+  is(message.delivery, "received", "message.delivery");
+  is(message.sender, "+1", "message.sender");
+  is(message.body, "A", "message.body");
+  ok(message.timestamp instanceof Date,
+     "message.timestamp is instanceof " + message.timestamp.constructor);
+  is(message.timestamp.getTime(), TIMESTAMP, "message.timestamp");
+  is(message.read, false, "message.read");
+}
+
+function test_message_class_0() {
+  let allDCSs = [
+    "10", // General Group: 00xx
+    "50", // Automatica Deletion Group: 01xx
+    "F0"  // (no name) Group: 1111
+  ];
+
+  function do_test(dcsIndex) {
+    sms.addEventListener("received", function onReceived(event) {
+      sms.removeEventListener("received", onReceived);
+
+      let message = event.message;
+      checkMessage(message, -1);
+
+      // Make sure the message is not stored.
+      let request = sms.getMessages(null, false);
+      request.onsuccess = function onsuccess() {
+        let cursor = request.result;
+        if (cursor.message) {
+          // Here we check whether there is any message of the same sender.
+          isnot(cursor.message.sender, message.sender, "cursor.message.sender");
+
+          cursor.continue();
+          return;
+        }
+
+        // All messages checked. Done.
+        ++dcsIndex;
+        if (dcsIndex >= allDCSs.length) {
+          window.setTimeout(test_message_class_1, 0);
+        } else {
+          window.setTimeout(do_test.bind(null, dcsIndex), 0);
+        }
+      };
+      request.onerror = function onerror() {
+        ok(false, "Can't fetch messages from SMS database");
+      };
+    });
+
+    let dcs = allDCSs[dcsIndex];
+    log("  Testing DCS " + dcs);
+    let pdu = PDU_SMSC + PDU_FIRST_OCTET + PDU_SENDER + PDU_PID_NORMAL +
+              dcs + PDU_TIMESTAMP + PDU_UDL + PDU_UD;
+
+    sendSmsPduToEmulator(pdu);
+  }
+
+  log("Checking Message Class 0");
+  do_test(0);
+}
+
+function doTestMessageClassGeneric(allDCSs, next) {
+  function do_test(dcsIndex) {
+    sms.addEventListener("received", function onReceived(event) {
+      sms.removeEventListener("received", onReceived);
+
+      // Make sure we can correctly receive the message
+      checkMessage(event.message);
+
+      ++dcsIndex;
+      if (dcsIndex >= allDCSs.length) {
+        window.setTimeout(next, 0);
+      } else {
+        window.setTimeout(do_test.bind(null, dcsIndex), 0);
+      }
+    });
+
+    let dcs = allDCSs[dcsIndex];
+    log("  Testing DCS " + dcs);
+    let pdu = PDU_SMSC + PDU_FIRST_OCTET + PDU_SENDER + PDU_PID_NORMAL +
+              dcs + PDU_TIMESTAMP + PDU_UDL + PDU_UD;
+
+    sendSmsPduToEmulator(pdu);
+  }
+
+  do_test(0);
+}
+
+function test_message_class_1() {
+  let allDCSs = [
+    "11", // General Group: 00xx
+    "51", // Automatica Deletion Group: 01xx
+    "F1"  // (no name) Group: 1111
+  ];
+
+  log("Checking Message Class 1");
+  doTestMessageClassGeneric(allDCSs, test_message_class_2);
+}
+
+function test_message_class_2() {
+  let allDCSs = [
+    "12", // General Group: 00xx
+    "52", // Automatica Deletion Group: 01xx
+    "F2"  // (no name) Group: 1111
+  ];
+
+  let allPIDs = [
+    PDU_PID_NORMAL,
+    PDU_PID_ANSI_136_R_DATA,
+    PDU_PID_USIM_DATA_DOWNLOAD
+  ];
+
+  function do_test_dcs(dcsIndex) {
+    function do_test_pid(pidIndex) {
+      function onReceived(event) {
+        if (pidIndex == 0) {
+          // Make sure we can correctly receive the message
+          checkMessage(event.message);
+
+          next();
+          return;
+        }
+
+        // TODO: Bug 792798 - B2G SMS: develop test cases for Message Class 2
+        // Since we have "data download via SMS Point-to-Point" service enabled
+        // but no working implementation in emulator SIM, all class 2 messages
+        // bug normal ones should goto `dataDownloadViaSMSPP()` and we should
+        // not receive the message in content page.
+        ok(false, "SMS-PP messages shouldn't be sent to content");
+      }
+
+      function next() {
+        sms.removeEventListener("received", onReceived);
+
+        ++pidIndex;
+        if (pidIndex >= allPIDs.length) {
+          ++dcsIndex;
+          if (dcsIndex >= allDCSs.length) {
+            window.setTimeout(test_message_class_3, 0);
+          } else {
+            window.setTimeout(do_test_dcs.bind(null, dcsIndex), 0);
+          }
+        } else {
+          window.setTimeout(do_test_pid.bind(null, pidIndex), 0);
+        }
+      }
+
+      sms.addEventListener("received", onReceived);
+
+      if (pidIndex != 0) {
+        // Wait for three seconds to ensure we don't receive the message.
+        window.setTimeout(next, 3000);
+      }
+
+      let pid = allPIDs[pidIndex];
+      log("    Testing PID " + pid);
+
+      let pdu = PDU_SMSC + PDU_FIRST_OCTET + PDU_SENDER + pid + dcs +
+                PDU_TIMESTAMP + PDU_UDL + PDU_UD;
+
+      sendSmsPduToEmulator(pdu);
+    }
+
+    let dcs = allDCSs[dcsIndex];
+    log("  Testing DCS " + dcs);
+
+    do_test_pid(0);
+  }
+
+  log("Checking Message Class 2");
+  do_test_dcs(0);
+}
+
+function test_message_class_3() {
+  let allDCSs = [
+    "13", // General Group: 00xx
+    "53", // Automatica Deletion Group: 01xx
+    "F3"  // (no name) Group: 1111
+  ];
+
+  log("Checking Message Class 3");
+  doTestMessageClassGeneric(allDCSs, cleanUp);
+}
+
+function cleanUp() {
+  if (pendingEmulatorCmdCount) {
+    window.setTimeout(cleanUp, 100);
+    return;
+  }
+
+  SpecialPowers.removePermission("sms", document);
+  finish();
+}
+
+test_message_class_0();
--- a/dom/src/json/nsJSON.cpp
+++ b/dom/src/json/nsJSON.cpp
@@ -495,17 +495,17 @@ nsJSON::LegacyDecodeFromStream(nsIInputS
   return DecodeInternal(cx, aStream, aContentLength, true, aRetval, LEGACY);
 }
 
 NS_IMETHODIMP
 nsJSON::LegacyDecodeToJSVal(const nsAString &str, JSContext *cx, jsval *result)
 {
   JSAutoRequest ar(cx);
 
-  JS::RootedValue reviver(cx, JS::NullValue()), value(cx);
+  js::RootedValue reviver(cx, JS::NullValue()), value(cx);
 
   if (!js::ParseJSONWithReviver(cx, static_cast<const jschar*>(PromiseFlatString(str).get()),
                                 str.Length(), reviver,
                                 &value, LEGACY)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   *result = value;
@@ -565,17 +565,17 @@ nsJSONListener::OnStopRequest(nsIRequest
 
   // This can happen with short UTF-8 messages (<4 bytes)
   if (!mSniffBuffer.IsEmpty()) {
     // Just consume mSniffBuffer
     rv = ProcessBytes(nullptr, 0);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  JS::RootedValue reviver(mCx, JS::NullValue()), value(mCx);
+  js::RootedValue reviver(mCx, JS::NullValue()), value(mCx);
 
   const jschar* chars = reinterpret_cast<const jschar*>(mBufferedChars.Elements());
   JSBool ok = js::ParseJSONWithReviver(mCx, chars,
                                        (uint32) mBufferedChars.Length(),
                                        reviver, &value,
                                        mDecodingMode);
 
   *mRootVal = value;
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -141,16 +141,18 @@ function NetworkManager() {
   settingsLock.get(SETTINGS_WIFI_PREFIX, this);
   settingsLock.get(SETTINGS_WIFI_DHCPSERVER_STARTIP, this);
   settingsLock.get(SETTINGS_WIFI_DHCPSERVER_ENDIP, this);
   // Read usb tethering data from settings DB.
   settingsLock.get(SETTINGS_USB_IP, this);
   settingsLock.get(SETTINGS_USB_PREFIX, this);
   settingsLock.get(SETTINGS_USB_DHCPSERVER_STARTIP, this);
   settingsLock.get(SETTINGS_USB_DHCPSERVER_ENDIP, this);
+
+  this.setAndConfigureActive();
 }
 NetworkManager.prototype = {
   classID:   NETWORKMANAGER_CID,
   classInfo: XPCOMUtils.generateCI({classID: NETWORKMANAGER_CID,
                                     contractID: NETWORKMANAGER_CONTRACTID,
                                     classDescription: "Network Manager",
                                     interfaces: [Ci.nsINetworkManager]}),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkManager,
@@ -167,29 +169,31 @@ NetworkManager.prototype = {
 
   observe: function observe(subject, topic, data) {
     switch (topic) {
       case TOPIC_INTERFACE_STATE_CHANGED:
         let network = subject.QueryInterface(Ci.nsINetworkInterface);
         debug("Network " + network.name + " changed state to " + network.state);
         switch (network.state) {
           case Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED:
-            // Add host route on secondary APN
-            if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
+            // Add host route for data calls
+            if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
+                network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
               this.addHostRoute(network);
             }
             // Remove pre-created default route and let setAndConfigureActive()
             // to set default route only on preferred network
             this.removeDefaultRoute(network.name);
             this.setAndConfigureActive();
             break;
           case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
-            // Remove host route on secondary APN
-            if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
+            // Remove host route for data calls
+            if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
+                network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
               this.removeHostRoute(network);
             }
             this.setAndConfigureActive();
             break;
         }
         break;
       case TOPIC_MOZSETTINGS_CHANGED:
@@ -211,18 +215,19 @@ NetworkManager.prototype = {
       throw Components.Exception("Argument must be nsINetworkInterface.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
     if (network.name in this.networkInterfaces) {
       throw Components.Exception("Network with that name already registered!",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
     this.networkInterfaces[network.name] = network;
-    // Add host route on secondary APN
-    if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
+    // Add host route for data calls
+    if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
+        network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
         network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
       this.addHostRoute(network);
     }
     // Remove pre-created default route and let setAndConfigureActive()
     // to set default route only on preferred network
     this.removeDefaultRoute(network.name);
     this.setAndConfigureActive();
     Services.obs.notifyObservers(network, TOPIC_INTERFACE_REGISTERED, null);
@@ -234,18 +239,19 @@ NetworkManager.prototype = {
       throw Components.Exception("Argument must be nsINetworkInterface.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
     if (!(network.name in this.networkInterfaces)) {
       throw Components.Exception("No network with that name registered.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
     delete this.networkInterfaces[network.name];
-    // Remove host route on secondary APN
-    if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
+    // Remove host route for data calls
+    if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
+        network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
         network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
       this.removeHostRoute(network);
     }
     this.setAndConfigureActive();
     Services.obs.notifyObservers(network, TOPIC_INTERFACE_UNREGISTERED, null);
     debug("Network '" + network.name + "' unregistered.");
   },
 
@@ -253,17 +259,18 @@ NetworkManager.prototype = {
 
   _preferredNetworkType: DEFAULT_PREFERRED_NETWORK_TYPE,
   get preferredNetworkType() {
     return this._preferredNetworkType;
   },
   set preferredNetworkType(val) {
     if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
          Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
-         Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS].indexOf(val) == -1) {
+         Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
+         Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL].indexOf(val) == -1) {
       throw "Invalid network type";
     }
     this._preferredNetworkType = val;
   },
 
   active: null,
   _overriddenActive: null,
 
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -23,16 +23,18 @@ Cu.import("resource://gre/modules/Servic
 var RIL = {};
 Cu.import("resource://gre/modules/ril_consts.js", RIL);
 
 // set to true in ril_consts.js to see debug messages
 const DEBUG = RIL.DEBUG_RIL;
 
 const RADIOINTERFACELAYER_CID =
   Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
+const RILNETWORKINTERFACE_CID =
+  Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
 
 const nsIAudioManager = Ci.nsIAudioManager;
 const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
 
 const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
 const kSmsReceivedObserverTopic          = "sms-received";
 const kSmsSentObserverTopic              = "sms-sent";
 const kSmsDeliveredObserverTopic         = "sms-delivered";
@@ -88,16 +90,20 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
                                    "@mozilla.org/system-message-internal;1",
                                    "nsISystemMessagesInternal");
 
+XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
+                                   "@mozilla.org/network/manager;1",
+                                   "nsINetworkManager");
+
 XPCOMUtils.defineLazyGetter(this, "WAP", function () {
   let WAP = {};
   Cu.import("resource://gre/modules/WapPushManager.js", WAP);
   return WAP;
 });
 
 function convertRILCallState(state) {
   switch (state) {
@@ -145,16 +151,20 @@ XPCOMUtils.defineLazyGetter(this, "gAudi
     //TODO on the phone this should not fall back as silently.
     debug("Using fake audio manager.");
     return FakeAudioManager;
   }
 });
 
 
 function RadioInterfaceLayer() {
+  this.dataNetworkInterface = new RILNetworkInterface(this, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
+  this.mmsNetworkInterface = new RILNetworkInterface(this, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS);
+  this.suplNetworkInterface = new RILNetworkInterface(this, Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL);
+
   debug("Starting RIL Worker");
   this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
   this.worker.onerror = this.onerror.bind(this);
   this.worker.onmessage = this.onmessage.bind(this);
 
   this.rilContext = {
     radioState:     RIL.GECKO_RADIOSTATE_UNAVAILABLE,
     cardState:      RIL.GECKO_CARDSTATE_UNAVAILABLE,
@@ -184,32 +194,47 @@ function RadioInterfaceLayer() {
 
   this.callWaitingStatus = null;
 
   // Read the 'ril.radio.disabled' setting in order to start with a known
   // value at boot time.
   let lock = gSettingsService.createLock();
   lock.get("ril.radio.disabled", this);
 
-  // Read the APN data form the setting DB.
+  // Read the APN data from the settings DB.
   lock.get("ril.data.apn", this);
   lock.get("ril.data.user", this);
   lock.get("ril.data.passwd", this);
   lock.get("ril.data.httpProxyHost", this);
   lock.get("ril.data.httpProxyPort", this);
   lock.get("ril.data.roaming_enabled", this);
   lock.get("ril.data.enabled", this);
   this._dataCallSettingsToRead = ["ril.data.enabled",
                                   "ril.data.roaming_enabled",
                                   "ril.data.apn",
                                   "ril.data.user",
                                   "ril.data.passwd",
                                   "ril.data.httpProxyHost",
                                   "ril.data.httpProxyPort"];
 
+  // Read secondary APNs from the settings DB.
+  lock.get("ril.mms.apn", this);
+  lock.get("ril.mms.user", this);
+  lock.get("ril.mms.passwd", this);
+  lock.get("ril.mms.httpProxyHost", this);
+  lock.get("ril.mms.httpProxyPort", this);
+  lock.get("ril.mms.mmsc", this);
+  lock.get("ril.mms.mmsproxy", this);
+  lock.get("ril.mms.mmsport", this);
+  lock.get("ril.supl.apn", this);
+  lock.get("ril.supl.user", this);
+  lock.get("ril.supl.passwd", this);
+  lock.get("ril.supl.httpProxyHost", this);
+  lock.get("ril.supl.httpProxyPort", this);
+
   // Read the desired setting of call waiting from the settings DB.
   lock.get("ril.callwaiting.enabled", this);
 
   this._messageManagerByRequest = {};
 
   for each (let msgname in RIL_IPC_MSG_NAMES) {
     ppmm.addMessageListener(msgname, this);
   }
@@ -614,17 +639,17 @@ RadioInterfaceLayer.prototype = {
   updateDataConnection: function updateDataConnection(newInfo) {
     let dataInfo = this.rilContext.data;
     dataInfo.state = newInfo.state;
     dataInfo.roaming = newInfo.roaming;
     dataInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly;
     dataInfo.type = newInfo.type;
     // For the data connection, the `connected` flag indicates whether
     // there's an active data call.
-    dataInfo.connected = RILNetworkInterface.connected;
+    dataInfo.connected = this.dataNetworkInterface.connected;
 
     // Make sure we also reset the operator and signal strength information
     // if we drop off the network.
     if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
       dataInfo.network = null;
       dataInfo.signalStrength = null;
       dataInfo.relSignalStrength = null;
     }
@@ -641,24 +666,22 @@ RadioInterfaceLayer.prototype = {
     }
     this.updateRILNetworkInterface();
   },
 
   /**
    * Handle data errors
    */
   handleDataCallError: function handleDataCallError(message) {
-    if (message.apn != this.dataCallSettings["apn"]) {
-      return;
+    // Notify data call error only for data APN
+    if (message.apn == this.dataCallSettings["apn"]) {
+      ppmm.broadcastAsyncMessage("RIL:DataError", message);
     }
 
-    // 3G Network revoked the data connection, possible unavailable APN
-    RILNetworkInterface.reset();
-    // Notify datacall error
-    ppmm.broadcastAsyncMessage("RIL:DataError", message);
+    this._deliverDataCallCallback("dataCallError", [message]);
   },
 
   handleSignalStrengthChange: function handleSignalStrengthChange(message) {
     let voiceInfo = this.rilContext.voice;
     // TODO CDMA, EVDO, LTE, etc. (see bug 726098)
     if (voiceInfo.signalStrength != message.gsmDBM ||
         voiceInfo.relSignalStrength != message.gsmRelative) {
       voiceInfo.signalStrength = message.gsmDBM;
@@ -792,22 +815,28 @@ RadioInterfaceLayer.prototype = {
     // true and any of the remaining flags change the setting application
     // should turn this flag to false and then to true in order to reload
     // the new values and reconnect the data call.
     if (this._oldRilDataEnabledState == this.dataCallSettings["enabled"]) {
       debug("No changes for ril.data.enabled flag. Nothing to do.");
       return;
     }
 
-    if (!this.dataCallSettings["enabled"] && RILNetworkInterface.connected) {
-      debug("Data call settings: disconnect data call.");
-      RILNetworkInterface.disconnect();
+    if (this.dataNetworkInterface.state == RIL.GECKO_NETWORK_STATE_CONNECTING ||
+        this.dataNetworkInterface.state == RIL.GECKO_NETWORK_STATE_DISCONNECTING) {
+      debug("Nothing to do during connecting/disconnecting in progress.");
       return;
     }
-    if (!this.dataCallSettings["enabled"] || RILNetworkInterface.connected) {
+
+    if (!this.dataCallSettings["enabled"] && this.dataNetworkInterface.connected) {
+      debug("Data call settings: disconnect data call.");
+      this.dataNetworkInterface.disconnect();
+      return;
+    }
+    if (!this.dataCallSettings["enabled"] || this.dataNetworkInterface.connected) {
       debug("Data call settings: nothing to do.");
       return;
     }
     let dataInfo = this.rilContext.data;
     let isRegistered =
       dataInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
     let haveDataConnection =
       dataInfo.type != RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
@@ -817,17 +846,17 @@ RadioInterfaceLayer.prototype = {
       return;
     }
     if (dataInfo.roaming && !this.dataCallSettings["roaming_enabled"]) {
       debug("We're roaming, but data roaming is disabled.");
       return;
     }
 
     debug("Data call settings: connect data call.");
-    RILNetworkInterface.connect(this.dataCallSettings);
+    this.dataNetworkInterface.connect(this.dataCallSettings);
   },
 
   /**
    * Track the active call and update the audio system as its state changes.
    */
   _activeCall: null,
   updateCallAudioState: function updateCallAudioState() {
     if (!this._activeCall) {
@@ -999,19 +1028,22 @@ RadioInterfaceLayer.prototype = {
     let mwi = message.mwi;
     if (mwi) {
       mwi.returnNumber = message.sender || null;
       mwi.returnMessage = message.fullBody || null;
       ppmm.broadcastAsyncMessage("RIL:VoicemailNotification", mwi);
       return;
     }
 
-    let id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
-                                                     message.fullBody || null,
-                                                     message.timestamp);
+    let id = -1;
+    if (message.messageClass != RIL.PDU_DCS_MSG_CLASS_0) {
+      id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
+                                                   message.fullBody || null,
+                                                   message.timestamp);
+    }
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.fullBody || null,
                                            message.timestamp,
                                            false);
 
@@ -1105,19 +1137,20 @@ RadioInterfaceLayer.prototype = {
   },
 
   /**
    * Handle data call state changes.
    */
   handleDataCallState: function handleDataCallState(datacall) {
     let data = this.rilContext.data;
 
-    if (datacall.ifname) {
+    if (datacall.ifname &&
+        datacall.apn == this.dataCallSettings["apn"]) {
       data.connected = (datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTED);
-      ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data);    
+      ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data);
     }
 
     this._deliverDataCallCallback("dataCallStateChanged",
                                   [datacall]);
   },
 
   /**
    * Handle data call list.
@@ -1184,17 +1217,20 @@ RadioInterfaceLayer.prototype = {
       case kMozSettingsChangedObserverTopic:
         let setting = JSON.parse(data);
         this.handle(setting.key, setting.value);
         break;
       case "xpcom-shutdown":
         for each (let msgname in RIL_IPC_MSG_NAMES) {
           ppmm.removeMessageListener(msgname, this);
         }
-        RILNetworkInterface.shutdown();
+        // Shutdown all RIL network interfaces
+        this.dataNetworkInterface.shutdown();
+        this.mmsNetworkInterface.shutdown();
+        this.suplNetworkInterface.shutdown();
         ppmm = null;
         Services.obs.removeObserver(this, "xpcom-shutdown");
         Services.obs.removeObserver(this, kMozSettingsChangedObserverTopic);
         break;
     }
   },
 
   // Flag to determine whether the UI's system app is ready to receive
@@ -1207,16 +1243,18 @@ RadioInterfaceLayer.prototype = {
 
   // Flag to determine whether we reject a waiting call directly or we
   // notify the UI of a waiting call. It corresponds to the
   // 'ril.callwaiting.enbled' setting from the UI.
   _callWaitingEnabled: null,
 
   // APN data for making data calls.
   dataCallSettings: {},
+  dataCallSettingsMMS: {},
+  dataCallSettingsSUPL: {},
   _dataCallSettingsToRead: [],
   _oldRilDataEnabledState: null,
 
   // nsISettingsServiceCallback
 
   handle: function handle(aName, aResult) {
     switch(aName) {
       case "ril.radio.disabled":
@@ -1237,16 +1275,35 @@ RadioInterfaceLayer.prototype = {
         this.dataCallSettings[key] = aResult;
         debug("'" + aName + "'" + " is now " + this.dataCallSettings[key]);
         let index = this._dataCallSettingsToRead.indexOf(aName);
         if (index != -1) {
           this._dataCallSettingsToRead.splice(index, 1);
         }
         this.updateRILNetworkInterface();
         break;
+      case "ril.mms.apn":
+      case "ril.mms.user":
+      case "ril.mms.passwd":
+      case "ril.mms.httpProxyHost":
+      case "ril.mms.httpProxyPort":
+      case "ril.mms.mmsc":
+      case "ril.mms.mmsproxy":
+      case "ril.mms.mmsport":
+        key = aName.slice(8);
+        this.dataCallSettingsMMS[key] = aResult;
+        break;
+      case "ril.supl.apn":
+      case "ril.supl.user":
+      case "ril.supl.passwd":
+      case "ril.supl.httpProxyHost":
+      case "ril.supl.httpProxyPort":
+        key = aName.slice(9);
+        this.dataCallSettingsSUPL[key] = aResult;
+        break;
       case "ril.callwaiting.enabled":
         this._callWaitingEnabled = aResult;
         this.setCallWaitingEnabled(this._callWaitingEnabled);
         break;
     };
   },
 
   handleError: function handleError(aErrorMessage) {
@@ -1833,16 +1890,84 @@ RadioInterfaceLayer.prototype = {
       try {
         handler.apply(callback, args);
       } catch (e) {
         debug("callback handler for " + name + " threw an exception: " + e);
       }
     }
   },
 
+  /**
+   * Determine whether secondary APN goes through default APN.
+   */
+  usingDefaultAPN: function usingDefaultAPN(apntype) {
+    switch (apntype) {
+      case "mms":
+        return (this.dataCallSettingsMMS["apn"] == this.dataCallSettings["apn"]);
+      case "supl":
+        return (this.dataCallSettingsSUPL["apn"] == this.dataCallSettings["apn"]);
+      return false;
+    }
+  },
+
+  setupDataCallByType: function setupDataCallByType(apntype) {
+    if (apntype != "default" && this.usingDefaultAPN(apntype)) {
+      debug("Secondary APN type " + apntype + " goes through default APN, nothing to do.");
+      return;
+    }
+    switch (apntype) {
+      case "default":
+        this.dataNetworkInterface.connect(this.dataCallSettings);
+        break;
+      case "mms":
+        this.mmsNetworkInterface.connect(this.dataCallSettingsMMS);
+        break;
+      case "supl":
+        this.suplNetworkInterface.connect(this.dataCallSettingsSUPL);
+        break;
+      default:
+        debug("Unsupported APN type " + apntype);
+        break;
+    }
+  },
+
+  deactivateDataCallByType: function deactivateDataCallByType(apntype) {
+    if (apntype != "default" && this.usingDefaultAPN(apntype)) {
+      debug("Secondary APN type " + apntype + " goes through default APN, nothing to do.");
+      return;
+    }
+    switch (apntype) {
+      case "default":
+        this.dataNetworkInterface.disconnect();
+        break;
+      case "mms":
+        this.mmsNetworkInterface.disconnect();
+        break;
+      case "supl":
+        this.suplNetworkInterface.disconnect();
+        break;
+      default:
+        debug("Unsupported APN type " + apntype);
+        break;
+    }
+  },
+
+  getDataCallStateByType: function getDataCallStateByType(apntype) {
+    switch (apntype) {
+      case "default":
+        return this.dataNetworkInterface.state;
+      case "mms":
+        return this.mmsNetworkInterface.state;
+      case "supl":
+        return this.suplNetworkInterface.state;
+      default:
+        return RIL.GECKO_NETWORK_STATE_UNKNOWN;
+    }
+  },
+
   setupDataCall: function setupDataCall(radioTech, apn, user, passwd, chappap, pdptype) {
     this.worker.postMessage({rilMessageType: "setupDataCall",
                              radioTech: radioTech,
                              apn: apn,
                              user: user,
                              passwd: passwd,
                              chappap: chappap,
                              pdptype: pdptype});
@@ -1881,18 +2006,28 @@ RadioInterfaceLayer.prototype = {
     let requestId = Math.floor(Math.random() * 1000);
     this._contactsCallbacks[requestId] = callback;
     this.worker.postMessage({rilMessageType: "getICCContacts",
                              contactType: contactType,
                              requestId: requestId});
   }
 };
 
-let RILNetworkInterface = {
+function RILNetworkInterface(ril, type)
+{
+  this.mRIL = ril;
+  this.type = type;
+}
 
+RILNetworkInterface.prototype = {
+  classID:   RILNETWORKINTERFACE_CID,
+  classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID,
+                                    classDescription: "RILNetworkInterface",
+                                    interfaces: [Ci.nsINetworkInterface,
+                                                 Ci.nsIRIODataCallback]}),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface,
                                          Ci.nsIRILDataCallback]),
 
   // nsINetworkInterface
 
   NETWORK_STATE_UNKNOWN:       Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
   NETWORK_STATE_CONNECTING:    Ci.nsINetworkInterface.CONNECTING,
   NETWORK_STATE_CONNECTED:     Ci.nsINetworkInterface.CONNECTED,
@@ -1934,47 +2069,72 @@ let RILNetworkInterface = {
   dns2: null,
 
   httpProxyHost: null,
 
   httpProxyPort: null,
 
   // nsIRILDataCallback
 
+  dataCallError: function dataCallError(message) {
+    if (message.apn != this.dataCallSettings["apn"]) {
+      return;
+    }
+    debug("Data call error on APN: " + message.apn);
+    this.reset();
+  },
+
   dataCallStateChanged: function dataCallStateChanged(datacall) {
-    debug("Data call ID: " + datacall.cid + ", interface name: " + datacall.ifname);
+    if (datacall.apn != this.dataCallSettings["apn"]) {
+      return;
+    }
+    debug("Data call ID: " + datacall.cid + ", interface name: " +
+          datacall.ifname + ", APN name: " + datacall.apn);
     if (this.connecting &&
         (datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTING ||
          datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTED)) {
       this.connecting = false;
       this.cid = datacall.cid;
       this.name = datacall.ifname;
       this.ip = datacall.ip;
       this.netmask = datacall.netmask;
       this.broadcast = datacall.broadcast;
       this.gateway = datacall.gw;
       if (datacall.dns) {
         this.dns1 = datacall.dns[0];
         this.dns2 = datacall.dns[1];
       }
       if (!this.registeredAsNetworkInterface) {
-        let networkManager = Cc["@mozilla.org/network/manager;1"]
-                               .getService(Ci.nsINetworkManager);
-        networkManager.registerNetworkInterface(this);
+        gNetworkManager.registerNetworkInterface(this);
         this.registeredAsNetworkInterface = true;
       }
     }
     if (this.cid != datacall.cid) {
       return;
     }
     if (this.state == datacall.state) {
       return;
     }
 
     this.state = datacall.state;
+
+    // In case the data setting changed while the datacall was being started or
+    // ended, let's re-check the setting and potentially adjust the datacall
+    // state again.
+    if (this == this.mRIL.dataNetworkInterface) {
+      this.mRIL.updateRILNetworkInterface();
+    }
+
+    if (this.state == RIL.GECKO_NETWORK_STATE_UNKNOWN &&
+       this.registeredAsNetworkInterface) {
+      gNetworkManager.unregisterNetworkInterface(this);
+      this.registeredAsNetworkInterface = false;
+      return;
+    }
+
     Services.obs.notifyObservers(this,
                                  kNetworkInterfaceStateChangedTopic,
                                  null);
   },
 
   receiveDataCallList: function receiveDataCallList(dataCalls, length) {
   },
 
@@ -1984,42 +2144,40 @@ let RILNetworkInterface = {
   registeredAsDataCallCallback: false,
   registeredAsNetworkInterface: false,
   connecting: false,
   dataCallSettings: {},
 
   // APN failed connections. Retry counter
   apnRetryCounter: 0,
 
-  get mRIL() {
-    delete this.mRIL;
-    return this.mRIL = Cc["@mozilla.org/telephony/system-worker-manager;1"]
-                         .getService(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIRadioInterfaceLayer);
-  },
-
   get connected() {
     return this.state == RIL.GECKO_NETWORK_STATE_CONNECTED;
   },
 
   connect: function connect(options) {
     if (this.connecting || this.connected) {
       return;
     }
 
     if (!this.registeredAsDataCallCallback) {
       this.mRIL.registerDataCallCallback(this);
       this.registeredAsDataCallCallback = true;
     }
 
     if (options) {
-      // Save the APN data locally for using them in connection retries. 
+      // Save the APN data locally for using them in connection retries.
       this.dataCallSettings = options;
     }
 
+    if (!this.dataCallSettings["apn"]) {
+      debug("APN name is empty, nothing to do.");
+      return;
+    }
+
     this.httpProxyHost = this.dataCallSettings["httpProxyHost"];
     this.httpProxyPort = this.dataCallSettings["httpProxyPort"];
 
     debug("Going to set up data connection with APN " + this.dataCallSettings["apn"]);
     this.mRIL.setupDataCall(RIL.DATACALL_RADIOTECHNOLOGY_GSM,
                             this.dataCallSettings["apn"], 
                             this.dataCallSettings["user"], 
                             this.dataCallSettings["passwd"],
@@ -2061,17 +2219,17 @@ let RILNetworkInterface = {
     }
     let reason = RIL.DATACALL_DEACTIVATE_NO_REASON;
     debug("Going to disconnet data connection " + this.cid);
     this.mRIL.deactivateDataCall(this.cid, reason);
   },
 
   // Entry method for timer events. Used to reconnect to a failed APN
   notify: function(timer) {
-    RILNetworkInterface.connect();
+    this.connect();
   },
 
   shutdown: function() {
     this.timer = null;
   }
 
 };
 
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -225,17 +225,17 @@ interface nsIRilContext : nsISupports
 
   readonly attribute nsIICCRecords icc;
 
   readonly attribute nsIDOMMozMobileConnectionInfo voice;
 
   readonly attribute nsIDOMMozMobileConnectionInfo data;
 };
 
-[scriptable, uuid(0a05f286-608d-4d2e-ab72-16bd36e93c15)]
+[scriptable, uuid(a90fef2c-44aa-4f2b-a0ee-a590e9dd345e)]
 interface nsIRadioInterfaceLayer : nsISupports
 {
   const unsigned short CALL_STATE_UNKNOWN = 0;
   const unsigned short CALL_STATE_DIALING = 1;
   const unsigned short CALL_STATE_ALERTING = 2;
   const unsigned short CALL_STATE_BUSY = 3;
   const unsigned short CALL_STATE_CONNECTING = 4;
   const unsigned short CALL_STATE_CONNECTED = 5;
@@ -251,16 +251,19 @@ interface nsIRadioInterfaceLayer : nsISu
    */
   void setRadioEnabled(in bool value);
 
   readonly attribute nsIRilContext rilContext;
 
   /**
    * PDP APIs
    */
+  void setupDataCallByType(in DOMString apntype);
+  void deactivateDataCallByType(in DOMString apntype);
+  long getDataCallStateByType(in DOMString apntype);
   void setupDataCall(in long radioTech,
                      in DOMString apn,
                      in DOMString user,
                      in DOMString passwd,
                      in long chappap,
                      in DOMString pdptype);
   void deactivateDataCall(in DOMString cid,
                           in DOMString reason);
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -444,16 +444,23 @@ const RESPONSE_DATA_LENGTH = 12;
 const RESPONSE_DATA_STRUCTURE = 13;
 const RESPONSE_DATA_RECORD_LENGTH = 14;
 
 // Types of files  TS 11.11 9.3
 const EF_TYPE_TRANSPARENT = 0;
 const EF_TYPE_LINEAR_FIXED = 1;
 const EF_TYPE_CYCLIC = 3;
 
+// Status code of EFsms
+// see 3GPP TS 51.011 clause 10.5.3
+const EFSMS_STATUS_FREE       = 0x00;
+const EFSMS_STATUS_READ       = 0x01;
+const EFSMS_STATUS_TO_BE_READ = 0x03;
+const EFSMS_STATUS_TO_BE_SENT = 0x07;
+
 // For retrieving MSISDN, TS 151.011 clause 10.5.5
 const MSISDN_FOOTER_SIZE_BYTES = 14;
 const MSISDN_MAX_NUMBER_SIZE_BYTES = 10;
 
 // READ_RECORD mode,  TS 102.221
 const READ_RECORD_ABSOLUTE_MODE = 4;
 
 // GET_RESPONSE mandatory response size for EF, see TS 51.011 clause 9, 
@@ -466,16 +473,17 @@ const EF_PATH_DF_PHONEBOOK = "5f3a";
 const EF_PATH_DF_TELECOM   = "7f10";
 const EF_PATH_DF_GSM       = "7f20";
 const EF_PATH_ADF_USIM     = "7fff";
 
 // Status code of sw1 for ICC I/O,
 // see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
 const ICC_STATUS_NORMAL_ENDING = 0x90;
 const ICC_STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
+const ICC_STATUS_SAT_BUSY = 0x93;
 const ICC_STATUS_WITH_SIM_DATA = 0x9e;
 const ICC_STATUS_WITH_RESPONSE_DATA = 0x9f;
 const ICC_STATUS_ERROR_WRONG_LENGTH = 0x67;
 const ICC_STATUS_ERROR_COMMAND_NOT_ALLOWED = 0x69;
 const ICC_STATUS_ERROR_WRONG_PARAMETERS = 0x6a;
 
 // ICC call barring facility.
 // TS 27.007, clause 7.4, +CLCK
@@ -511,29 +519,31 @@ const ICC_USIM_EFEMAIL_TAG = 0xca;
 const ICC_USIM_EFCCP1_TAG  = 0xcb;
 
 /**
  * STK constants.
  */
 //  Tags for Ber Tlv.
 const BER_UNKNOWN_TAG = 0x00;
 const BER_PROACTIVE_COMMAND_TAG = 0xd0;
+const BER_SMS_PP_DOWNLOAD_TAG = 0xd1;
 const BER_MENU_SELECTION_TAG = 0xd3;
 const BER_EVENT_DOWNLOAD_TAG = 0xd6;
 
 // Flags in Comprehension TLV.
 const COMPREHENSIONTLV_FLAG_CR = 0x80;  // Comprehension required.
 
 // Tags for Comprehension TLV.
 const COMPREHENSIONTLV_TAG_COMMAND_DETAILS = 0x01;
 const COMPREHENSIONTLV_TAG_DEVICE_ID = 0x02;
 const COMPREHENSIONTLV_TAG_RESULT = 0x03;
 const COMPREHENSIONTLV_TAG_DURATION = 0x04;
 const COMPREHENSIONTLV_TAG_ALPHA_ID = 0x05;
 const COMPREHENSIONTLV_TAG_ADDRESS = 0x06;
+const COMPREHENSIONTLV_TAG_SMS_TPDU = 0x0b;
 const COMPREHENSIONTLV_TAG_TEXT_STRING = 0x0d;
 const COMPREHENSIONTLV_TAG_ITEM = 0x0f;
 const COMPREHENSIONTLV_TAG_ITEM_ID = 0x10;
 const COMPREHENSIONTLV_TAG_RESPONSE_LENGTH = 0x11;
 const COMPREHENSIONTLV_TAG_HELP_REQUEST = 0x15;
 const COMPREHENSIONTLV_TAG_DEFAULT_TEXT = 0x17;
 const COMPREHENSIONTLV_TAG_EVENT_LIST = 0x19;
 const COMPREHENSIONTLV_TAG_ICON_ID = 0x1e;
@@ -723,22 +733,24 @@ const STK_EVENT_TYPE_BROWSING_STATUS = 0
  *
  * @see 3GPP TS 51.011 10.3.7 (SIM) and 3GPP TS 31.102 4.2.8 (USIM).
  */
 const GECKO_ICC_SERVICES = {
   sim: {
     ADN: 2,
     FDN: 3,
     SDN: 18,
+    DATA_DOWNLOAD_SMS_PP: 26,
     BDN: 31
   },
   usim: {
     FDN: 2,
     SDN: 4,
-    BDN: 6
+    BDN: 6,
+    DATA_DOWNLOAD_SMS_PP: 28
   }
 };
 
 /**
  * GSM PDU constants
  */
 
 // PDU TYPE-OF-ADDRESS
@@ -820,18 +832,26 @@ const PDU_MTI_SMS_DELIVER         = 0x00
 // PI - Parameter Indicator
 const PDU_PI_EXTENSION           = 0x80;
 const PDU_PI_USER_DATA_LENGTH    = 0x04;
 const PDU_PI_DATA_CODING_SCHEME  = 0x02;
 const PDU_PI_PROTOCOL_IDENTIFIER = 0x01;
 const PDU_PI_RESERVED            = 0x78;
 
 // FCS - Failure Cause
-const PDU_FCS_OK          = 0x00;
-const PDU_FCS_UNSPECIFIED = 0xFF;
+// 0...127   see 3GPP TS 24.011 clause E.2
+// 128...255 see 3GPP TS 23.040 clause 9.2.3.22
+// others    see 3GPP TS 27.005 clause 3.2.5
+const PDU_FCS_OK                       = 0x00;
+const PDU_FCS_PROTOCOL_ERROR           = 0x6F;
+const PDU_FCS_MEMORY_CAPACITY_EXCEEDED = 0XD3;
+const PDU_FCS_USAT_BUSY                = 0XD4;
+const PDU_FCS_USIM_DATA_DOWNLOAD_ERROR = 0xD5;
+const PDU_FCS_RESERVED                 = 0xE0;
+const PDU_FCS_UNSPECIFIED              = 0xFF;
 
 // ST - Status
 // Bit 7..0 = 000xxxxx, short message transaction completed
 const PDU_ST_0_RECEIVED             = 0x00;
 const PDU_ST_0_FORWARDED_NO_CONFIRM = 0x01;
 const PDU_ST_0_REPLACED_BY_SC       = 0x02;
 const PDU_ST_0_RESERVED_BEGIN       = 0x03;
 const PDU_ST_0_SC_SPECIFIC_BEGIN    = 0x10;
@@ -897,23 +917,23 @@ const PDU_PID_ANSI_136_R_DATA           
 const PDU_PID_ME_DATA_DOWNLOAD             = 0x7D;
 const PDU_PID_ME_DEPERSONALIZATION         = 0x7E;
 const PDU_PID_USIM_DATA_DOWNLOAD           = 0x7F;
 
 // DCS - Data Coding Scheme
 const PDU_DCS_MSG_CODING_7BITS_ALPHABET  = 0x00;
 const PDU_DCS_MSG_CODING_8BITS_ALPHABET  = 0x04;
 const PDU_DCS_MSG_CODING_16BITS_ALPHABET = 0x08;
-const PDU_DCS_MSG_CLASS_ME_SPECIFIC      = 0xF1;
-const PDU_DCS_MSG_CLASS_SIM_SPECIFIC     = 0xF2;
-const PDU_DCS_MSG_CLASS_TE_SPECIFIC      = 0xF3;
+const PDU_DCS_MSG_CLASS_UNKNOWN          = 0xFF;
+const PDU_DCS_MSG_CLASS_0                = 0x00;
+const PDU_DCS_MSG_CLASS_ME_SPECIFIC      = 0x01;
+const PDU_DCS_MSG_CLASS_SIM_SPECIFIC     = 0x02;
+const PDU_DCS_MSG_CLASS_TE_SPECIFIC      = 0x03;
 const PDU_DCS_CODING_GROUP_BITS          = 0xF0;
-const PDU_DCS_CODING_GROUP_7BITS_DISCARD = 0xC0;
-const PDU_DCS_CODING_GROUP_7BITS_STORE   = 0xD0;
-const PDU_DCS_CODING_GROUP_16BITS_STORE  = 0xE0;
+const PDU_DCS_MSG_CLASS_BITS             = 0x03;
 const PDU_DCS_MWI_ACTIVE_BITS            = 0x08;
 const PDU_DCS_MWI_ACTIVE_VALUE           = 0x08;
 const PDU_DCS_MWI_TYPE_BITS              = 0x03;
 const PDU_DCS_MWI_TYPE_VOICEMAIL         = 0x00;
 const PDU_DCS_MWI_TYPE_FAX               = 0x01;
 const PDU_DCS_MWI_TYPE_EMAIL             = 0x02;
 const PDU_DCS_MWI_TYPE_OTHER             = 0x03;
 
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -307,20 +307,32 @@ let Buf = {
            this.readUint8Unchecked() <<  8 |
            this.readUint8Unchecked();
   },
 
   /**
    * Functions for writing data to the outgoing buffer.
    */
 
+  /**
+   * Ensure position specified is writable.
+   *
+   * @param index
+   *        Data position in outgoing parcel, valid from 0 to
+   *        this.OUTGOING_BUFFER_LENGTH.
+   */
+  ensureOutgoingAvailable: function ensureOutgoingAvailable(index) {
+    if (index >= this.OUTGOING_BUFFER_LENGTH) {
+      this.growOutgoingBuffer(index + 1);
+    }
+  },
+
   writeUint8: function writeUint8(value) {
-    if (this.outgoingIndex >= this.OUTGOING_BUFFER_LENGTH) {
-      this.growOutgoingBuffer(this.outgoingIndex + 1);
-    }
+    this.ensureOutgoingAvailable(this.outgoingIndex);
+
     this.outgoingBytes[this.outgoingIndex] = value;
     this.outgoingIndex++;
   },
 
   writeUint16: function writeUint16(value) {
     this.writeUint8(value & 0xff);
     this.writeUint8((value >> 8) & 0xff);
   },
@@ -371,16 +383,48 @@ let Buf = {
     this.outgoingIndex = 0;
     this.writeUint8((value >> 24) & 0xff);
     this.writeUint8((value >> 16) & 0xff);
     this.writeUint8((value >> 8) & 0xff);
     this.writeUint8(value & 0xff);
     this.outgoingIndex = currentIndex;
   },
 
+  copyIncomingToOutgoing: function copyIncomingToOutgoing(length) {
+    if (!length || (length < 0)) {
+      return;
+    }
+
+    let translatedReadIndexEnd = this.currentParcelSize - this.readAvailable + length - 1;
+    this.ensureIncomingAvailable(translatedReadIndexEnd);
+
+    let translatedWriteIndexEnd = this.outgoingIndex + length - 1
+    this.ensureOutgoingAvailable(translatedWriteIndexEnd);
+
+    let newIncomingReadIndex = this.incomingReadIndex + length;
+    if (newIncomingReadIndex < this.INCOMING_BUFFER_LENGTH) {
+      // Reading won't cause wrapping, go ahead with builtin copy.
+      this.outgoingBytes.set(this.incomingBytes.subarray(this.incomingReadIndex, newIncomingReadIndex),
+                             this.outgoingIndex);
+    } else {
+      // Not so lucky.
+      newIncomingReadIndex %= this.INCOMING_BUFFER_LENGTH;
+      this.outgoingBytes.set(this.incomingBytes.subarray(this.incomingReadIndex, this.INCOMING_BUFFER_LENGTH),
+                             this.outgoingIndex);
+      if (newIncomingReadIndex) {
+        let firstPartLength = this.INCOMING_BUFFER_LENGTH - this.incomingReadIndex;
+        this.outgoingBytes.set(this.incomingBytes.subarray(0, newIncomingReadIndex),
+                               this.outgoingIndex + firstPartLength);
+      }
+    }
+
+    this.incomingReadIndex = newIncomingReadIndex;
+    this.readAvailable -= length;
+    this.outgoingIndex += length;
+  },
 
   /**
    * Parcel management
    */
 
   /**
    * Write incoming data to the circular buffer.
    *
@@ -2923,34 +2967,44 @@ let RIL = {
     for each (let currentDataCall in this.currentDataCalls) {
       let updatedDataCall;
       if (datacalls) {
         updatedDataCall = datacalls[currentDataCall.cid];
         delete datacalls[currentDataCall.cid];
       }
 
       if (!updatedDataCall) {
-        delete this.currentDataCalls[currentDataCall.callIndex];
         currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED;
         currentDataCall.rilMessageType = "datacallstatechange";
         this.sendDOMMessage(currentDataCall);
         continue;
       }
 
+      if (updatedDataCall && !updatedDataCall.ifname) {
+        delete this.currentDataCalls[currentDataCall.cid];
+        currentDataCall.state = GECKO_NETWORK_STATE_UNKNOWN;
+        currentDataCall.rilMessageType = "datacallstatechange";
+        this.sendDOMMessage(currentDataCall);
+        continue;
+      }
+
       this._setDataCallGeckoState(updatedDataCall);
       if (updatedDataCall.state != currentDataCall.state) {
         currentDataCall.status = updatedDataCall.status;
         currentDataCall.active = updatedDataCall.active;
         currentDataCall.state = updatedDataCall.state;
         currentDataCall.rilMessageType = "datacallstatechange";
         this.sendDOMMessage(currentDataCall);
       }
     }
 
     for each (let newDataCall in datacalls) {
+      if (!newDataCall.ifname) {
+        continue;
+      }
       this.currentDataCalls[newDataCall.cid] = newDataCall;
       this._setDataCallGeckoState(newDataCall);
       if (newDataCallOptions) {
         newDataCall.radioTech = newDataCallOptions.radioTech;
         newDataCall.apn = newDataCallOptions.apn;
         newDataCall.user = newDataCallOptions.user;
         newDataCall.passwd = newDataCallOptions.passwd;
         newDataCall.chappap = newDataCallOptions.chappap;
@@ -3032,16 +3086,174 @@ let RIL = {
       throw new Error("Invalid network tuple (should be 5 or 6 digits): " + networkTuple);
     }
 
     network.mcc = mcc;
     network.mnc = mnc;
   },
 
   /**
+   * @param message A decoded SMS-DELIVER message.
+   *
+   * @see 3GPP TS 31.111 section 7.1.1
+   */
+  dataDownloadViaSMSPP: function dataDownloadViaSMSPP(message) {
+    let options = {
+      pid: message.pid,
+      dcs: message.dcs,
+      encoding: message.encoding,
+    };
+    Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, options);
+
+    Buf.seekIncoming(-1 * (Buf.currentParcelSize - Buf.readAvailable
+                           - 2 * UINT32_SIZE)); // Skip response_type & request_type.
+    let messageStringLength = Buf.readUint32(); // In semi-octets
+    let smscLength = GsmPDUHelper.readHexOctet(); // In octets, inclusive of TOA
+    let tpduLength = (messageStringLength / 2) - (smscLength + 1); // In octets
+
+    // Device identities: 4 bytes
+    // Address: 0 or (2 + smscLength)
+    // SMS TPDU: (2 or 3) + tpduLength
+    let berLen = 4 +
+                 (smscLength ? (2 + smscLength) : 0) +
+                 (tpduLength <= 127 ? 2 : 3) + tpduLength; // In octets
+
+    let parcelLength = (berLen <= 127 ? 2 : 3) + berLen; // In octets
+    Buf.writeUint32(parcelLength * 2); // In semi-octets
+
+    // Write a BER-TLV
+    GsmPDUHelper.writeHexOctet(BER_SMS_PP_DOWNLOAD_TAG);
+    if (berLen > 127) {
+      GsmPDUHelper.writeHexOctet(0x81);
+    }
+    GsmPDUHelper.writeHexOctet(berLen);
+
+    // Device Identifies-TLV
+    GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DEVICE_ID |
+                               COMPREHENSIONTLV_FLAG_CR);
+    GsmPDUHelper.writeHexOctet(0x02);
+    GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_NETWORK);
+    GsmPDUHelper.writeHexOctet(STK_DEVICE_ID_SIM);
+
+    // Address-TLV
+    if (smscLength) {
+      GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ADDRESS);
+      GsmPDUHelper.writeHexOctet(smscLength);
+      Buf.copyIncomingToOutgoing(PDU_HEX_OCTET_SIZE * smscLength);
+    }
+
+    // SMS TPDU-TLV
+    GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_SMS_TPDU |
+                               COMPREHENSIONTLV_FLAG_CR);
+    if (tpduLength > 127) {
+      GsmPDUHelper.writeHexOctet(0x81);
+    }
+    GsmPDUHelper.writeHexOctet(tpduLength);
+    Buf.copyIncomingToOutgoing(PDU_HEX_OCTET_SIZE * tpduLength);
+
+    // Write 2 string delimitors for the total string length must be even.
+    Buf.writeStringDelimiter(0);
+
+    Buf.sendParcel();
+  },
+
+  /**
+   * @param success A boolean value indicating the result of previous
+   *                SMS-DELIVER message handling.
+   * @param responsePduLen ICC IO response PDU length in octets.
+   * @param options An object that contains four attributes: `pid`, `dcs`,
+   *                `encoding` and `responsePduLen`.
+   *
+   * @see 3GPP TS 23.040 section 9.2.2.1a
+   */
+  acknowledgeIncomingGsmSmsWithPDU: function acknowledgeIncomingGsmSmsWithPDU(success, responsePduLen, options) {
+    Buf.newParcel(REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU);
+
+    // Two strings.
+    Buf.writeUint32(2);
+
+    // String 1: Success
+    Buf.writeString(success ? "1" : "0");
+
+    // String 2: RP-ACK/RP-ERROR PDU
+    Buf.writeUint32(2 * (responsePduLen + (success ? 5 : 6))); // In semi-octet
+    // 1. TP-MTI & TP-UDHI
+    GsmPDUHelper.writeHexOctet(PDU_MTI_SMS_DELIVER);
+    if (!success) {
+      // 2. TP-FCS
+      GsmPDUHelper.writeHexOctet(PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
+    }
+    // 3. TP-PI
+    GsmPDUHelper.writeHexOctet(PDU_PI_USER_DATA_LENGTH |
+                               PDU_PI_DATA_CODING_SCHEME |
+                               PDU_PI_PROTOCOL_IDENTIFIER);
+    // 4. TP-PID
+    GsmPDUHelper.writeHexOctet(options.pid);
+    // 5. TP-DCS
+    GsmPDUHelper.writeHexOctet(options.dcs);
+    // 6. TP-UDL
+    if (options.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
+      GsmPDUHelper.writeHexOctet(Math.floor(responsePduLen * 8 / 7));
+    } else {
+      GsmPDUHelper.writeHexOctet(responsePduLen);
+    }
+    // TP-UD
+    Buf.copyIncomingToOutgoing(PDU_HEX_OCTET_SIZE * responsePduLen);
+    // Write 2 string delimitors for the total string length must be even.
+    Buf.writeStringDelimiter(0);
+
+    Buf.sendParcel();
+  },
+
+  /**
+   * @param message A decoded SMS-DELIVER message.
+   */
+  writeSmsToSIM: function writeSmsToSIM(message) {
+    Buf.newParcel(REQUEST_WRITE_SMS_TO_SIM);
+
+    // Write EFsms Status
+    Buf.writeUint32(EFSMS_STATUS_FREE);
+
+    Buf.seekIncoming(-1 * (Buf.currentParcelSize - Buf.readAvailable
+                           - 2 * UINT32_SIZE)); // Skip response_type & request_type.
+    let messageStringLength = Buf.readUint32(); // In semi-octets
+    let smscLength = GsmPDUHelper.readHexOctet(); // In octets, inclusive of TOA
+    let pduLength = (messageStringLength / 2) - (smscLength + 1); // In octets
+
+    // 1. Write PDU first.
+    if (smscLength > 0) {
+      Buf.seekIncoming(smscLength * PDU_HEX_OCTET_SIZE);
+    }
+    // Write EFsms PDU string length
+    Buf.writeUint32(2 * pduLength); // In semi-octets
+    if (pduLength) {
+      Buf.copyIncomingToOutgoing(PDU_HEX_OCTET_SIZE * pduLength);
+    }
+    // Write 2 string delimitors for the total string length must be even.
+    Buf.writeStringDelimiter(0);
+
+    // 2. Write SMSC
+    // Write EFsms SMSC string length
+    Buf.writeUint32(2 * (smscLength + 1)); // Plus smscLength itself, in semi-octets
+    // Write smscLength
+    GsmPDUHelper.writeHexOctet(smscLength);
+    // Write TOA & SMSC Address
+    if (smscLength) {
+      Buf.seekIncoming(-1 * (Buf.currentParcelSize - Buf.readAvailable
+                             - 2 * UINT32_SIZE // Skip response_type, request_type.
+                             - 2 * PDU_HEX_OCTET_SIZE)); // Skip messageStringLength & smscLength.
+      Buf.copyIncomingToOutgoing(PDU_HEX_OCTET_SIZE * smscLength);
+    }
+    // Write 2 string delimitors for the total string length must be even.
+    Buf.writeStringDelimiter(0);
+
+    Buf.sendParcel();
+  },
+
+  /**
    * Helper for processing received SMS parcel data.
    *
    * @param length
    *        Length of SMS string in the incoming parcel.
    *
    * @return Message parsed or null for invalid message.
    */
   _processReceivedSms: function _processReceivedSms(length) {
@@ -3079,16 +3291,57 @@ let RIL = {
 
     if (message.epid == PDU_PID_SHORT_MESSAGE_TYPE_0) {
       // `A short message type 0 indicates that the ME must acknowledge receipt
       // of the short message but shall discard its contents.` ~ 3GPP TS 23.040
       // 9.2.3.9
       return PDU_FCS_OK;
     }
 
+    if (message.messageClass == PDU_DCS_MSG_CLASS_SIM_SPECIFIC) {
+      switch (message.epid) {
+        case PDU_PID_ANSI_136_R_DATA:
+        case PDU_PID_USIM_DATA_DOWNLOAD:
+          if (this.isICCServiceAvailable("DATA_DOWNLOAD_SMS_PP")) {
+            // `If the service "data download via SMS Point-to-Point" is
+            // allocated and activated in the (U)SIM Service Table, ... then the
+            // ME shall pass the message transparently to the UICC using the
+            // ENVELOPE (SMS-PP DOWNLOAD).` ~ 3GPP TS 31.111 7.1.1.1
+            this.dataDownloadViaSMSPP(message);
+
+            // `the ME shall not display the message, or alert the user of a
+            // short message waiting.` ~ 3GPP TS 31.111 7.1.1.1
+            return PDU_FCS_RESERVED;
+          }
+
+          // If the service "data download via SMS-PP" is not available in the
+          // (U)SIM Service Table, ..., then the ME shall store the message in
+          // EFsms in accordance with TS 31.102` ~ 3GPP TS 31.111 7.1.1.1
+        default:
+          this.writeSmsToSIM(message);
+          break;
+      }
+    }
+
+    // TODO: Bug 739143: B2G SMS: Support SMS Storage Full event
+    if ((message.messageClass != PDU_DCS_MSG_CLASS_0) && !true) {
+      // `When a mobile terminated message is class 0..., the MS shall display
+      // the message immediately and send a ACK to the SC ..., irrespective of
+      // whether there is memory available in the (U)SIM or ME.` ~ 3GPP 23.038
+      // clause 4.
+
+      if (message.messageClass == PDU_DCS_MSG_CLASS_SIM_SPECIFIC) {
+        // `If all the short message storage at the MS is already in use, the
+        // MS shall return "memory capacity exceeded".` ~ 3GPP 23.038 clause 4.
+        return PDU_FCS_MEMORY_CAPACITY_EXCEEDED;
+      }
+
+      return PDU_FCS_UNSPECIFIED;
+    }
+
     if (message.header && (message.header.segmentMaxSeq > 1)) {
       message = this._processReceivedSmsSegment(message);
     } else {
       if (message.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
         message.fullData = message.data;
         delete message.data;
       } else {
         message.fullBody = message.body;
@@ -3096,16 +3349,22 @@ let RIL = {
       }
     }
 
     if (message) {
       message.rilMessageType = "sms-received";
       this.sendDOMMessage(message);
     }
 
+    if (message.messageClass == PDU_DCS_MSG_CLASS_SIM_SPECIFIC) {
+      // `MS shall ensure that the message has been to the SMS data field in
+      // the (U)SIM before sending an ACK to the SC.`  ~ 3GPP 23.038 clause 4
+      return PDU_FCS_RESERVED;
+    }
+
     return PDU_FCS_OK;
   },
 
   /**
    * Helper for processing SMS-STATUS-REPORT PDUs.
    *
    * @param length
    *        Length of SMS string in the incoming parcel.
@@ -3817,17 +4076,17 @@ RIL[REQUEST_GET_IMEISV] = function REQUE
 RIL[REQUEST_ANSWER] = null;
 RIL[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let datacall = this.currentDataCalls[options.cid];
   delete this.currentDataCalls[options.cid];
-  datacall.state = GECKO_NETWORK_STATE_DISCONNECTED;
+  datacall.state = GECKO_NETWORK_STATE_UNKNOWN;
   datacall.rilMessageType = "datacallstatechange";
   this.sendDOMMessage(datacall);
 };
 RIL[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
   options.success = options.rilRequestError == 0;
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
@@ -4001,17 +4260,27 @@ RIL[REQUEST_DATA_CALL_LIST] = function R
   }
   this._processDataCallList(datacalls, newDataCallOptions);
 };
 RIL[REQUEST_RESET_RADIO] = null;
 RIL[REQUEST_OEM_HOOK_RAW] = null;
 RIL[REQUEST_OEM_HOOK_STRINGS] = null;
 RIL[REQUEST_SCREEN_STATE] = null;
 RIL[REQUEST_SET_SUPP_SVC_NOTIFICATION] = null;
-RIL[REQUEST_WRITE_SMS_TO_SIM] = null;
+RIL[REQUEST_WRITE_SMS_TO_SIM] = function REQUEST_WRITE_SMS_TO_SIM(length, options) {
+  if (options.rilRequestError) {
+    // `The MS shall return a "protocol error, unspecified" error message if
+    // the short message cannot be stored in the (U)SIM, and there is other
+    // message storage available at the MS` ~ 3GPP TS 23.038 section 4. Here
+    // we assume we always have indexed db as another storage.
+    this.acknowledgeSMS(false, PDU_FCS_PROTOCOL_ERROR);
+  } else {
+    this.acknowledgeSMS(true, PDU_FCS_OK);
+  }
+};
 RIL[REQUEST_DELETE_SMS_ON_SIM] = null;
 RIL[REQUEST_SET_BAND_MODE] = null;
 RIL[REQUEST_QUERY_AVAILABLE_BAND_MODE] = null;
 RIL[REQUEST_STK_GET_PROFILE] = null;
 RIL[REQUEST_STK_SET_PROFILE] = null;
 RIL[REQUEST_STK_SEND_ENVELOPE_COMMAND] = null;
 RIL[REQUEST_STK_SEND_TERMINAL_RESPONSE] = null;
 RIL[REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM] = null;
@@ -4048,16 +4317,43 @@ RIL[REQUEST_GET_SMSC_ADDRESS] = function
     return;
   }
 
   this.SMSC = Buf.readString();
 };
 RIL[REQUEST_SET_SMSC_ADDRESS] = null;
 RIL[REQUEST_REPORT_SMS_MEMORY_STATUS] = null;
 RIL[REQUEST_REPORT_STK_SERVICE_IS_RUNNING] = null;
+RIL[REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU] = null;
+RIL[REQUEST_STK_SEND_ENVELOPE_WITH_STATUS] = function REQUEST_STK_SEND_ENVELOPE_WITH_STATUS(length, options) {
+  if (options.rilRequestError) {
+    this.acknowledgeSMS(false, PDU_FCS_UNSPECIFIED);
+    return;
+  }
+
+  let sw1 = Buf.readUint32();
+  let sw2 = Buf.readUint32();
+  if ((sw1 == ICC_STATUS_SAT_BUSY) && (sw2 == 0x00)) {
+    this.acknowledgeSMS(false, PDU_FCS_USAT_BUSY);
+    return;
+  }
+
+  let success = ((sw1 == ICC_STATUS_NORMAL_ENDING) && (sw2 == 0x00))
+                || (sw1 == ICC_STATUS_NORMAL_ENDING_WITH_EXTRA);
+
+  let messageStringLength = Buf.readUint32(); // In semi-octets
+  let responsePduLen = messageStringLength / 2; // In octets
+  if (!responsePduLen) {
+    this.acknowledgeSMS(success, success ? PDU_FCS_OK
+                                         : PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
+    return;
+  }
+
+  this.acknowledgeIncomingGsmSmsWithPDU(success, responsePduLen, options);
+};
 RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() {
   let radioState = Buf.readUint32();
 
   // Ensure radio state at boot time.
   if (this._isInitialRadioState) {
     this._isInitialRadioState = false;
     if (radioState != RADIO_STATE_OFF) {
       this.setRadioPower({on: false});
@@ -4117,17 +4413,20 @@ RIL[UNSOLICITED_RESPONSE_CALL_STATE_CHAN
 };
 RIL[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED() {
   if (DEBUG) debug("Network state changed, re-requesting phone state and ICC status");
   this.getICCStatus();
   this.requestNetworkInfo();
 };
 RIL[UNSOLICITED_RESPONSE_NEW_SMS] = function UNSOLICITED_RESPONSE_NEW_SMS(length) {
   let result = this._processSmsDeliver(length);
-  this.acknowledgeSMS(result == PDU_FCS_OK, result);
+  if (result != PDU_FCS_RESERVED) {
+    // Not reserved FCS values, send ACK now.
+    this.acknowledgeSMS(result == PDU_FCS_OK, result);
+  }
 };
 RIL[UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT] = function UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT(length) {
   let result = this._processSmsStatusReport(length);
   this.acknowledgeSMS(result == PDU_FCS_OK, result);
 };
 RIL[UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM] = function UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM(length) {
   let info = Buf.readUint32List();
   //TODO
@@ -5094,16 +5393,18 @@ let GsmPDUHelper = {
     msg.pid = this.readHexOctet();
 
     msg.epid = msg.pid;
     switch (msg.epid & 0xC0) {
       case 0x40:
         // Bit 7..0 = 01xxxxxx
         switch (msg.epid) {
           case PDU_PID_SHORT_MESSAGE_TYPE_0:
+          case PDU_PID_ANSI_136_R_DATA:
+          case PDU_PID_USIM_DATA_DOWNLOAD:
             return;
           case PDU_PID_RETURN_CALL_MESSAGE:
             // Level 1 of message waiting indication:
             // Only a return call message is provided
             let mwi = msg.mwi = {};
 
             // TODO: When should we de-activate the level 1 indicator?
             mwi.active = true;
@@ -5125,99 +5426,99 @@ let GsmPDUHelper = {
    *        message object for output.
    *
    * @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
    */
   readDataCodingScheme: function readDataCodingScheme(msg) {
     let dcs = this.readHexOctet();
     if (DEBUG) debug("PDU: read dcs: " + dcs);
 
-    // Level 2 of message waiting indication
-    this.readMessageWaitingFromDCS(msg, dcs);
-
+    // No message class by default.
+    let messageClass = PDU_DCS_MSG_CLASS_UNKNOWN;
     // 7 bit is the default fallback encoding.
     let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
-    switch (dcs & 0xC0) {
-      case 0x0:
-        // bits 7..4 = 00xx
+    switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
+      case 0x40: // bits 7..4 = 01xx
+      case 0x50:
+      case 0x60:
+      case 0x70:
+        // Bit 5..0 are coded exactly the same as Group 00xx
+      case 0x00: // bits 7..4 = 00xx
+      case 0x10:
+      case 0x20:
+      case 0x30:
+        if (dcs & 0x10) {
+          messageClass = dcs & PDU_DCS_MSG_CLASS_BITS;
+        }
         switch (dcs & 0x0C) {
           case 0x4:
             encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
             break;
           case 0x8:
             encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
             break;
         }
         break;
-      case 0xC0:
-        // bits 7..4 = 11xx
-        switch (dcs & 0x30) {
-          case 0x20:
-            encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
+
+      case 0xE0: // bits 7..4 = 1110
+        encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
+        // Bit 3..0 are coded exactly the same as Message Waiting Indication
+        // Group 1101.
+      case 0xC0: // bits 7..4 = 1100
+      case 0xD0: // bits 7..4 = 1101
+        // Indiciates voicemail indicator set or clear
+        let active = (dcs & PDU_DCS_MWI_ACTIVE_BITS) == PDU_DCS_MWI_ACTIVE_VALUE;
+
+        // If TP-UDH is present, these values will be overwritten
+        switch (dcs & PDU_DCS_MWI_TYPE_BITS) {
+          case PDU_DCS_MWI_TYPE_VOICEMAIL:
+            let mwi = msg.mwi;
+            if (!mwi) {
+              mwi = msg.mwi = {};
+            }
+
+            mwi.active = active;
+            mwi.discard = (dcs & PDU_DCS_CODING_GROUP_BITS) == 0xC0;
+            mwi.msgCount = active ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN : 0;
+
+            if (DEBUG) {
+              debug("MWI in DCS received for voicemail: " + JSON.stringify(mwi));
+            }
             break;
-          case 0x30:
-            if (dcs & 0x04) {
-              encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
-            }
+          case PDU_DCS_MWI_TYPE_FAX:
+            if (DEBUG) debug("MWI in DCS received for fax");
+            break;
+          case PDU_DCS_MWI_TYPE_EMAIL:
+            if (DEBUG) debug("MWI in DCS received for email");
+            break;
+          default:
+            if (DEBUG) debug("MWI in DCS received for \"other\"");
             break;
         }
         break;
+
+      case 0xF0: // bits 7..4 = 1111
+        if (dcs & 0x04) {
+          encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
+        }
+        messageClass = dcs & PDU_DCS_MSG_CLASS_BITS;
+        break;
+
       default:
         // Falling back to default encoding.
         break;
     }
 
     msg.dcs = dcs;
     msg.encoding = encoding;
+    msg.messageClass = messageClass;
 
     if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
   },
 
-  readMessageWaitingFromDCS: function readMessageWaitingFromDCS(msg, dcs) {
-    // 0xC0 == 7 bit, don't store
-    // 0xD0 == 7 bit, store
-    // 0xE0 == UCS-2, store
-    let codingGroup = dcs & PDU_DCS_CODING_GROUP_BITS;
-
-    if (codingGroup == PDU_DCS_CODING_GROUP_7BITS_DISCARD ||
-        codingGroup == PDU_DCS_CODING_GROUP_7BITS_STORE ||
-        codingGroup == PDU_DCS_CODING_GROUP_16BITS_STORE) {
-
-      // Indiciates voicemail indicator set or clear
-      let active = (dcs & PDU_DCS_MWI_ACTIVE_BITS) == PDU_DCS_MWI_ACTIVE_VALUE;
-
-      // If TP-UDH is present, these values will be overwritten
-      switch (dcs & PDU_DCS_MWI_TYPE_BITS) {
-        case PDU_DCS_MWI_TYPE_VOICEMAIL:
-          let mwi = msg.mwi;
-          if (!mwi) {
-            mwi = msg.mwi = {};
-          }
-
-          mwi.active = active;
-          mwi.discard = codingGroup == PDU_DCS_CODING_GROUP_7BITS_DISCARD;
-          mwi.msgCount = active ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN : 0;
-
-          if (DEBUG) {
-            debug("MWI in DCS received for voicemail: " + JSON.stringify(mwi));
-          }
-          break;
-        case PDU_DCS_MWI_TYPE_FAX:
-          if (DEBUG) debug("MWI in DCS received for fax");
-          break;
-        case PDU_DCS_MWI_TYPE_EMAIL:
-          if (DEBUG) debug("MWI in DCS received for email");
-          break;
-        default:
-          if (DEBUG) debug("MWI in DCS received for \"other\"");
-          break;
-      }
-    }
-  },
-
   /**
    * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
    *
    * @see 3GPP TS 23.040 9.2.3.11
    */
   readTimestamp: function readTimestamp() {
     let year   = this.readSwappedNibbleBcdNum(1) + PDU_TIMESTAMP_YEAR_OFFSET;
     let month  = this.readSwappedNibbleBcdNum(1) - 1;
--- a/dom/system/gonk/tests/test_ril_worker_sms.js
+++ b/dom/system/gonk/tests/test_ril_worker_sms.js
@@ -50,16 +50,121 @@ add_test(function test_nl_single_shift_t
     do_check_eq(table[PDU_NL_PAGE_BREAK], FF);
     do_check_eq(table[PDU_NL_RESERVED_CONTROL], RESCTL);
   }
 
   run_next_test();
 });
 
 /**
+ * Verify GsmPDUHelper#readDataCodingScheme.
+ */
+add_test(function test_GsmPDUHelper_readDataCodingScheme() {
+  let worker = newWorker({
+    postRILMessage: function fakePostRILMessage(data) {
+      // Do nothing
+    },
+    postMessage: function fakePostMessage(message) {
+      // Do nothing
+    }
+  });
+
+  let helper = worker.GsmPDUHelper;
+  function test_dcs(dcs, encoding, messageClass, mwi) {
+    helper.readHexOctet = function () {
+      return dcs;
+    }
+
+    let msg = {};
+    helper.readDataCodingScheme(msg);
+
+    do_check_eq(msg.dcs, dcs);
+    do_check_eq(msg.encoding, encoding);
+    do_check_eq(msg.messageClass, messageClass);
+    do_check_eq(msg.mwi == null, mwi == null);
+    if (mwi != null) {
+      do_check_eq(msg.mwi.active, mwi.active);
+      do_check_eq(msg.mwi.discard, mwi.discard);
+      do_check_eq(msg.mwi.msgCount, mwi.msgCount);
+    }
+  }
+
+  // Group 00xx
+  //   Bit 3 and 2 indicate the character set being used.
+  test_dcs(0x00, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x04, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x08, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x0C, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  //   Bit 4, if set to 0, indicates that bits 1 to 0 are reserved and have no
+  //   message class meaning.
+  test_dcs(0x01, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x02, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x03, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  //   Bit 4, if set to 1, indicates that bits 1 to 0 have a message class meaning.
+  test_dcs(0x10, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
+  test_dcs(0x11, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_ME_SPECIFIC);
+  test_dcs(0x12, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_SIM_SPECIFIC);
+  test_dcs(0x13, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_TE_SPECIFIC);
+
+  // Group 01xx
+  test_dcs(0x50, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
+
+  // Group 1000..1011: reserved
+  test_dcs(0x8F, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x9F, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0xAF, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0xBF, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+
+  // Group 1100: Message Waiting Indication Group: Discard Message
+  //   Bit 3 indicates Indication Sense:
+  test_dcs(0xC0, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: false, discard: true, msgCount: 0});
+  test_dcs(0xC8, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: true, discard: true, msgCount: -1});
+  //   Bit 2 is reserved, and set to 0:
+  test_dcs(0xCC, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: true, discard: true, msgCount: -1});
+
+  // Group 1101: Message Waiting Indication Group: Store Message
+  //   Bit 3 indicates Indication Sense:
+  test_dcs(0xD0, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: false, discard: false, msgCount: 0});
+  test_dcs(0xD8, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: true, discard: false, msgCount: -1});
+  //   Bit 2 is reserved, and set to 0:
+  test_dcs(0xDC, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: true, discard: false, msgCount: -1});
+
+  // Group 1110: Message Waiting Indication Group: Store Message, UCS2
+  //   Bit 3 indicates Indication Sense:
+  test_dcs(0xE0, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: false, discard: false, msgCount: 0});
+  test_dcs(0xE8, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: true, discard: false, msgCount: -1});
+  //   Bit 2 is reserved, and set to 0:
+  test_dcs(0xEC, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+           {active: true, discard: false, msgCount: -1});
+
+  // Group 1111
+  test_dcs(0xF0, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
+  test_dcs(0xF1, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_ME_SPECIFIC);
+  test_dcs(0xF2, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_SIM_SPECIFIC);
+  test_dcs(0xF3, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_TE_SPECIFIC);
+  test_dcs(0xF4, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
+  test_dcs(0xF5, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_ME_SPECIFIC);
+  test_dcs(0xF6, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_SIM_SPECIFIC);
+  test_dcs(0xF7, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_TE_SPECIFIC);
+  //   Bit 3 is reserved and should be set to 0, but if it doesn't we should
+  //   ignore it.
+  test_dcs(0xF8, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
+
+  run_next_test();
+});
+
+/**
  * Verify RadioInterfaceLayer#_countGsm7BitSeptets() and
  * GsmPDUHelper#writeStringAsSeptets() algorithm match each other.
  */
 add_test(function test_RadioInterfaceLayer__countGsm7BitSeptets() {
   let ril = newRadioInterfaceLayer();
 
   let worker = newWorker({
     postRILMessage: function fakePostRILMessage(data) {
--- a/dom/time/TimeManager.cpp
+++ b/dom/time/TimeManager.cpp
@@ -43,15 +43,15 @@ TimeManager::Set(const JS::Value& date, 
       return NS_ERROR_INVALID_ARG;
     }
   } else if (date.isNumber()) {
     dateMSec = date.toNumber();
   } else {
     return NS_ERROR_INVALID_ARG;
   }
 
-  hal::AdjustSystemClock(JS_DoubleToInt32(dateMSec - nowMSec));
+  hal::AdjustSystemClock(dateMSec - nowMSec);
   return NS_OK;
 }
 
 } // namespace time
 } // namespace dom
 } // namespace mozilla
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -580,17 +580,17 @@ ScriptExecutorRunnable::WorkerRun(JSCont
     NS_ASSERTION(!loadInfo.mChannel, "Should no longer have a channel!");
     NS_ASSERTION(loadInfo.mExecutionScheduled, "Should be scheduled!");
 
     if (!loadInfo.mExecutionResult) {
       return true;
     }
   }
 
-  JS::RootedObject global(aCx, JS_GetGlobalObject(aCx));
+  js::RootedObject global(aCx, JS_GetGlobalObject(aCx));
   NS_ASSERTION(global, "Must have a global by now!");
 
   JSPrincipals* principal = GetWorkerPrincipal();
   NS_ASSERTION(principal, "This should never be null!");
 
   for (uint32_t index = mFirstIndex; index <= mLastIndex; index++) {
     ScriptLoadInfo& loadInfo = loadInfos.ElementAt(index);
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3810,17 +3810,17 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
   }
 
   NS_ASSERTION(mTimer, "Must have a timer!");
   NS_ASSERTION(!mTimeouts.IsEmpty(), "Should have some work to do!");
 
   bool retval = true;
 
   AutoPtrComparator<TimeoutInfo> comparator = GetAutoPtrComparator(mTimeouts);
-  JS::RootedObject global(aCx, JS_GetGlobalObject(aCx));
+  js::RootedObject global(aCx, JS_GetGlobalObject(aCx));
   JSPrincipals* principal = GetWorkerPrincipal();
 
   // We want to make sure to run *something*, even if the timer fired a little
   // early. Fudge the value of now to at least include the first timeout.
   const TimeStamp now = NS_MAX(TimeStamp::Now(), mTimeouts[0]->mTargetTime);
 
   nsAutoTArray<TimeoutInfo*, 10> expiredTimeouts;
   for (uint32_t index = 0; index < mTimeouts.Length(); index++) {
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -196,17 +196,17 @@ nsresult EvaluateAdminConfigScript(const
     }
 
     JS_BeginRequest(autoconfig_cx);
     nsCOMPtr<nsIPrincipal> principal;
     nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(principal));
     JS::CompileOptions options(autoconfig_cx);
     options.setPrincipals(nsJSPrincipals::get(principal))
            .setFileAndLine(filename, 1);
-    JS::RootedObject glob(autoconfig_cx, autoconfig_glob);
+    js::RootedObject glob(autoconfig_cx, autoconfig_glob);
     ok = JS::Evaluate(autoconfig_cx, glob, options, js_buffer, length, nullptr);
     JS_EndRequest(autoconfig_cx);
 
     JS_MaybeGC(autoconfig_cx);
 
     JSContext *cx;
     cxstack->Pop(&cx);
     NS_ASSERTION(cx == autoconfig_cx, "AutoConfig JS contexts didn't match");
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -185,16 +185,18 @@ win32-ExtCreatePen-zero-size.patch: Don'
 d2d-repeating-gradients.patch: Minimize number of gradient stops added to handle repeating with path fills (bug 768775)
 
 xlib-glyph-clip-region.patch: bug 709477, addressed upstream by be1ff2f45fdbc69537e513834fcffa0435e63073
 
 gdi-RGB24-ARGB32.patch: bug 788794
 
 dwrite-font-printing.patch: bug 468568; don't substitute a GDI font for a DWrite font if the name tables aren't equal
 
+d2d-gradient-ensure-stops.patch: bug 792903, ensure we don't set num_stops to 0
+
 ==== pixman patches ====
 
 pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
 
 pixman-rename-and-endian.patch: include cairo-platform.h for renaming of external symbols and endian macros
 
 NOTE: we previously supported ARM assembler on MSVC, this has been removed because of the maintenance burden
 
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -1641,17 +1641,20 @@ static RefPtr<ID2D1Brush>
 	min_dist = MIN(_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_left, p1)),
 		       _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_right, p1)));
 	min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_left, p1)));
 	min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_right, p1)));
 
 	min_dist = MAX(-min_dist, 0);
 
 	// Repeats after gradient start.
-	int after_repeat = (int)ceil(max_dist / gradient_length);
+ 	// It's possible for max_dist and min_dist to both be zero, in which case
+ 	// we'll set num_stops to 0 and crash D2D. Let's just ensure after_repeat
+ 	// is at least 1.
+ 	int after_repeat = MAX((int)ceil(max_dist / gradient_length), 1);
 	int before_repeat = (int)ceil(min_dist / gradient_length);
 	num_stops *= (after_repeat + before_repeat);
 
 	p2.x = p1.x + u.x * after_repeat * gradient_length;
 	p2.y = p1.y + u.y * after_repeat * gradient_length;
 	p1.x = p1.x - u.x * before_repeat * gradient_length;
 	p1.y = p1.y - u.y * before_repeat * gradient_length;
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/d2d-gradient-ensure-stops.patch
@@ -0,0 +1,32 @@
+# HG changeset patch
+# User Robert O'Callahan <robert@ocallahan.org>
+# Date 1348618772 -43200
+# Node ID 55ccbc8d52e69b020f2ba493e92ad2e214388df0
+# Parent  e0d69219dd2b3b2826d186dc99c673b879409ea6
+Bug 792903. Prevent num_stops from being set to zero. r=bas
+
+diff --git a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
++++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+@@ -1641,17 +1641,20 @@ static RefPtr<ID2D1Brush>
+ 	min_dist = MIN(_cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_left, p1)),
+ 		       _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(top_right, p1)));
+ 	min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_left, p1)));
+ 	min_dist = MIN(min_dist, _cairo_d2d_dot_product(u, _cairo_d2d_subtract_point(bottom_right, p1)));
+ 
+ 	min_dist = MAX(-min_dist, 0);
+ 
+ 	// Repeats after gradient start.
+-	int after_repeat = (int)ceil(max_dist / gradient_length);
++ 	// It's possible for max_dist and min_dist to both be zero, in which case
++ 	// we'll set num_stops to 0 and crash D2D. Let's just ensure after_repeat
++ 	// is at least 1.
++ 	int after_repeat = MAX((int)ceil(max_dist / gradient_length), 1);
+ 	int before_repeat = (int)ceil(min_dist / gradient_length);
+ 	num_stops *= (after_repeat + before_repeat);
+ 
+ 	p2.x = p1.x + u.x * after_repeat * gradient_length;
+ 	p2.y = p1.y + u.y * after_repeat * gradient_length;
+ 	p1.x = p1.x - u.x * before_repeat * gradient_length;
+ 	p1.y = p1.y - u.y * before_repeat * gradient_length;
+ 
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -11,16 +11,20 @@ using namespace mozilla::gfx;
 
 gfxAlphaBoxBlur::gfxAlphaBoxBlur()
  : mBlur(nullptr)
 {
 }
 
 gfxAlphaBoxBlur::~gfxAlphaBoxBlur()
 {
+  // Drop references to mContext and mImageSurface before we delete mBlur,
+  // because the image surface points to data in mBlur.
+  mContext = nullptr;
+  mImageSurface = nullptr;
   delete mBlur;
 }
 
 gfxContext*
 gfxAlphaBoxBlur::Init(const gfxRect& aRect,
                       const gfxIntSize& aSpreadRadius,
                       const gfxIntSize& aBlurRadius,
                       const gfxRect* aDirtyRect,
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -202,17 +202,17 @@ gfxPlatformFontList::InitOtherFamilyName
 {
     mOtherFamilyNamesInitialized = true;
 
     Telemetry::AutoTimer<Telemetry::FONTLIST_INITOTHERFAMILYNAMES> timer;
     // iterate over all font families and read in other family names
     mFontFamilies.Enumerate(gfxPlatformFontList::InitOtherFamilyNamesProc, this);
 }
                                                          
-PLDHashOperator PR_CALLBACK
+PLDHashOperator
 gfxPlatformFontList::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
                                               nsRefPtr<gfxFontFamily>& aFamilyEntry,
                                               void* userArg)
 {
     gfxPlatformFontList *fc = static_cast<gfxPlatformFontList*>(userArg);
     aFamilyEntry->ReadOtherFamilyNames(fc);
     return PL_DHASH_NEXT;
 }
@@ -222,17 +222,17 @@ gfxPlatformFontList::InitFaceNameLists()
 {
     mFaceNamesInitialized = true;
 
     // iterate over all font families and read in other family names
     Telemetry::AutoTimer<Telemetry::FONTLIST_INITFACENAMELISTS> timer;
     mFontFamilies.Enumerate(gfxPlatformFontList::InitFaceNameListsProc, this);
 }
 
-PLDHashOperator PR_CALLBACK
+PLDHashOperator
 gfxPlatformFontList::InitFaceNameListsProc(nsStringHashKey::KeyType aKey,
                                            nsRefPtr<gfxFontFamily>& aFamilyEntry,
                                            void* userArg)
 {
     gfxPlatformFontList *fc = static_cast<gfxPlatformFontList*>(userArg);
     aFamilyEntry->ReadFaceNames(fc, fc->NeedFullnamePostscriptNames());
     return PL_DHASH_NEXT;
 }
@@ -303,17 +303,17 @@ struct FontListData {
                  nsTArray<nsString>& aListOfFonts) :
         mLangGroup(aLangGroup), mGenericFamily(aGenericFamily),
         mListOfFonts(aListOfFonts) {}
     nsIAtom *mLangGroup;
     const nsACString& mGenericFamily;
     nsTArray<nsString>& mListOfFonts;
 };
 
-PLDHashOperator PR_CALLBACK
+PLDHashOperator
 gfxPlatformFontList::HashEnumFuncForFamilies(nsStringHashKey::KeyType aKey,
                                              nsRefPtr<gfxFontFamily>& aFamilyEntry,
                                              void *aUserArg)
 {
     FontListData *data = static_cast<FontListData*>(aUserArg);
 
     // use the first variation for now.  This data should be the same
     // for all the variations and should probably be moved up to
@@ -353,19 +353,19 @@ gfxPlatformFontList::GetFontList(nsIAtom
     aListOfFonts.Compact();
 }
 
 struct FontFamilyListData {
     FontFamilyListData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray) 
         : mFamilyArray(aFamilyArray)
     {}
 
-    static PLDHashOperator PR_CALLBACK AppendFamily(nsStringHashKey::KeyType aKey,
-                                                    nsRefPtr<gfxFontFamily>& aFamilyEntry,
-                                                    void *aUserArg)
+    static PLDHashOperator AppendFamily(nsStringHashKey::KeyType aKey,
+                                        nsRefPtr<gfxFontFamily>& aFamilyEntry,
+                                        void *aUserArg)
     {
         FontFamilyListData *data = static_cast<FontFamilyListData*>(aUserArg);
         data->mFamilyArray.AppendElement(aFamilyEntry);
         return PL_DHASH_NEXT;
     }
 
     nsTArray<nsRefPtr<gfxFontFamily> >& mFamilyArray;
 };
@@ -456,17 +456,17 @@ gfxPlatformFontList::SystemFindFontForCh
 
     // track the script for which fallback occurred (incremented one make it
     // 1-based)
     Telemetry::Accumulate(Telemetry::SYSTEM_FONT_FALLBACK_SCRIPT, aRunScript + 1);
 
     return fontEntry;
 }
 
-PLDHashOperator PR_CALLBACK 
+PLDHashOperator 
 gfxPlatformFontList::FindFontForCharProc(nsStringHashKey::KeyType aKey, nsRefPtr<gfxFontFamily>& aFamilyEntry,
      void *userArg)
 {
     GlobalFontMatch *data = static_cast<GlobalFontMatch*>(userArg);
  
      // evaluate all fonts in this family for a match
      aFamilyEntry->FindFontForChar(data);
 
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -436,17 +436,17 @@ UnregisterSystemTimeChangeObserver(Syste
 
 void
 NotifySystemTimeChange(const hal::SystemTimeChange& aReason)
 {
   sSystemTimeObservers.BroadcastInformation(aReason);
 }
  
 void 
-AdjustSystemClock(int32_t aDeltaMilliseconds)
+AdjustSystemClock(int64_t aDeltaMilliseconds)
 {
   AssertMainThread();
   PROXY_IF_SANDBOXED(AdjustSystemClock(aDeltaMilliseconds));
 }
 
 void 
 SetTimezone(const nsCString& aTimezoneSpec)
 {
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -237,17 +237,17 @@ void GetCurrentNetworkInformation(hal::N
  * @param aNetworkInfo The new network information.
  */
 void NotifyNetworkChange(const hal::NetworkInformation& aNetworkInfo);
 
 /**
  * Adjusting system clock.
  * @param aDeltaMilliseconds The difference compared with current system clock.
  */
-void AdjustSystemClock(int32_t aDeltaMilliseconds);
+void AdjustSystemClock(int64_t aDeltaMilliseconds);
 
 /**
  * Set timezone
  * @param aTimezoneSpec The definition can be found in 
  * http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  */
 void SetTimezone(const nsCString& aTimezoneSpec);
 
--- a/hal/fallback/FallbackTime.cpp
+++ b/hal/fallback/FallbackTime.cpp
@@ -6,17 +6,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Hal.h"
 
 namespace mozilla {
 namespace hal_impl {
 
 void 
-AdjustSystemClock(int32_t aDeltaMilliseconds)
+AdjustSystemClock(int64_t aDeltaMilliseconds)
 {}
 
 void
 SetTimezone(const nsCString& aTimezoneSpec)
 {}
 
 nsCString
 GetTimezone()
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -346,18 +346,18 @@ GetCurrentBatteryInformation(hal::Batter
     done = true;
   }
 
   if (!done) {
     // toro devices support
     chargingFile = fopen("/sys/class/power_supply/battery/status", "r");
     if (chargingFile) {
       char status[16];
-      fscanf(chargingFile, "%s", &status);
-      if (!strcmp(status, "Charging") || !strcmp(status, "Full")) {
+      char *str = fgets(status, sizeof(status), chargingFile);
+      if (str && (!strcmp(str, "Charging\n") || !strcmp(str, "Full\n"))) {
         // no way here to know if we're charging from USB or AC.
         chargingSrc = BATTERY_CHARGING_USB;
       } else {
         chargingSrc = BATTERY_NOT_CHARGING;
       }
       fclose(chargingFile);
       done = true;
     }
@@ -610,29 +610,29 @@ GetLight(hal::LightType light, hal::Ligh
  */
 static int
 sys_clock_settime(clockid_t clk_id, const struct timespec *tp)
 {
   return syscall(__NR_clock_settime, clk_id, tp);
 }
 
 void
-AdjustSystemClock(int32_t aDeltaMilliseconds)
+AdjustSystemClock(int64_t aDeltaMilliseconds)
 {
   if (aDeltaMilliseconds == 0) {
     return;
   }
 
   struct timespec now;
 
   // Preventing context switch before setting system clock
   sched_yield();
   clock_gettime(CLOCK_REALTIME, &now);
-  now.tv_sec += aDeltaMilliseconds/1000;
-  now.tv_nsec += (aDeltaMilliseconds%1000)*NsecPerMsec;
+  now.tv_sec += aDeltaMilliseconds / 1000;
+  now.tv_nsec += (aDeltaMilliseconds % 1000) * NsecPerMsec;
   if (now.tv_nsec >= NsecPerSec)
   {
     now.tv_sec += 1;
     now.tv_nsec -= NsecPerSec;
   }
 
   if (now.tv_nsec < 0)
   {
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -126,17 +126,17 @@ parent:
     SetScreenEnabled(bool enabled);
 
     sync GetCpuSleepAllowed() returns (bool allowed);
     SetCpuSleepAllowed(bool allowed);
 
     sync GetScreenBrightness() returns (double brightness);
     SetScreenBrightness(double brightness);
 
-    AdjustSystemClock(int32_t aDeltaMilliseconds);
+    AdjustSystemClock(int64_t aDeltaMilliseconds);
     SetTimezone(nsCString aTimezoneSpec);
     sync GetTimezone()
       returns (nsCString aTimezoneSpec);
     EnableSystemTimeChangeNotifications();
     DisableSystemTimeChangeNotifications();
 
     sync SetLight(LightType light, LightConfiguration aConfig)
       returns (bool status);
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -179,17 +179,17 @@ bool
 GetLight(hal::LightType light, hal::LightConfiguration* aConfig)
 {
   bool status;
   Hal()->SendGetLight(light, aConfig, &status);
   return status;
 }
 
 void 
-AdjustSystemClock(int32_t aDeltaMilliseconds)
+AdjustSystemClock(int64_t aDeltaMilliseconds)
 {
   Hal()->SendAdjustSystemClock(aDeltaMilliseconds);
 }
 
 void
 SetTimezone(const nsCString& aTimezoneSpec)
 {
   Hal()->SendSetTimezone(nsCString(aTimezoneSpec));
@@ -587,17 +587,17 @@ public:
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
     *status = hal::GetLight(aLight, aConfig);
     return true;
   }
 
   virtual bool
-  RecvAdjustSystemClock(const int32_t &aDeltaMilliseconds) MOZ_OVERRIDE
+  RecvAdjustSystemClock(const int64_t &aDeltaMilliseconds) MOZ_OVERRIDE
   {
     if (!AssertAppProcessPermission(this, "time")) {
       return false;
     }
     hal::AdjustSystemClock(aDeltaMilliseconds);
     return true;
   }
 
--- a/image/src/Makefile.in
+++ b/image/src/Makefile.in
@@ -38,17 +38,17 @@ LOCAL_INCLUDES += -I$(topsrcdir)/image/d
 
 # Because SVGDocumentWrapper.cpp includes "nsSVGSVGElement.h"
 LOCAL_INCLUDES += \
 			-I$(topsrcdir)/content/svg/content/src \
 			-I$(topsrcdir)/content/base/src \
 			$(NULL)
 
 # Because VectorImage.cpp includes nsSVGUtils.h and nsSVGEffects.h
-LOCAL_INCLUDES += -I$(topsrcdir)/layout/svg/base/src
+LOCAL_INCLUDES += -I$(topsrcdir)/layout/svg
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 # Because imgFrame.cpp includes "cairo.h"
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS)
 
 
--- a/js/ipc/ObjectWrapperChild.cpp
+++ b/js/ipc/ObjectWrapperChild.cpp
@@ -417,24 +417,24 @@ ObjectWrapperChild::AnswerNewEnumerateIn
     AutoCheckOperation aco(this, status);
 
     JSClass* clasp = const_cast<JSClass*>(&sCPOW_NewEnumerateState_JSClass);
     JSObject* state = JS_NewObjectWithGivenProto(cx, clasp, NULL, NULL);
     if (!state)
         return false;
     AutoObjectRooter tvr(cx, state);
 
-    for (JSObject* proto = mObj;
-         proto;
-         proto = JS_GetPrototype(proto))
-    {
+    for (JSObject* proto = mObj; proto; ) {
         AutoIdArray ids(cx, JS_Enumerate(cx, proto));
         for (size_t i = 0; i < ids.length(); ++i)
             JS_DefinePropertyById(cx, state, ids[i], JSVAL_VOID,
                                   NULL, NULL, JSPROP_ENUMERATE | JSPROP_SHARED);
+
+        if (!JS_GetPrototype(cx, proto, &proto))
+            return false;
     }
 
     InfallibleTArray<nsString>* strIds;
     {
         AutoIdArray ids(cx, JS_Enumerate(cx, state));
         if (!ids)
             return false;
         strIds = new InfallibleTArray<nsString>(ids.length());
--- a/js/ipc/ObjectWrapperParent.cpp
+++ b/js/ipc/ObjectWrapperParent.cpp
@@ -179,22 +179,23 @@ ObjectWrapperParent::GetJSObject(JSConte
             JS_SetPrivate(mObj, (void*)this);
             JS_SetReservedSlot(mObj, sFlagsSlot, JSVAL_ZERO);
         }
     }
     return mObj;
 }
 
 static ObjectWrapperParent*
-Unwrap(JSObject* obj)
+Unwrap(JSContext* cx, JSObject* obj)
 {
-    while (js::GetObjectClass(obj) != &ObjectWrapperParent::sCPOW_JSClass)
-        if (!(obj = js::GetObjectProto(obj)))
+    while (js::GetObjectClass(obj) != &ObjectWrapperParent::sCPOW_JSClass) {
+        if (!js::GetObjectProto(cx, obj, &obj) || !obj)
             return NULL;
-    
+    }
+
     ObjectWrapperParent* self =
         static_cast<ObjectWrapperParent*>(JS_GetPrivate(obj));
 
     NS_ASSERTION(!self || self->GetJSObjectOrNull() == obj,
                  "Wrapper and wrapped object disagree?");
     
     return self;
 }
@@ -213,17 +214,17 @@ ObjectWrapperParent::jsval_to_JSVariant(
         // fall through
     case JSTYPE_FUNCTION:
         // CPOWs can fool JS_TypeOfValue into returning JSTYPE_FUNCTION
         // because they have a call hook, but CPOWs are really objects, so
         // fall through to the JSTYPE_OBJECT case:
     case JSTYPE_OBJECT:
         {
             PObjectWrapperParent* powp;
-            if (!JSObject_to_PObjectWrapperParent(JSVAL_TO_OBJECT(from), &powp))
+            if (!JSObject_to_PObjectWrapperParent(cx, JSVAL_TO_OBJECT(from), &powp))
                 return with_error(cx, false, "Cannot pass parent-created object to child");
             *to = powp;
         }
         return true;
     case JSTYPE_STRING:
         {
             nsDependentJSString depStr;
             if (!depStr.init(cx, from))
@@ -277,23 +278,23 @@ ObjectWrapperParent::jsval_from_JSVarian
         return true;
     default:
         return false;
     }
 }
 
 /*static*/ bool
 ObjectWrapperParent::
-JSObject_to_PObjectWrapperParent(JSObject* from, PObjectWrapperParent** to)
+JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from, PObjectWrapperParent** to)
 {
     if (!from) {
         *to = NULL;
         return true;
     }
-    ObjectWrapperParent* owp = Unwrap(from);
+    ObjectWrapperParent* owp = Unwrap(cx, from);
     if (!owp)
         return false;
     *to = owp;
     return true;
 }
 
 /*static*/ bool
 ObjectWrapperParent::
@@ -310,17 +311,17 @@ JSObject_from_PObjectWrapperParent(JSCon
 }
 
 /*static*/ bool
 ObjectWrapperParent::
 jsval_from_PObjectWrapperParent(JSContext* cx,
                                 const PObjectWrapperParent* from,
                                 jsval* to)
 {
-    JS::RootedObject obj(cx);
+    js::RootedObject obj(cx);
     if (!JSObject_from_PObjectWrapperParent(cx, from, &obj))
         return false;
     *to = OBJECT_TO_JSVAL(obj);
     return true;
 }
     
 static bool
 jsid_from_int(JSContext* cx, int from, jsid* to)
@@ -355,17 +356,17 @@ jsval_to_nsString(JSContext* cx, jsid fr
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_AddProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_AddProperty");
 
     if (AutoResolveFlag::IsSet(obj))
         return JS_TRUE;
 
     AutoCheckOperation aco(cx, self);
 
@@ -382,17 +383,17 @@ ObjectWrapperParent::CPOW_AddProperty(JS
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_GetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_GetProperty");
 
     AutoCheckOperation aco(cx, self);
 
     nsString in_id;
 
     if (!jsval_to_nsString(cx, id, &in_id))
@@ -409,17 +410,17 @@ ObjectWrapperParent::CPOW_GetProperty(JS
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, 
                                       JSBool strict, JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_SetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_SetProperty");
 
     AutoCheckOperation aco(cx, self);
 
     nsString in_id;
     JSVariant in_v;
 
@@ -438,17 +439,17 @@ ObjectWrapperParent::CPOW_SetProperty(JS
     
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_DelProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_DelProperty");
 
     AutoCheckOperation aco(cx, self);
 
     nsString in_id;
 
     if (!jsval_to_nsString(cx, id, &in_id))
@@ -519,17 +520,17 @@ ObjectWrapperParent::NewEnumerateDestroy
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_NewEnumerate(JSContext *cx, JSHandleObject obj,
                                        JSIterateOp enum_op, jsval *statep,
                                        jsid *idp)
 {
     CPOW_LOG(("Calling CPOW_NewEnumerate..."));
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewEnumerate");
 
     switch (enum_op) {
     case JSENUMERATE_INIT:
     case JSENUMERATE_INIT_ALL:
         self->Manager()->RequestRunToCompletion();
         return self->NewEnumerateInit(cx, statep, idp);
@@ -545,17 +546,17 @@ ObjectWrapperParent::CPOW_NewEnumerate(J
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                      unsigned flags, JSMutableHandleObject objp)
 {
     CPOW_LOG(("Calling CPOW_NewResolve (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewResolve");
 
     AutoCheckOperation aco(cx, self);
 
     nsString in_id;
 
     if (!jsval_to_nsString(cx, id, &in_id))
@@ -567,68 +568,70 @@ ObjectWrapperParent::CPOW_NewResolve(JSC
         !self->CallNewResolve(in_id, flags,
                               aco.StatusPtr(), &out_pobj) ||
         !aco.Ok() ||
         !JSObject_from_PObjectWrapperParent(cx, out_pobj, objp))
         return JS_FALSE;
 
     if (objp) {
         AutoResolveFlag arf(objp);
-        JS::RootedObject obj2(cx, objp);
+        js::RootedObject obj2(cx, objp);
         JS_DefinePropertyById(cx, obj2, id, JSVAL_VOID, NULL, NULL,
                               JSPROP_ENUMERATE);
     }
     return JS_TRUE;
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type,
                                   JSMutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_Convert (to %s)...",
               JS_GetTypeName(cx, type)));
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Convert");
 
     vp.set(OBJECT_TO_JSVAL(obj));
 
     return JS_TRUE;
 }
 
 /*static*/ void
 ObjectWrapperParent::CPOW_Finalize(js::FreeOp* fop, JSObject* obj)
 {
     CPOW_LOG(("Calling CPOW_Finalize..."));
-    
-    ObjectWrapperParent* self = Unwrap(obj);
+
+    MOZ_ASSERT(js::GetObjectClass(obj) == &ObjectWrapperParent::sCPOW_JSClass);
+    ObjectWrapperParent* self =
+        static_cast<ObjectWrapperParent*>(JS_GetPrivate(obj));
     if (self) {
         self->mObj = NULL;
         unused << ObjectWrapperParent::Send__delete__(self);
     }
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_Call(JSContext* cx, unsigned argc, jsval* vp)
 {
     CPOW_LOG(("Calling CPOW_Call..."));
 
     JSObject* thisobj = JS_THIS_OBJECT(cx, vp);
     if (!thisobj)
         return JS_FALSE;
 
     ObjectWrapperParent* function =
-        Unwrap(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
+        Unwrap(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
     if (!function)
         return with_error(cx, JS_FALSE, "Could not unwrap CPOW function");
 
     AutoCheckOperation aco(cx, function);
 
-    ObjectWrapperParent* receiver = Unwrap(thisobj);
+    ObjectWrapperParent* receiver = Unwrap(cx, thisobj);
     if (!receiver) {
         // Substitute child global for parent global object.
         // TODO First make sure we're really replacing the global object?
         ContextWrapperParent* manager =
             static_cast<ContextWrapperParent*>(function->Manager());
         receiver = manager->GetGlobalObjectWrapper();
     }
 
@@ -647,17 +650,17 @@ ObjectWrapperParent::CPOW_Call(JSContext
             jsval_from_JSVariant(cx, out_rval, vp));
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_Construct(JSContext* cx, unsigned argc, jsval* vp)
 {
     CPOW_LOG(("Calling CPOW_Construct..."));
     
-    ObjectWrapperParent* constructor = Unwrap(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
+    ObjectWrapperParent* constructor = Unwrap(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
     if (!constructor)
         return with_error(cx, JS_FALSE, "Could not unwrap CPOW constructor function");
 
     AutoCheckOperation aco(cx, constructor);
 
     InfallibleTArray<JSVariant> in_argv(argc);
     jsval* argv = JS_ARGV(cx, vp);
     for (unsigned i = 0; i < argc; i++)
@@ -675,17 +678,17 @@ ObjectWrapperParent::CPOW_Construct(JSCo
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue v,
                                       JSBool *bp)
 {
     CPOW_LOG(("Calling CPOW_HasInstance..."));
 
     *bp = JS_FALSE;
 
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_HasInstance");
 
     AutoCheckOperation aco(cx, self);
 
     JSVariant in_v;
 
     if (!jsval_to_JSVariant(cx, v, &in_v))
@@ -700,23 +703,23 @@ ObjectWrapperParent::CPOW_HasInstance(JS
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_Equality(JSContext *cx, JSHandleObject obj, JSHandleValue v,
                                    JSBool *bp)
 {
     CPOW_LOG(("Calling CPOW_Equality..."));
 
     *bp = JS_FALSE;
     
-    ObjectWrapperParent* self = Unwrap(obj);
+    ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Equality");
 
     if (JSVAL_IS_PRIMITIVE(v))
         return JS_TRUE;
 
-    ObjectWrapperParent* other = Unwrap(JSVAL_TO_OBJECT(v));
+    ObjectWrapperParent* other = Unwrap(cx, JSVAL_TO_OBJECT(v));
     if (!other)
         return JS_TRUE;
 
     *bp = (self == other);
     
     return JS_TRUE;
 }
--- a/js/ipc/ObjectWrapperParent.h
+++ b/js/ipc/ObjectWrapperParent.h
@@ -99,17 +99,17 @@ private:
 
     static JSBool
     CPOW_Equality(JSContext *cx, JSHandleObject obj, JSHandleValue v, JSBool *bp);
 
     static bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
     static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
                                      jsval* to);
     static bool
-    JSObject_to_PObjectWrapperParent(JSObject* from, PObjectWrapperParent** to);
+    JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from, PObjectWrapperParent** to);
     static bool
     JSObject_from_PObjectWrapperParent(JSContext* cx,
                                        const PObjectWrapperParent* from,
                                        JSMutableHandleObject to);
     static bool
     jsval_from_PObjectWrapperParent(JSContext* cx,
                                     const PObjectWrapperParent* from,
                                     jsval* to);
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -609,26 +609,28 @@ jsd_GetValueFunction(JSDContext* jsdc, J
     JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
 
     return fun;
 }
 
 JSDValue*
 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
 {
+    JSContext* cx = jsdc->dumbContext;
     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROTO)))
     {
         JSObject* obj;
         JSObject* proto;
         JS_ASSERT(!jsdval->proto);
         SET_BIT_FLAG(jsdval->flags, GOT_PROTO);
         if(JSVAL_IS_PRIMITIVE(jsdval->val))
             return NULL;
         obj = JSVAL_TO_OBJECT(jsdval->val);
-        proto = JS_GetPrototype(obj);
+        if(!JS_GetPrototype(cx, obj, &proto))
+            return NULL;
         if(!proto)
             return NULL;
         jsdval->proto = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(proto));
     }
     if(jsdval->proto)
         jsdval->proto->nref++;
     return jsdval->proto;
 }
@@ -660,28 +662,30 @@ jsd_GetValueParent(JSDContext* jsdc, JSD
         jsdval->parent->nref++;
     return jsdval->parent;
 }
 
 JSDValue*
 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSCompartment* oldCompartment = NULL;
+    JSContext* cx = jsdc->dumbContext;
 
     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
     {
         JSObject* obj;
         JSObject* proto;
         JSObject* ctor;
         JS_ASSERT(!jsdval->ctor);
         SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
         if(JSVAL_IS_PRIMITIVE(jsdval->val))
             return NULL;
         obj = JSVAL_TO_OBJECT(jsdval->val);
-        proto = JS_GetPrototype(obj);
+        if(!JS_GetPrototype(cx, obj, &proto))
+            return NULL;
         if(!proto)
             return NULL;
         JS_BeginRequest(jsdc->dumbContext);
         oldCompartment = JS_EnterCompartment(jsdc->dumbContext, obj);
         ctor = JS_GetConstructor(jsdc->dumbContext,proto);
         JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
         JS_EndRequest(jsdc->dumbContext);
         if(!ctor)
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -712,17 +712,19 @@ static JSObject*
 InitCTypeClass(JSContext* cx, HandleObject parent)
 {
   JSFunction *fun = JS_DefineFunction(cx, parent, "CType", ConstructAbstract, 0,
                                       CTYPESCTOR_FLAGS);
   if (!fun)
     return NULL;
 
   RootedObject ctor(cx, JS_GetFunctionObject(fun));
-  RootedObject fnproto(cx, JS_GetPrototype(ctor));
+  RootedObject fnproto(cx);
+  if (!JS_GetPrototype(cx, ctor, fnproto.address()))
+    return NULL;
   JS_ASSERT(ctor);
   JS_ASSERT(fnproto);
 
   // Set up ctypes.CType.prototype.
   RootedObject prototype(cx, JS_NewObject(cx, &sCTypeProtoClass, fnproto, parent));
   if (!prototype)
     return NULL;
 
@@ -1923,21 +1925,25 @@ ConvertToJS(JSContext* cx,
 #define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType)                           \
   case TYPE_##name: {                                                          \
     /* Return an Int64 or UInt64 object - do not convert to a JS number. */    \
     uint64_t value;                                                            \
     RootedObject proto(cx);                                                    \
     if (!numeric_limits<type>::is_signed) {                                    \
       value = *static_cast<type*>(data);                                       \
       /* Get ctypes.UInt64.prototype from ctypes.CType.prototype. */           \
-      proto = CType::GetProtoFromType(typeObj, SLOT_UINT64PROTO);              \
+      proto = CType::GetProtoFromType(cx, typeObj, SLOT_UINT64PROTO);          \
+      if (!proto)                                                              \
+        return false;                                                          \
     } else {                                                                   \
       value = int64_t(*static_cast<type*>(data));                              \
       /* Get ctypes.Int64.prototype from ctypes.CType.prototype. */            \
-      proto = CType::GetProtoFromType(typeObj, SLOT_INT64PROTO);               \
+      proto = CType::GetProtoFromType(cx, typeObj, SLOT_INT64PROTO);     \
+      if (!proto)                                                              \
+        return false;                                                          \
     }                                                                          \
                                                                                \
     JSObject* obj = Int64Base::Construct(cx, proto, value,                     \
       !numeric_limits<type>::is_signed);                                       \
     if (!obj)                                                                  \
       return false;                                                            \
     *result = OBJECT_TO_JSVAL(obj);                                            \
     break;                                                                     \
@@ -3352,27 +3358,30 @@ CType::GetProtoFromCtor(JSObject* obj, C
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get the desired prototype.
   jsval result = JS_GetReservedSlot(proto, slot);
   return JSVAL_TO_OBJECT(result);
 }
 
 JSObject*
-CType::GetProtoFromType(JSObject* obj, CTypeProtoSlot slot)
+CType::GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
 {
   JS_ASSERT(IsCType(obj));
 
   // Get the prototype of the type object.
-  JSObject* proto = JS_GetPrototype(obj);
+  JSObject* proto;
+  if (!JS_GetPrototype(cx, obj, &proto))
+    return NULL;
   JS_ASSERT(proto);
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get the requested ctypes.{Pointer,Array,Struct,Function}Type.prototype.
   jsval result = JS_GetReservedSlot(proto, slot);
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(result));
   return JSVAL_TO_OBJECT(result);
 }
 
 JSBool
 CType::PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!(CType::IsCType(obj) || CType::IsCTypeProto(obj))) {
     JS_ReportError(cx, "not a CType or CTypeProto");
@@ -3533,39 +3542,44 @@ CType::HasInstance(JSContext* cx, JSHand
   JS_ASSERT(prototype);
   JS_ASSERT(CData::IsCDataProto(prototype));
 
   *bp = JS_FALSE;
   if (JSVAL_IS_PRIMITIVE(v))
     return JS_TRUE;
 
   JSObject* proto = JSVAL_TO_OBJECT(v);
-  while ((proto = JS_GetPrototype(proto))) {
+  for (;;) {
+    if (!JS_GetPrototype(cx, proto, &proto))
+      return JS_FALSE;
+    if (!proto)
+      break;
     if (proto == prototype) {
       *bp = JS_TRUE;
       break;
     }
   }
   return JS_TRUE;
 }
 
 static JSObject*
 CType::GetGlobalCTypes(JSContext* cx, JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(obj));
 
-  JSObject *objTypeProto = JS_GetPrototype(obj);
-  if (!objTypeProto) {
-  }
+  JSObject *objTypeProto;
+  if (!JS_GetPrototype(cx, obj, &objTypeProto))
+    return NULL;
   JS_ASSERT(objTypeProto);
   JS_ASSERT(CType::IsCTypeProto(objTypeProto));
 
   jsval valCTypes = JS_GetReservedSlot(objTypeProto, SLOT_CTYPES);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCTypes));
 
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCTypes));
   return JSVAL_TO_OBJECT(valCTypes);
 }
 
 /*******************************************************************************
 ** ABI implementation
 *******************************************************************************/
 
 bool
@@ -3648,18 +3662,22 @@ PointerType::CreateInternal(JSContext* c
   jsval slot = JS_GetReservedSlot(baseType, SLOT_PTR);
   if (!JSVAL_IS_VOID(slot))
     return JSVAL_TO_OBJECT(slot);
 
   // Get ctypes.PointerType.prototype and the common prototype for CData objects
   // of this type, or ctypes.FunctionType.prototype for function pointers.
   CTypeProtoSlot slotId = CType::GetTypeCode(baseType) == TYPE_function ?
     SLOT_FUNCTIONDATAPROTO : SLOT_POINTERDATAPROTO;
-  RootedObject dataProto(cx, CType::GetProtoFromType(baseType, slotId));
-  RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_POINTERPROTO));
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, baseType, slotId));
+  if (!dataProto)
+    return NULL;
+  RootedObject typeProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_POINTERPROTO));
+  if (!typeProto)
+    return NULL;
 
   // Create a new CType object with the common properties and slots.
   JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_pointer,
                         NULL, INT_TO_JSVAL(sizeof(void*)),
                         INT_TO_JSVAL(ffi_type_pointer.alignment),
                         &ffi_type_pointer);
   if (!typeObj)
     return NULL;
@@ -3966,18 +3984,22 @@ ArrayType::Create(JSContext* cx, unsigne
 JSObject*
 ArrayType::CreateInternal(JSContext* cx,
                           HandleObject baseType,
                           size_t length,
                           bool lengthDefined)
 {
   // Get ctypes.ArrayType.prototype and the common prototype for CData objects
   // of this type, from ctypes.CType.prototype.
-  RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYPROTO));
-  RootedObject dataProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYDATAPROTO));
+  RootedObject typeProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_ARRAYPROTO));
+  if (!typeProto)
+    return NULL;
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, baseType, SLOT_ARRAYDATAPROTO));
+  if (!dataProto)
+    return NULL;
 
   // Determine the size of the array from the base type, if possible.
   // The size of the base type must be defined.
   // If our length is undefined, both our size and length will be undefined.
   size_t baseSize;
   if (!CType::GetSafeSize(baseType, &baseSize)) {
     JS_ReportError(cx, "base size must be defined");
     return NULL;
@@ -4510,17 +4532,19 @@ StructType::DefineInternal(JSContext* cx
   RootedObject typeObj(cx, typeObj_);
   RootedObject fieldsObj(cx, fieldsObj_);
 
   uint32_t len;
   ASSERT_OK(JS_GetArrayLength(cx, fieldsObj, &len));
 
   // Get the common prototype for CData objects of this type from
   // ctypes.CType.prototype.
-  RootedObject dataProto(cx, CType::GetProtoFromType(typeObj, SLOT_STRUCTDATAPROTO));
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, typeObj, SLOT_STRUCTDATAPROTO));
+  if (!dataProto)
+    return JS_FALSE;
 
   // Set up the 'prototype' and 'prototype.constructor' properties.
   // The prototype will reflect the struct fields as properties on CData objects
   // created from this type.
   RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, dataProto, NULL));
   if (!prototype)
     return JS_FALSE;
 
@@ -5367,20 +5391,24 @@ FunctionType::CreateInternal(JSContext* 
 {
   // Determine and check the types, and prepare the function CIF.
   AutoPtr<FunctionInfo> fninfo(NewFunctionInfo(cx, abi, rtype, argtypes, arglen));
   if (!fninfo)
     return NULL;
 
   // Get ctypes.FunctionType.prototype and the common prototype for CData objects
   // of this type, from ctypes.CType.prototype.
-  RootedObject typeProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
+  RootedObject typeProto(cx, CType::GetProtoFromType(cx, fninfo->mReturnType,
                                                      SLOT_FUNCTIONPROTO));
-  RootedObject dataProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
+  if (!typeProto)
+    return NULL;
+  RootedObject dataProto(cx, CType::GetProtoFromType(cx, fninfo->mReturnType,
                                                      SLOT_FUNCTIONDATAPROTO));
+  if (!dataProto)
+    return NULL;
 
   // Create a new CType object with the common properties and slots.
   JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_function,
                         NULL, JSVAL_VOID, JSVAL_VOID, NULL);
   if (!typeObj)
     return NULL;
   js::AutoObjectRooter root(cx, typeObj);
 
@@ -5585,16 +5613,18 @@ FunctionType::Call(JSContext* cx,
   lastErrorStatus = GetLastError();
   SetLastError(savedLastError);
 #endif // defined(XP_WIN)
 
   errno = savedErrno;
 
   // Store the error value for later consultation with |ctypes.getStatus|
   JSObject *objCTypes = CType::GetGlobalCTypes(cx, typeObj);
+  if (!objCTypes)
+    return false;
 
   JS_SetReservedSlot(objCTypes, SLOT_ERRNO, INT_TO_JSVAL(errnoStatus));
 #if defined(XP_WIN)
   JS_SetReservedSlot(objCTypes, SLOT_LASTERROR, INT_TO_JSVAL(lastErrorStatus));
 #endif // defined(XP_WIN)
 
   // Small integer types get returned as a word-sized ffi_arg. Coerce it back
   // into the correct size for ConvertToJS.
@@ -5735,17 +5765,19 @@ CClosure::Create(JSContext* cx,
   AutoPtr<ClosureInfo> cinfo(cx->new_<ClosureInfo>(JS_GetRuntime(cx)));
   if (!cinfo) {
     JS_ReportOutOfMemory(cx);
     return NULL;
   }
 
   // Get the prototype of the FunctionType object, of class CTypeProto,
   // which stores our JSContext for use with the closure.
-  JSObject* proto = JS_GetPrototype(typeObj);
+  JSObject* proto;
+  if (!JS_GetPrototype(cx, typeObj, &proto))
+    return NULL;
   JS_ASSERT(proto);
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get a JSContext for use with the closure.
   jsval slot = JS_GetReservedSlot(proto, SLOT_CLOSURECX);
   if (!JSVAL_IS_VOID(slot)) {
     // Use the existing JSContext.
     cinfo->cx = static_cast<JSContext*>(JSVAL_TO_PRIVATE(slot));
@@ -6901,16 +6933,18 @@ CDataFinalizer::Methods::Dispose(JSConte
     JS_ReportError(cx, "dispose called on an empty CDataFinalizer.");
     return JS_FALSE;
   }
 
   jsval valType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_VALTYPE);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(valType));
 
   JSObject *objCTypes = CType::GetGlobalCTypes(cx, JSVAL_TO_OBJECT(valType));
+  if (!objCTypes)
+    return JS_FALSE;
 
   jsval valCodePtrType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_CODETYPE);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCodePtrType));
   JSObject *objCodePtrType = JSVAL_TO_OBJECT(valCodePtrType);
 
   JSObject *objCodeType = PointerType::GetBaseType(objCodePtrType);
   JS_ASSERT(objCodeType);
   JS_ASSERT(CType::GetTypeCode(objCodeType) == TYPE_function);
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -423,17 +423,17 @@ namespace CType {
   bool TypesEqual(JSObject* t1, JSObject* t2);
   size_t GetSize(JSObject* obj);
   bool GetSafeSize(JSObject* obj, size_t* result);
   bool IsSizeDefined(JSObject* obj);
   size_t GetAlignment(JSObject* obj);
   ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
   JSString* GetName(JSContext* cx, JSHandleObject obj);
   JSObject* GetProtoFromCtor(JSObject* obj, CTypeProtoSlot slot);
-  JSObject* GetProtoFromType(JSObject* obj, CTypeProtoSlot slot);
+  JSObject* GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
   JSCTypesCallbacks* GetCallbacksFromType(JSObject* obj);
 }
 
 namespace PointerType {
   JSObject* CreateInternal(JSContext* cx, JSHandleObject baseType);
 
   JSObject* GetBaseType(JSObject* obj);
 }
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -840,27 +840,27 @@ class TokenStream
         while (--n >= 0)
             getChar();
     }
 
     void updateLineInfoForEOL();
     void updateFlagsForEOL();
 
     Token               tokens[ntokens];/* circular token buffer */
-    JS::SkipRoot        tokensRoot;     /* prevent overwriting of token buffer */
+    js::SkipRoot        tokensRoot;     /* prevent overwriting of token buffer */
     unsigned            cursor;         /* index of last parsed token */
     unsigned            lookahead;      /* count of lookahead tokens */
     unsigned            lineno;         /* current line number */
     unsigned            flags;          /* flags -- see above */
     const jschar        *linebase;      /* start of current line;  points into userbuf */
     const jschar        *prevLinebase;  /* start of previous line;  NULL if on the first line */
-    JS::SkipRoot        linebaseRoot;
-    JS::SkipRoot        prevLinebaseRoot;
+    js::SkipRoot        linebaseRoot;
+    js::SkipRoot        prevLinebaseRoot;
     TokenBuf            userbuf;        /* user input buffer */
-    JS::SkipRoot        userbufRoot;
+    js::SkipRoot        userbufRoot;
     const char          *filename;      /* input filename or null */
     jschar              *sourceMap;     /* source map's filename or null */
     void                *listenerTSData;/* listener data for this TokenStream */
     CharBuffer          tokenbuf;       /* current token string buffer */
     int8_t              oneCharTokens[128];  /* table of one-char tokens */
     bool                maybeEOL[256];       /* probabilistic EOL lookup table */
     bool                maybeStrSpecial[256];/* speeds up string scanning */
     JSVersion           version;        /* (i.e. to identify keywords) */
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -884,17 +884,17 @@ ScanTypeObject(GCMarker *gcmarker, types
         unsigned count = type->getPropertyCount();
         for (unsigned i = 0; i < count; i++) {
             types::Property *prop = type->getProperty(i);
             if (prop && JSID_IS_STRING(prop->id))
                 PushMarkStack(gcmarker, JSID_TO_STRING(prop->id));
         }
     }
 
-    if (type->proto)
+    if (TaggedProto(type->proto).isObject())
         PushMarkStack(gcmarker, type->proto);
 
     if (type->singleton && !type->lazy())
         PushMarkStack(gcmarker, type->singleton);
 
     if (type->newScript) {
         PushMarkStack(gcmarker, type->newScript->fun);
         PushMarkStack(gcmarker, type->newScript->shape);
@@ -909,17 +909,17 @@ MarkChildren(JSTracer *trc, types::TypeO
 {
     unsigned count = type->getPropertyCount();
     for (unsigned i = 0; i < count; i++) {
         types::Property *prop = type->getProperty(i);
         if (prop)
             MarkId(trc, &prop->id, "type_prop");
     }
 
-    if (type->proto)
+    if (TaggedProto(type->proto).isObject())
         MarkObject(trc, &type->proto, "type_proto");
 
     if (type->singleton && !type->lazy())
         MarkObject(trc, &type->singleton, "type_singleton");
 
     if (type->newScript) {
         MarkObject(trc, &type->newScript->fun, "type_new_function");
         MarkShape(trc, &type->newScript->shape, "type_new_shape");
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -12,24 +12,16 @@
 
 #include "mozilla/TypeTraits.h"
 #include "mozilla/GuardObjects.h"
 
 #include "js/TemplateLib.h"
 
 #include "jspubtd.h"
 
-namespace js {
-namespace gc {
-struct Cell;
-} /* namespace gc */
-} /* namespace js */
-
-namespace JS {
-
 /*
  * Moving GC Stack Rooting
  *
  * A moving GC may change the physical location of GC allocated things, even
  * when they are rooted, updating all pointers to the thing to refer to its new
  * location. The GC must therefore know about all live pointers to a thing,
  * not just one of them, in order to behave correctly.
  *
@@ -63,50 +55,60 @@ namespace JS {
  *   generally use handles for those arguments and avoid any explicit rooting.
  *   This has two benefits. First, when several such functions call each other
  *   then redundant rooting of multiple copies of the GC thing can be avoided.
  *   Second, if the caller does not pass a rooted value a compile error will be
  *   generated, which is quicker and easier to fix than when relying on a
  *   separate rooting analysis.
  */
 
-template <typename T> class MutableHandle;
+namespace js {
+
 template <typename T> class Rooted;
 
 template <typename T>
 struct RootMethods { };
 
+template <typename T>
+class HandleBase {};
+
+template <typename T>
+class MutableHandleBase {};
+
+} /* namespace js */
+
+namespace JS {
+
+template <typename T> class MutableHandle;
+
 /*
  * Handle provides an implicit constructor for NullPtr so that, given:
  *   foo(Handle<JSObject*> h);
  * callers can simply write:
  *   foo(NullPtr());
  * which avoids creating a Rooted<JSObject*> just to pass NULL.
  */
 struct NullPtr
 {
     static void * const constNullValue;
 };
 
 template <typename T>
 class MutableHandle;
 
-template <typename T>
-class HandleBase {};
-
 /*
  * Reference to a T that has been rooted elsewhere. This is most useful
  * as a parameter type, which guarantees that the T lvalue is properly
  * rooted. See "Move GC Stack Rooting" above.
  *
  * If you want to add additional methods to Handle for a specific
  * specialization, define a HandleBase<T> specialization containing them.
  */
 template <typename T>
-class Handle : public HandleBase<T>
+class Handle : public js::HandleBase<T>
 {
   public:
     /* Creates a handle from a handle of a type convertible to T. */
     template <typename S>
     Handle(Handle<S> handle,
            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
     {
         ptr = reinterpret_cast<const T *>(handle.address());
@@ -137,17 +139,17 @@ class Handle : public HandleBase<T>
     }
 
     /*
      * Construct a handle from an explicitly rooted location. This is the
      * normal way to create a handle, and normally happens implicitly.
      */
     template <typename S>
     inline
-    Handle(Rooted<S> &root,
+    Handle(js::Rooted<S> &root,
            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
 
     /* Construct a read only handle from a mutable handle. */
     template <typename S>
     inline
     Handle(MutableHandle<S> &root,
            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
 
@@ -168,46 +170,43 @@ class Handle : public HandleBase<T>
 
 typedef Handle<JSObject*>    HandleObject;
 typedef Handle<JSFunction*>  HandleFunction;
 typedef Handle<JSScript*>    HandleScript;
 typedef Handle<JSString*>    HandleString;
 typedef Handle<jsid>         HandleId;
 typedef Handle<Value>        HandleValue;
 
-template <typename T>
-class MutableHandleBase {};
-
 /*
  * Similar to a handle, but the underlying storage can be changed. This is
  * useful for outparams.
  *
  * If you want to add additional methods to MutableHandle for a specific
  * specialization, define a MutableHandleBase<T> specialization containing
  * them.
  */
 template <typename T>
-class MutableHandle : public MutableHandleBase<T>
+class MutableHandle : public js::MutableHandleBase<T>
 {
   public:
     template <typename S>
     MutableHandle(MutableHandle<S> handle,
                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
     {
         this->ptr = reinterpret_cast<const T *>(handle.address());
     }
 
     template <typename S>
     inline
-    MutableHandle(Rooted<S> *root,
+    MutableHandle(js::Rooted<S> *root,
                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
 
     void set(T v)
     {
-        JS_ASSERT(!RootMethods<T>::poisoned(v));
+        JS_ASSERT(!js::RootMethods<T>::poisoned(v));
         *ptr = v;
     }
 
     /*
      * This may be called only if the location of the T is guaranteed
      * to be marked (for some reason other than being a Rooted),
      * e.g., if it is guaranteed to be reachable from an implicit root.
      *
@@ -247,16 +246,20 @@ typedef MutableHandle<Value>       Mutab
  */
 typedef JSObject *                  RawObject;
 typedef JSFunction *                RawFunction;
 typedef JSScript *                  RawScript;
 typedef JSString *                  RawString;
 typedef jsid                        RawId;
 typedef Value                       RawValue;
 
+} /* namespace JS */
+
+namespace js {
+
 /*
  * InternalHandle is a handle to an internal pointer into a gcthing. Use
  * InternalHandle when you have a pointer to a direct field of a gcthing, or
  * when you need a parameter type for something that *may* be a pointer to a
  * direct field of a gcthing.
  */
 class InternalHandleBase
 {
@@ -274,17 +277,17 @@ class InternalHandle<T*> : public Intern
     size_t offset;
 
   public:
     /*
      * Create an InternalHandle using a Handle to the gcthing containing the
      * field in question, and a pointer to the field.
      */
     template<typename H>
-    InternalHandle(const Handle<H> &handle, T *field)
+    InternalHandle(const JS::Handle<H> &handle, T *field)
       : holder((void**)handle.address()), offset(uintptr_t(field) - uintptr_t(handle.get()))
     {
     }
 
     /*
      * Create an InternalHandle to a field within a Rooted<>.
      */
     template<typename R>
@@ -314,18 +317,16 @@ class InternalHandle<T*> : public Intern
      */
     InternalHandle(T *field)
       : holder(reinterpret_cast<void * const *>(&zeroPointer)),
         offset(uintptr_t(field))
     {
     }
 };
 
-extern mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
-
 /*
  * By default, pointers should use the inheritance hierarchy to find their
  * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
  * Rooted<T> may be used without the class definition being available.
  */
 template <typename T>
 struct RootKind<T *> { static ThingRootKind rootKind() { return T::rootKind(); } };
 
@@ -449,40 +450,16 @@ class Rooted : public RootedBase<T>
     Rooted<T> **stack, *prev;
 #endif
     T ptr;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     Rooted(const Rooted &) MOZ_DELETE;
 };
 
-template<typename T> template <typename S>
-inline
-Handle<T>::Handle(Rooted<S> &root,
-                  typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
-{
-    ptr = reinterpret_cast<const T *>(root.address());
-}
-
-template<typename T> template <typename S>
-inline
-Handle<T>::Handle(MutableHandle<S> &root,
-                  typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
-{
-    ptr = reinterpret_cast<const T *>(root.address());
-}
-
-template<typename T> template <typename S>
-inline
-MutableHandle<T>::MutableHandle(Rooted<S> *root,
-                                typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
-{
-    ptr = root->address();
-}
-
 typedef Rooted<JSObject*>    RootedObject;
 typedef Rooted<JSFunction*>  RootedFunction;
 typedef Rooted<JSScript*>    RootedScript;
 typedef Rooted<JSString*>    RootedString;
 typedef Rooted<jsid>         RootedId;
 typedef Rooted<Value>        RootedValue;
 
 /*
@@ -540,16 +517,44 @@ class SkipRoot
         JS_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
 #endif /* DEBUG && JSGC_ROOT_ANALYSIS */
 
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
+} /* namespace js */
+
+namespace JS {
+
+template<typename T> template <typename S>
+inline
+Handle<T>::Handle(js::Rooted<S> &root,
+                  typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
+{
+    ptr = reinterpret_cast<const T *>(root.address());
+}
+
+template<typename T> template <typename S>
+inline
+Handle<T>::Handle(MutableHandle<S> &root,
+                  typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
+{
+    ptr = reinterpret_cast<const T *>(root.address());
+}
+
+template<typename T> template <typename S>
+inline
+MutableHandle<T>::MutableHandle(js::Rooted<S> *root,
+                                typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
+{
+    ptr = root->address();
+}
+
 JS_FRIEND_API(void) EnterAssertNoGCScope();
 JS_FRIEND_API(void) LeaveAssertNoGCScope();
 JS_FRIEND_API(bool) InNoGCScope();
 
 /*
  * The scoped guard object AutoAssertNoGC forces the GC to assert if a GC is
  * attempted while the guard object is live.  If you have a GC-unsafe operation
  * to perform, use this guard object to protect your operation.
@@ -575,32 +580,40 @@ public:
 
 #if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
 extern void
 CheckStackRoots(JSContext *cx);
 #endif
 
 JS_FRIEND_API(bool) NeedRelaxedRootChecks();
 
+} /* namespace JS */
+
+namespace js {
+
 /*
  * Hook for dynamic root analysis. Checks the native stack and poisons
  * references to GC things which have not been rooted.
  */
 inline void MaybeCheckStackRoots(JSContext *cx, bool relax = true)
 {
 #ifdef DEBUG
     JS_ASSERT(!InNoGCScope());
 # if defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
     if (relax && NeedRelaxedRootChecks())
         return;
     CheckStackRoots(cx);
 # endif
 #endif
 }
 
+namespace gc {
+struct Cell;
+} /* namespace gc */
+
 /* Base class for automatic read-only object rooting during compilation. */
 class CompilerRootNode
 {
   protected:
     CompilerRootNode(js::gc::Cell *ptr)
       : next(NULL), ptr(ptr)
     { }
 
@@ -609,13 +622,13 @@ class CompilerRootNode
 
   public:
     CompilerRootNode *next;
 
   protected:
     js::gc::Cell *ptr;
 };
 
-}  /* namespace JS */
+}  /* namespace js */
 
 #endif  /* __cplusplus */
 
 #endif  /* jsgc_root_h___ */
--- a/js/src/ion/CompilerRoot.h
+++ b/js/src/ion/CompilerRoot.h
@@ -30,17 +30,17 @@ class CompilerRoot : public CompilerRoot
     {
         if (ptr)
             setRoot(ptr);
     }
 
   public:
     // Sets the pointer and inserts into root list. The pointer becomes read-only.
     void setRoot(T root) {
-        JS::CompilerRootNode *&rootList = GetIonContext()->temp->rootList();
+        CompilerRootNode *&rootList = GetIonContext()->temp->rootList();
 
         JS_ASSERT(!ptr);
         ptr = root;
         next = rootList;
         rootList = this;
     }
 
   public:
--- a/js/src/ion/IonAllocPolicy.h
+++ b/js/src/ion/IonAllocPolicy.h
@@ -18,17 +18,17 @@ namespace js {
 namespace ion {
 
 class TempAllocator
 {
     LifoAlloc *lifoAlloc_;
     void *mark_;
 
     // Linked list of GCThings rooted by this allocator.
-    JS::CompilerRootNode *rootList_;
+    CompilerRootNode *rootList_;
 
   public:
     TempAllocator(LifoAlloc *lifoAlloc)
       : lifoAlloc_(lifoAlloc),
         mark_(lifoAlloc->mark()),
         rootList_(NULL)
     { }
 
@@ -52,17 +52,17 @@ class TempAllocator
         return p;
     }
 
     LifoAlloc *lifoAlloc()
     {
         return lifoAlloc_;
     }
 
-    JS::CompilerRootNode *&rootList()
+    CompilerRootNode *&rootList()
     {
         return rootList_;
     }
 
     bool ensureBallast() {
         // Most infallible Ion allocations are small, so we use a ballast of
         // ~16K for now.
         return lifoAlloc_->ensureUnusedApproximate(16 * 1024);
--- a/js/src/ion/IonFrameIterator.h
+++ b/js/src/ion/IonFrameIterator.h
@@ -108,16 +108,17 @@ class IonFrameIterator
     // places the invalidated Ion script in |ionScript|.
     bool checkInvalidation(IonScript **ionScript) const;
     bool checkInvalidation() const;
 
     bool isScripted() const {
         return type_ == IonFrame_JS;
     }
     bool isNative() const;
+    bool isOOLNativeGetter() const;
     bool isDOMExit() const;
     bool isEntry() const {
         return type_ == IonFrame_Entry;
     }
     bool isFunctionFrame() const;
 
     bool isConstructing() const;
 
--- a/js/src/ion/IonFrames-inl.h
+++ b/js/src/ion/IonFrames-inl.h
@@ -77,21 +77,30 @@ size_t
 IonFrameIterator::frameSize() const
 {
     JS_ASSERT(type_ != IonFrame_Exit);
     return frameSize_;
 }
 
 // Returns the JSScript associated with the topmost Ion frame.
 inline JSScript *
-GetTopIonJSScript(JSContext *cx)
+GetTopIonJSScript(JSContext *cx, const SafepointIndex **safepointIndexOut, void **returnAddrOut)
 {
     IonFrameIterator iter(cx->runtime->ionTop);
     JS_ASSERT(iter.type() == IonFrame_Exit);
     ++iter;
+
+    // If needed, grab the safepoint index.
+    if (safepointIndexOut)
+        *safepointIndexOut = iter.safepoint();
+
+    JS_ASSERT(iter.returnAddressToFp() != NULL);
+    if (returnAddrOut)
+        *returnAddrOut = (void *) iter.returnAddressToFp();
+
     JS_ASSERT(iter.type() == IonFrame_JS);
     IonJSFrameLayout *frame = static_cast<IonJSFrameLayout*>(iter.current());
     switch (GetCalleeTokenTag(frame->calleeToken())) {
       case CalleeToken_Function: {
         JSFunction *fun = CalleeTokenToFunction(frame->calleeToken());
         return fun->script();
       }
       case CalleeToken_Script:
--- a/js/src/ion/IonFrames.cpp
+++ b/js/src/ion/IonFrames.cpp
@@ -113,16 +113,24 @@ bool
 IonFrameIterator::isNative() const
 {
     if (type_ != IonFrame_Exit)
         return false;
     return exitFrame()->footer()->ionCode() == NULL;
 }
 
 bool
+IonFrameIterator::isOOLNativeGetter() const
+{
+    if (type_ != IonFrame_Exit)
+        return false;
+    return exitFrame()->footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER;
+}
+
+bool
 IonFrameIterator::isDOMExit() const
 {
     if (type_ != IonFrame_Exit)
         return false;
     return exitFrame()->isDomExit();
 }
 
 bool
@@ -525,16 +533,23 @@ MarkIonExitFrame(JSTracer *trc, const Io
     if (frame.isNative()) {
         IonNativeExitFrameLayout *native = frame.exitFrame()->nativeExit();
         size_t len = native->argc() + 2;
         Value *vp = native->vp();
         gc::MarkValueRootRange(trc, len, vp, "ion-native-args");
         return;
     }
 
+    if (frame.isOOLNativeGetter()) {
+        IonOOLNativeGetterExitFrameLayout *oolgetter = frame.exitFrame()->oolNativeGetterExit();
+        gc::MarkValueRoot(trc, oolgetter->vp(), "ion-ool-getter-callee");
+        gc::MarkValueRoot(trc, oolgetter->vp() + 1, "ion-ool-getter-this");
+        return;
+    }
+
     if (frame.isDOMExit()) {
         IonDOMExitFrameLayout *dom = frame.exitFrame()->DOMExit();
         gc::MarkObjectRoot(trc, dom->thisObjAddress(), "ion-dom-args");
         if (dom->isSetterFrame()) {
             gc::MarkValueRoot(trc, dom->vp(), "ion-dom-args");
         } else if (dom->isMethodFrame()) {
             IonDOMMethodExitFrameLayout *method =
                 reinterpret_cast<IonDOMMethodExitFrameLayout *>(dom);
--- a/js/src/ion/IonFrames.h
+++ b/js/src/ion/IonFrames.h
@@ -252,17 +252,19 @@ MakeFrameDescriptor(uint32 frameSize, Fr
 #else
 # error "unsupported architecture"
 #endif
 
 namespace js {
 namespace ion {
 
 JSScript *
-GetTopIonJSScript(JSContext *cx);
+GetTopIonJSScript(JSContext *cx,
+                  const SafepointIndex **safepointIndexOut = NULL,
+                  void **returnAddrOut = NULL);
 
 void
 GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes);
 
 // Given a slot index, returns the offset, in bytes, of that slot from an
 // IonJSFrameLayout. Slot distances are uniform across architectures, however,
 // the distance does depend on the size of the frame header.
 static inline int32
--- a/js/src/ion/arm/IonFrames-arm.h
+++ b/js/src/ion/arm/IonFrames-arm.h
@@ -151,16 +151,17 @@ class IonOsrFrameLayout : public IonJSFr
 {
   public:
     static inline size_t Size() {
         return sizeof(IonOsrFrameLayout);
     }
 };
 
 class IonNativeExitFrameLayout;
+class IonOOLNativeGetterExitFrameLayout;
 class IonDOMExitFrameLayout;
 
 // this is the frame layout when we are exiting ion code, and about to enter EABI code
 class IonExitFrameLayout : public IonCommonFrameLayout
 {
     inline uint8 *top() {
         return reinterpret_cast<uint8 *>(this + 1);
     }
@@ -187,29 +188,36 @@ class IonExitFrameLayout : public IonCom
     }
 
     inline bool isWrapperExit() {
         return footer()->function() != NULL;
     }
     inline bool isNativeExit() {
         return footer()->ionCode() == NULL;
     }
+    inline bool isOOLNativeGetterExit() {
+        return footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER;
+    }
     inline bool isDomExit() {
         IonCode *code = footer()->ionCode();
         return
             code == ION_FRAME_DOMGETTER ||
             code == ION_FRAME_DOMSETTER ||
             code == ION_FRAME_DOMMETHOD;
     }
 
     inline IonNativeExitFrameLayout *nativeExit() {
         // see CodeGenerator::visitCallNative
         JS_ASSERT(isNativeExit());
         return reinterpret_cast<IonNativeExitFrameLayout *>(footer());
     }
+    inline IonOOLNativeGetterExitFrameLayout *oolNativeGetterExit() {
+        JS_ASSERT(isOOLNativeGetterExit());
+        return reinterpret_cast<IonOOLNativeGetterExitFrameLayout *>(footer());
+    }
     inline IonDOMExitFrameLayout *DOMExit() {
         JS_ASSERT(isDomExit());
         return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
     }
 };
 
 // Cannot inherit implementa<tion since we need to extend the top of
 // IonExitFrameLayout.
@@ -235,16 +243,46 @@ class IonNativeExitFrameLayout
     inline Value *vp() {
         return reinterpret_cast<Value*>(&loCalleeResult_);
     }
     inline uintptr_t argc() const {
         return argc_;
     }
 };
 
+class IonOOLNativeGetterExitFrameLayout
+{
+    IonExitFooterFrame footer_;
+    IonExitFrameLayout exit_;
+
+    // We need to split the Value into 2 fields of 32 bits, otherwise the C++
+    // compiler may add some padding between the fields.
+    uint32_t loCalleeResult_;
+    uint32_t hiCalleeResult_;
+
+    // The frame includes the object argument.
+    uint32_t loThis_;
+    uint32_t hiThis_;
+
+  public:
+    static inline size_t Size() {
+        return sizeof(IonOOLNativeGetterExitFrameLayout);
+    }
+
+    static size_t offsetOfResult() {
+        return offsetof(IonOOLNativeGetterExitFrameLayout, loCalleeResult_);
+    }
+    inline Value *vp() {
+        return reinterpret_cast<Value*>(&loCalleeResult_);
+    }
+    inline uintptr_t argc() const {
+        return 0;
+    }
+};
+
 class IonDOMExitFrameLayout
 {
     IonExitFooterFrame footer_;
     IonExitFrameLayout exit_;
     JSObject *thisObj;
 
     // We need to split the Value in 2 field of 32 bits, otherwise the C++
     // compiler may add some padding between the fields.
--- a/js/src/ion/shared/IonFrames-shared.h
+++ b/js/src/ion/shared/IonFrames-shared.h
@@ -39,10 +39,11 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef jsion_ionframes_shared_h__
 #define jsion_ionframes_shared_h__
 
 #define ION_FRAME_DOMGETTER ((IonCode *)0x1)
 #define ION_FRAME_DOMSETTER ((IonCode *)0x2)
 #define ION_FRAME_DOMMETHOD ((IonCode *)0x3)
+#define ION_FRAME_OOL_NATIVE_GETTER ((IonCode *)0x4)
 
 #endif
--- a/js/src/ion/shared/IonFrames-x86-shared.h
+++ b/js/src/ion/shared/IonFrames-x86-shared.h
@@ -136,16 +136,17 @@ class IonExitFooterFrame
 
     // This should only be called for function()->outParam == Type_Handle
     Value *outVp() {
         return reinterpret_cast<Value *>(reinterpret_cast<char *>(this) - sizeof(Value));
     }
 };
 
 class IonNativeExitFrameLayout;
+class IonOOLNativeGetterExitFrameLayout;
 class IonDOMExitFrameLayout;
 
 class IonExitFrameLayout : public IonCommonFrameLayout
 {
     inline uint8 *top() {
         return reinterpret_cast<uint8 *>(this + 1);
     }
 
@@ -184,16 +185,21 @@ class IonExitFrameLayout : public IonCom
             code == ION_FRAME_DOMMETHOD;
     }
 
     inline IonNativeExitFrameLayout *nativeExit() {
         // see CodeGenerator::visitCallNative
         JS_ASSERT(isNativeExit());
         return reinterpret_cast<IonNativeExitFrameLayout *>(footer());
     }
+    inline IonOOLNativeGetterExitFrameLayout *oolNativeGetterExit() {
+        // see CodeGenerator::visitCallNative
+        JS_ASSERT(footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER);
+        return reinterpret_cast<IonOOLNativeGetterExitFrameLayout *>(footer());
+    }
     inline IonDOMExitFrameLayout *DOMExit() {
         JS_ASSERT(isDomExit());
         return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
     }
 };
 
 class IonNativeExitFrameLayout
 {
@@ -218,16 +224,47 @@ class IonNativeExitFrameLayout
     inline Value *vp() {
         return reinterpret_cast<Value*>(&loCalleeResult_);
     }
     inline uintptr_t argc() const {
         return argc_;
     }
 };
 
+class IonOOLNativeGetterExitFrameLayout
+{
+    IonExitFooterFrame footer_;
+    IonExitFrameLayout exit_;
+
+    // We need to split the Value into 2 fields of 32 bits, otherwise the C++
+    // compiler may add some padding between the fields.
+    uint32_t loCalleeResult_;
+    uint32_t hiCalleeResult_;
+
+    // The frame includes the object argument.
+    uint32_t loThisResult_;
+    uint32_t hiThisResult_;
+
+  public:
+    static inline size_t Size() {
+        return sizeof(IonOOLNativeGetterExitFrameLayout);
+    }
+
+    static size_t offsetOfResult() {
+        return offsetof(IonOOLNativeGetterExitFrameLayout, loCalleeResult_);
+    }
+
+    inline Value *vp() {
+        return reinterpret_cast<Value*>(&loCalleeResult_);
+    }
+    inline uintptr_t argc() const {
+        return 0;
+    }
+};
+
 class IonDOMExitFrameLayout
 {
   protected: // only to silence a clang warning about unused private fields
     IonExitFooterFrame footer_;
     IonExitFrameLayout exit_;
     JSObject *thisObj;
 
     // We need to split the Value in 2 field of 32 bits, otherwise the C++
--- a/js/src/jsapi-tests/selfTest.cpp
+++ b/js/src/jsapi-tests/selfTest.cpp
@@ -5,17 +5,17 @@
  * 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 "tests.h"
 
 BEGIN_TEST(selfTest_NaNsAreSame)
 {
-    JS::RootedValue v1(cx), v2(cx);
+    js::RootedValue v1(cx), v2(cx);
     EVAL("0/0", v1.address());  // NaN
     CHECK_SAME(v1, v1);
 
     EVAL("Math.sin('no')", v2.address());  // also NaN
     CHECK_SAME(v1, v2);
     return true;
 }
 END_TEST(selfTest_NaNsAreSame)
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -29,35 +29,35 @@ JSClass addPropertyClass = {
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 BEGIN_TEST(testAddPropertyHook)
 {
-    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
+    js::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     CHECK(obj);
-    JS::RootedValue proto(cx, OBJECT_TO_JSVAL(obj));
+    js::RootedValue proto(cx, OBJECT_TO_JSVAL(obj));
     JS_InitClass(cx, global, obj, &addPropertyClass, NULL, 0, NULL, NULL, NULL,
                  NULL);
 
     obj = JS_NewArrayObject(cx, 0, NULL);
     CHECK(obj);
-    JS::RootedValue arr(cx, OBJECT_TO_JSVAL(obj));
+    js::RootedValue arr(cx, OBJECT_TO_JSVAL(obj));
 
     CHECK(JS_DefineProperty(cx, global, "arr", arr,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE));
 
     for (int i = 0; i < expectedCount; ++i) {
         obj = JS_NewObject(cx, &addPropertyClass, NULL, NULL);
         CHECK(obj);
-        JS::RootedValue vobj(cx, OBJECT_TO_JSVAL(obj));
-        JS::RootedObject arrObj(cx, JSVAL_TO_OBJECT(arr));
+        js::RootedValue vobj(cx, OBJECT_TO_JSVAL(obj));
+        js::RootedObject arrObj(cx, JSVAL_TO_OBJECT(arr));
         CHECK(JS_DefineElement(cx, arrObj, i, vobj,
                                JS_PropertyStub, JS_StrictPropertyStub,
                                JSPROP_ENUMERATE));
     }
 
     // Now add a prop to each of the objects, but make sure to do
     // so at the same bytecode location so we can hit the propcache.
     EXEC("'use strict';                                     \n"
--- a/js/src/jsapi-tests/testArrayBuffer.cpp
+++ b/js/src/jsapi-tests/testArrayBuffer.cpp
@@ -6,18 +6,18 @@
 #include "jsfriendapi.h"
 
 #define NUM_TEST_BUFFERS 2
 #define MAGIC_VALUE_1 3
 #define MAGIC_VALUE_2 17
 
 BEGIN_TEST(testArrayBuffer_bug720949_steal)
 {
-    JS::RootedObject buf_len1(cx), buf_len200(cx);
-    JS::RootedObject tarray_len1(cx), tarray_len200(cx);
+    js::RootedObject buf_len1(cx), buf_len200(cx);
+    js::RootedObject tarray_len1(cx), tarray_len200(cx);
 
     uint32_t sizes[NUM_TEST_BUFFERS] = { sizeof(uint32_t), 200 * sizeof(uint32_t) };
     JS::HandleObject testBuf[NUM_TEST_BUFFERS] = { buf_len1, buf_len200 };
     JS::HandleObject testArray[NUM_TEST_BUFFERS] = { tarray_len1, tarray_len200 };
 
     // Single-element ArrayBuffer (uses fixed slots for storage)
     CHECK(buf_len1 = JS_NewArrayBuffer(cx, sizes[0]));
     CHECK(tarray_len1 = JS_NewInt32ArrayWithBuffer(cx, testBuf[0], 0, -1));
@@ -66,21 +66,21 @@ BEGIN_TEST(testArrayBuffer_bug720949_ste
         CHECK(JS_GetProperty(cx, view, "length", &v));
         CHECK_SAME(v, INT_TO_JSVAL(0));
         CHECK_EQUAL(JS_GetArrayBufferByteLength(obj, cx), 0);
         v = JSVAL_VOID;
         JS_GetElement(cx, obj, 0, &v);
         CHECK_SAME(v, JSVAL_VOID);
 
         // Transfer to a new ArrayBuffer
-        JS::RootedObject dst(cx, JS_NewArrayBufferWithContents(cx, contents));
+        js::RootedObject dst(cx, JS_NewArrayBufferWithContents(cx, contents));
         CHECK(JS_IsArrayBufferObject(dst, cx));
         data = JS_GetArrayBufferData(obj, cx);
 
-        JS::RootedObject dstview(cx, JS_NewInt32ArrayWithBuffer(cx, dst, 0, -1));
+        js::RootedObject dstview(cx, JS_NewInt32ArrayWithBuffer(cx, dst, 0, -1));
         CHECK(dstview != NULL);
 
         CHECK_EQUAL(JS_GetArrayBufferByteLength(dst, cx), size);
         data = JS_GetArrayBufferData(dst, cx);
         CHECK(data != NULL);
         CHECK_EQUAL(*reinterpret_cast<uint32_t*>(data), MAGIC_VALUE_2);
         CHECK(JS_GetElement(cx, dstview, 0, &v));
         CHECK_SAME(v, INT_TO_JSVAL(MAGIC_VALUE_2));
@@ -94,27 +94,27 @@ static void GC(JSContext *cx)
 {
     JS_GC(JS_GetRuntime(cx));
     JS_GC(JS_GetRuntime(cx)); // Trigger another to wait for background finalization to end
 }
 
 // Varying number of views of a buffer, to test the neutering weak pointers
 BEGIN_TEST(testArrayBuffer_bug720949_viewList)
 {
-    JS::RootedObject buffer(cx);
+    js::RootedObject buffer(cx);
 
     // No views
     buffer = JS_NewArrayBuffer(cx, 2000);
     buffer = NULL;
     GC(cx);
 
     // One view.
     {
         buffer = JS_NewArrayBuffer(cx, 2000);
-        JS::RootedObject view(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
+        js::RootedObject view(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
         void *contents;
         CHECK(JS_StealArrayBufferContents(cx, buffer, &contents));
         CHECK(contents != NULL);
         JS_free(cx, contents);
         GC(cx);
         CHECK(isNeutered(view));
         CHECK(isNeutered(buffer));
         view = NULL;
@@ -122,18 +122,18 @@ BEGIN_TEST(testArrayBuffer_bug720949_vie
         buffer = NULL;
         GC(cx);
     }
 
     // Two views
     {
         buffer = JS_NewArrayBuffer(cx, 2000);
 
-        JS::RootedObject view1(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
-        JS::RootedObject view2(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 1, 200));
+        js::RootedObject view1(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
+        js::RootedObject view2(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 1, 200));
 
         // Remove, re-add a view
         view2 = NULL;
         GC(cx);
         view2 = JS_NewUint8ArrayWithBuffer(cx, buffer, 1, 200);
 
         // Neuter
         void *contents;
--- a/js/src/jsapi-tests/testBindCallable.cpp
+++ b/js/src/jsapi-tests/testBindCallable.cpp
@@ -9,18 +9,18 @@ BEGIN_TEST(test_BindCallable)
   jsval v;
   EVAL("({ somename : 1717 })", &v);
   CHECK(v.isObject());
 
   jsval func;
   EVAL("(function() { return this.somename; })", &func);
   CHECK(func.isObject());
 
-  JS::RootedObject funcObj(cx, JSVAL_TO_OBJECT(func));
-  JS::RootedObject vObj(cx, JSVAL_TO_OBJECT(v));
+  js::RootedObject funcObj(cx, JSVAL_TO_OBJECT(func));
+  js::RootedObject vObj(cx, JSVAL_TO_OBJECT(v));
   JSObject* newCallable = JS_BindCallable(cx, funcObj, vObj);
   CHECK(newCallable);
 
   jsval retval;
   bool called = JS_CallFunctionValue(cx, NULL, OBJECT_TO_JSVAL(newCallable),
                                      0, NULL, &retval);
   CHECK(called);
 
--- a/js/src/jsapi-tests/testBug604087.cpp
+++ b/js/src/jsapi-tests/testBug604087.cpp
@@ -7,16 +7,18 @@
  * 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 "tests.h"
 #include "jsobj.h"
 #include "jswrapper.h"
 
+#include "jsobjinlines.h"
+
 struct OuterWrapper : js::DirectWrapper
 {
     OuterWrapper() : DirectWrapper(0) {}
 
     virtual bool isOuterWindow() {
         return true;
     }
 
@@ -25,70 +27,70 @@ struct OuterWrapper : js::DirectWrapper
 
 OuterWrapper
 OuterWrapper::singleton;
 
 static JSObject *
 wrap(JSContext *cx, JS::HandleObject toWrap, JS::HandleObject target)
 {
     JSAutoCompartment ac(cx, target);
-    JS::RootedObject wrapper(cx, toWrap);
+    js::RootedObject wrapper(cx, toWrap);
     if (!JS_WrapObject(cx, wrapper.address()))
         return NULL;
     return wrapper;
 }
 
 static JSObject *
 SameCompartmentWrap(JSContext *cx, JSObject *objArg)
 {
-    JS::RootedObject obj(cx, objArg);
+    js::RootedObject obj(cx, objArg);
     JS_GC(JS_GetRuntime(cx));
     return obj;
 }
 
 static JSObject *
 PreWrap(JSContext *cx, JSObject *scopeArg, JSObject *objArg, unsigned flags)
 {
-    JS::RootedObject scope(cx, scopeArg);
-    JS::RootedObject obj(cx, objArg);
+    js::RootedObject scope(cx, scopeArg);
+    js::RootedObject obj(cx, objArg);
     JS_GC(JS_GetRuntime(cx));
     return obj;
 }
 
 static JSObject *
 Wrap(JSContext *cx, JSObject *objArg, JSObject *protoArg, JSObject *parentArg, unsigned flags)
 {
-    JS::RootedObject obj(cx, objArg);
-    JS::RootedObject proto(cx, protoArg);
-    JS::RootedObject parent(cx, parentArg);
+    js::RootedObject obj(cx, objArg);
+    js::RootedObject proto(cx, protoArg);
+    js::RootedObject parent(cx, parentArg);
     return js::Wrapper::New(cx, obj, proto, parent, &js::CrossCompartmentWrapper::singleton);
 }
 
 BEGIN_TEST(testBug604087)
 {
-    JS::RootedObject outerObj(cx, js::Wrapper::New(cx, global, global->getProto(), global,
+    js::RootedObject outerObj(cx, js::Wrapper::New(cx, global, global->getProto(), global,
                                                &OuterWrapper::singleton));
-    JS::RootedObject compartment2(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
-    JS::RootedObject compartment3(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
-    JS::RootedObject compartment4(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    js::RootedObject compartment2(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    js::RootedObject compartment3(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    js::RootedObject compartment4(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
 
-    JS::RootedObject c2wrapper(cx, wrap(cx, outerObj, compartment2));
+    js::RootedObject c2wrapper(cx, wrap(cx, outerObj, compartment2));
     CHECK(c2wrapper);
     js::SetProxyExtra(c2wrapper, 0, js::Int32Value(2));
 
-    JS::RootedObject c3wrapper(cx, wrap(cx, outerObj, compartment3));
+    js::RootedObject c3wrapper(cx, wrap(cx, outerObj, compartment3));
     CHECK(c3wrapper);
     js::SetProxyExtra(c3wrapper, 0, js::Int32Value(3));
 
-    JS::RootedObject c4wrapper(cx, wrap(cx, outerObj, compartment4));
+    js::RootedObject c4wrapper(cx, wrap(cx, outerObj, compartment4));
     CHECK(c4wrapper);
     js::SetProxyExtra(c4wrapper, 0, js::Int32Value(4));
     compartment4 = c4wrapper = NULL;
 
-    JS::RootedObject next(cx);
+    js::RootedObject next(cx);
     {
         JSAutoCompartment ac(cx, compartment2);
         next = js::Wrapper::New(cx, compartment2, compartment2->getProto(), compartment2,
                                 &OuterWrapper::singleton);
         CHECK(next);
     }
 
     JS_SetWrapObjectCallbacks(JS_GetRuntime(cx), Wrap, SameCompartmentWrap, PreWrap);
--- a/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
+++ b/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
@@ -39,49 +39,49 @@ CustomMethod(JSContext *cx, unsigned arg
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   return CallNonGenericMethod(cx, IsCustomClass, CustomMethodImpl, args);
 }
 
 BEGIN_TEST(test_CallNonGenericMethodOnProxy)
 {
   // Create the first global object and compartment
-  JS::RootedObject globalA(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+  js::RootedObject globalA(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
   CHECK(globalA);
 
-  JS::RootedObject customA(cx, JS_NewObject(cx, &CustomClass, NULL, NULL));
+  js::RootedObject customA(cx, JS_NewObject(cx, &CustomClass, NULL, NULL));
   CHECK(customA);
   JS_SetReservedSlot(customA, CUSTOM_SLOT, Int32Value(17));
 
   JSFunction *customMethodA = JS_NewFunction(cx, CustomMethod, 0, 0, customA, "customMethodA");
   CHECK(customMethodA);
 
   jsval rval;
   CHECK(JS_CallFunction(cx, customA, customMethodA, 0, NULL, &rval));
   CHECK_SAME(rval, Int32Value(17));
 
   // Now create the second global object and compartment...
   {
-    JS::RootedObject globalB(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    js::RootedObject globalB(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
     CHECK(globalB);
 
     // ...and enter it.
     JSAutoCompartment enter(cx, globalB);
-    JS::RootedObject customB(cx, JS_NewObject(cx, &CustomClass, NULL, NULL));
+    js::RootedObject customB(cx, JS_NewObject(cx, &CustomClass, NULL, NULL));
     CHECK(customB);
     JS_SetReservedSlot(customB, CUSTOM_SLOT, Int32Value(42));
 
     JSFunction *customMethodB = JS_NewFunction(cx, CustomMethod, 0, 0, customB, "customMethodB");
     CHECK(customMethodB);
 
     jsval rval;
     CHECK(JS_CallFunction(cx, customB, customMethodB, 0, NULL, &rval));
     CHECK_SAME(rval, Int32Value(42));
 
-    JS::RootedObject wrappedCustomA(cx, customA);
+    js::RootedObject wrappedCustomA(cx, customA);
     CHECK(JS_WrapObject(cx, wrappedCustomA.address()));
 
     jsval rval2;
     CHECK(JS_CallFunction(cx, wrappedCustomA, customMethodB, 0, NULL, &rval2));
     CHECK_SAME(rval, Int32Value(42));
   }
 
   return true;
--- a/js/src/jsapi-tests/testClassGetter.cpp
+++ b/js/src/jsapi-tests/testClassGetter.cpp
@@ -58,16 +58,16 @@ static JSFunctionSpec ptestFunctions[] =
 BEGIN_TEST(testClassGetter_isCalled)
 {
     CHECK(JS_InitClass(cx, global, NULL, &ptestClass, PTest, 0,
                        NULL, ptestFunctions, NULL, NULL));
 
     EXEC("function check() { var o = new PTest(); o.test_fn(); o.test_value1; o.test_value2; o.test_value1; }");
 
     for (int i = 1; i < 9; i++) {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK_SAME(INT_TO_JSVAL(called_test_fn), INT_TO_JSVAL(i));
         CHECK_SAME(INT_TO_JSVAL(called_test_prop_get), INT_TO_JSVAL(4 * i));
     }
     return true;
 }
 END_TEST(testClassGetter_isCalled)
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -8,32 +8,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 #include "jsdbgapi.h"
 
 BEGIN_TEST(test_cloneScript)
 {
-    JS::RootedObject A(cx, createGlobal());
-    JS::RootedObject B(cx, createGlobal());
+    js::RootedObject A(cx, createGlobal());
+    js::RootedObject B(cx, createGlobal());
 
     CHECK(A);
     CHECK(B);
 
     const char *source =
         "var i = 0;\n"
         "var sum = 0;\n"
         "while (i < 10) {\n"
         "    sum += i;\n"
         "    ++i;\n"
         "}\n"
         "(sum);\n";
 
-    JS::RootedObject obj(cx);
+    js::RootedObject obj(cx);
 
     // compile for A
     {
         JSAutoCompartment a(cx, A);
         JSFunction *fun;
         CHECK(fun = JS_CompileFunction(cx, A, "f", 0, NULL, source, strlen(source), __FILE__, 1));
         CHECK(obj = JS_GetFunctionObject(fun));
     }
@@ -85,26 +85,26 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
 {
     JS_InitDestroyPrincipalsCallback(rt, DestroyPrincipals);
 
     JSPrincipals *principalsA = new Principals();
     AutoDropPrincipals dropA(rt, principalsA);
     JSPrincipals *principalsB = new Principals();
     AutoDropPrincipals dropB(rt, principalsB);
 
-    JS::RootedObject A(cx, createGlobal(principalsA));
-    JS::RootedObject B(cx, createGlobal(principalsB));
+    js::RootedObject A(cx, createGlobal(principalsA));
+    js::RootedObject B(cx, createGlobal(principalsB));
 
     CHECK(A);
     CHECK(B);
 
     const char *argnames[] = { "arg" };
     const char *source = "return function() { return arg; }";
 
-    JS::RootedObject obj(cx);
+    js::RootedObject obj(cx);
 
     // Compile in A
     {
         JSAutoCompartment a(cx, A);
         JSFunction *fun;
         CHECK(fun = JS_CompileFunctionForPrincipals(cx, A, principalsA, "f",
                                                     mozilla::ArrayLength(argnames), argnames,
                                                     source, strlen(source), __FILE__, 1));
@@ -114,17 +114,17 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
 
         CHECK(JS_GetScriptPrincipals(script) == principalsA);
         CHECK(obj = JS_GetFunctionObject(fun));
     }
 
     // Clone into B
     {
         JSAutoCompartment b(cx, B);
-        JS::RootedObject cloned(cx);
+        js::RootedObject cloned(cx);
         CHECK(cloned = JS_CloneFunctionObject(cx, obj, B));
 
         JSFunction *fun;
         CHECK(fun = JS_ValueToFunction(cx, JS::ObjectValue(*cloned)));
 
         JSScript *script;
         CHECK(script = JS_GetFunctionScript(cx, fun));
 
--- a/js/src/jsapi-tests/testConservativeGC.cpp
+++ b/js/src/jsapi-tests/testConservativeGC.cpp
@@ -1,41 +1,43 @@
 /* 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 "tests.h"
 #include "jsobj.h"
 #include "vm/String.h"
 
+#include "jsobjinlines.h"
+
 BEGIN_TEST(testConservativeGC)
 {
 #ifndef JSGC_USE_EXACT_ROOTING
-    JS::RootedValue v2(cx);
+    js::RootedValue v2(cx);
     EVAL("({foo: 'bar'});", v2.address());
     CHECK(v2.isObject());
     char objCopy[sizeof(JSObject)];
     js_memcpy(&objCopy, JSVAL_TO_OBJECT(v2), sizeof(JSObject));
 
-    JS::RootedValue v3(cx);
+    js::RootedValue v3(cx);
     EVAL("String(Math.PI);", v3.address());
     CHECK(JSVAL_IS_STRING(v3));
     char strCopy[sizeof(JSString)];
     js_memcpy(&strCopy, JSVAL_TO_STRING(v3), sizeof(JSString));
 
     jsval tmp;
     EVAL("({foo2: 'bar2'});", &tmp);
     CHECK(tmp.isObject());
-    JS::RootedObject obj2(cx, JSVAL_TO_OBJECT(tmp));
+    js::RootedObject obj2(cx, JSVAL_TO_OBJECT(tmp));
     char obj2Copy[sizeof(JSObject)];
     js_memcpy(&obj2Copy, obj2, sizeof(JSObject));
 
     EVAL("String(Math.sqrt(3));", &tmp);
     CHECK(JSVAL_IS_STRING(tmp));
-    JS::RootedString str2(cx, JSVAL_TO_STRING(tmp));
+    js::RootedString str2(cx, JSVAL_TO_STRING(tmp));
     char str2Copy[sizeof(JSString)];
     js_memcpy(&str2Copy, str2, sizeof(JSString));
 
     tmp = JSVAL_NULL;
 
     JS_GC(rt);
 
     EVAL("var a = [];\n"
--- a/js/src/jsapi-tests/testCustomIterator.cpp
+++ b/js/src/jsapi-tests/testCustomIterator.cpp
@@ -15,17 +15,17 @@ IterNext(JSContext *cx, unsigned argc, j
         return JS_ThrowStopIteration(cx);
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(count));
     return true;
 }
 
 static JSObject *
 IterHook(JSContext *cx, JS::HandleObject obj, JSBool keysonly)
 {
-    JS::RootedObject iterObj(cx, JS_NewObject(cx, NULL, NULL, NULL));
+    js::RootedObject iterObj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     if (!iterObj)
         return NULL;
     if (!JS_DefineFunction(cx, iterObj, "next", IterNext, 0, 0))
         return NULL;
     return iterObj;
 }
 
 js::Class HasCustomIterClass = {
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -112,17 +112,17 @@ END_TEST(testDebugger_getThisStrict)
 bool called = false;
 
 static JSTrapStatus
 ThrowHook(JSContext *cx, JSScript *, jsbytecode *, jsval *rval, void *closure)
 {
     JS_ASSERT(!closure);
     called = true;
 
-    JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx));
+    js::RootedObject global(cx, JS_GetGlobalForScopeChain(cx));
 
     char text[] = "new Error()";
     jsval _;
     JS_EvaluateScript(cx, global, text, strlen(text), "", 0, &_);
 
     return JSTRAP_CONTINUE;
 }
 
@@ -145,26 +145,26 @@ BEGIN_TEST(testDebugger_throwHook)
     JS_SetOptions(cx, oldopts);
     return true;
 }
 END_TEST(testDebugger_throwHook)
 
 BEGIN_TEST(testDebugger_debuggerObjectVsDebugMode)
 {
     CHECK(JS_DefineDebuggerObject(cx, global));
-    JS::RootedObject debuggee(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    js::RootedObject debuggee(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
     CHECK(debuggee);
 
     {
         JSAutoCompartment ae(cx, debuggee);
         CHECK(JS_SetDebugMode(cx, true));
         CHECK(JS_InitStandardClasses(cx, debuggee));
     }
 
-    JS::RootedObject debuggeeWrapper(cx, debuggee);
+    js::RootedObject debuggeeWrapper(cx, debuggee);
     CHECK(JS_WrapObject(cx, debuggeeWrapper.address()));
     jsval v = OBJECT_TO_JSVAL(debuggeeWrapper);
     CHECK(JS_SetProperty(cx, global, "debuggee", &v));
 
     EVAL("var dbg = new Debugger(debuggee);\n"
          "var hits = 0;\n"
          "dbg.onDebuggerStatement = function () { hits++; };\n"
          "debuggee.eval('debugger;');\n"
@@ -185,24 +185,24 @@ BEGIN_TEST(testDebugger_debuggerObjectVs
     return true;
 }
 END_TEST(testDebugger_debuggerObjectVsDebugMode)
 
 BEGIN_TEST(testDebugger_newScriptHook)
 {
     // Test that top-level indirect eval fires the newScript hook.
     CHECK(JS_DefineDebuggerObject(cx, global));
-    JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    js::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
     CHECK(g);
     {
         JSAutoCompartment ae(cx, g);
         CHECK(JS_InitStandardClasses(cx, g));
     }
 
-    JS::RootedObject gWrapper(cx, g);
+    js::RootedObject gWrapper(cx, g);
     CHECK(JS_WrapObject(cx, gWrapper.address()));
     jsval v = OBJECT_TO_JSVAL(gWrapper);
     CHECK(JS_SetProperty(cx, global, "g", &v));
 
     EXEC("var dbg = Debugger(g);\n"
          "var hits = 0;\n"
          "dbg.onNewScript = function (s) {\n"
          "    hits += Number(s instanceof Debugger.Script);\n"
--- a/js/src/jsapi-tests/testDeepFreeze.cpp
+++ b/js/src/jsapi-tests/testDeepFreeze.cpp
@@ -7,34 +7,34 @@
 
 
 #include "tests.h"
 
 BEGIN_TEST(testDeepFreeze_bug535703)
 {
     jsval v;
     EVAL("var x = {}; x;", &v);
-    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(v));
+    js::RootedObject obj(cx, JSVAL_TO_OBJECT(v));
     CHECK(JS_DeepFreezeObject(cx, obj));  // don't crash
     EVAL("Object.isFrozen(x)", &v);
     CHECK_SAME(v, JSVAL_TRUE);
     return true;
 }
 END_TEST(testDeepFreeze_bug535703)
 
 BEGIN_TEST(testDeepFreeze_deep)
 {
     jsval a, o;
     EXEC("var a = {}, o = a;\n"
          "for (var i = 0; i < 5000; i++)\n"
          "    a = {x: a, y: a};\n");
     EVAL("a", &a);
     EVAL("o", &o);
 
-    JS::RootedObject aobj(cx, JSVAL_TO_OBJECT(a));
+    js::RootedObject aobj(cx, JSVAL_TO_OBJECT(a));
     CHECK(JS_DeepFreezeObject(cx, aobj));
 
     jsval b;
     EVAL("Object.isFrozen(a)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     EVAL("Object.isFrozen(o)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     return true;
@@ -43,17 +43,17 @@ END_TEST(testDeepFreeze_deep)
 
 BEGIN_TEST(testDeepFreeze_loop)
 {
     jsval x, y;
     EXEC("var x = [], y = {x: x}; y.y = y; x.push(x, y);");
     EVAL("x", &x);
     EVAL("y", &y);
 
-    JS::RootedObject xobj(cx, JSVAL_TO_OBJECT(x));
+    js::RootedObject xobj(cx, JSVAL_TO_OBJECT(x));
     CHECK(JS_DeepFreezeObject(cx, xobj));
 
     jsval b;
     EVAL("Object.isFrozen(x)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     EVAL("Object.isFrozen(y)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     return true;
--- a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
+++ b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
@@ -13,32 +13,32 @@ native(JSContext *cx, unsigned argc, jsv
 {
     return JS_TRUE;
 }
 
 static const char PROPERTY_NAME[] = "foo";
 
 BEGIN_TEST(testDefineGetterSetterNonEnumerable)
 {
-    JS::RootedValue vobj(cx);
-    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
+    js::RootedValue vobj(cx);
+    js::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     CHECK(obj);
     vobj = OBJECT_TO_JSVAL(obj);
 
     JSFunction *funGet = JS_NewFunction(cx, native, 0, 0, NULL, "get");
     CHECK(funGet);
-    JS::RootedObject funGetObj(cx, JS_GetFunctionObject(funGet));
-    JS::RootedValue vget(cx, OBJECT_TO_JSVAL(funGetObj));
+    js::RootedObject funGetObj(cx, JS_GetFunctionObject(funGet));
+    js::RootedValue vget(cx, OBJECT_TO_JSVAL(funGetObj));
 
     JSFunction *funSet = JS_NewFunction(cx, native, 1, 0, NULL, "set");
     CHECK(funSet);
-    JS::RootedObject funSetObj(cx, JS_GetFunctionObject(funSet));
-    JS::RootedValue vset(cx, OBJECT_TO_JSVAL(funSetObj));
+    js::RootedObject funSetObj(cx, JS_GetFunctionObject(funSet));
+    js::RootedValue vset(cx, OBJECT_TO_JSVAL(funSetObj));
 
-    JS::RootedObject vObject(cx, JSVAL_TO_OBJECT(vobj));
+    js::RootedObject vObject(cx, JSVAL_TO_OBJECT(vobj));
     CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JSVAL_VOID,
                             JS_DATA_TO_FUNC_PTR(JSPropertyOp, (JSObject*) funGetObj),
                             JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, (JSObject*) funSetObj),
                             JSPROP_GETTER | JSPROP_SETTER | JSPROP_ENUMERATE));
 
     CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JSVAL_VOID,
--- a/js/src/jsapi-tests/testDefineProperty.cpp
+++ b/js/src/jsapi-tests/testDefineProperty.cpp
@@ -5,20 +5,20 @@
  * 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 "tests.h"
 
 BEGIN_TEST(testDefineProperty_bug564344)
 {
-    JS::RootedValue x(cx);
+    js::RootedValue x(cx);
     EVAL("function f() {}\n"
          "var x = {p: f};\n"
          "x.p();  // brand x's scope\n"
          "x;", x.address());
 
-    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(x));
+    js::RootedObject obj(cx, JSVAL_TO_OBJECT(x));
     for (int i = 0; i < 2; i++)
         CHECK(JS_DefineProperty(cx, obj, "q", JSVAL_VOID, NULL, NULL, JSPROP_SHARED));
     return true;
 }
 END_TEST(testDefineProperty_bug564344)
--- a/js/src/jsapi-tests/testErrorCopying.cpp
+++ b/js/src/jsapi-tests/testErrorCopying.cpp
@@ -21,15 +21,15 @@ my_ErrorReporter(JSContext *cx, const ch
 }
 
 BEGIN_TEST(testErrorCopying_columnCopied)
 {
         //0         1         2
         //0123456789012345678901234567
     EXEC("function check() { Object; foo; }");
 
-    JS::RootedValue rval(cx);
+    js::RootedValue rval(cx);
     JS_SetErrorReporter(cx, my_ErrorReporter);
     CHECK(!JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
     CHECK(column == 27);
     return true;
 }
 END_TEST(testErrorCopying_columnCopied)
--- a/js/src/jsapi-tests/testFunctionProperties.cpp
+++ b/js/src/jsapi-tests/testFunctionProperties.cpp
@@ -5,22 +5,22 @@
  * 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 "tests.h"
 
 BEGIN_TEST(testFunctionProperties)
 {
-    JS::RootedValue x(cx);
+    js::RootedValue x(cx);
     EVAL("(function f() {})", x.address());
 
-    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(x));
+    js::RootedObject obj(cx, JSVAL_TO_OBJECT(x));
 
-    JS::RootedValue y(cx);
+    js::RootedValue y(cx);
     CHECK(JS_GetProperty(cx, obj, "arguments", y.address()));
     CHECK_SAME(y, JSVAL_NULL);
 
     CHECK(JS_GetProperty(cx, obj, "caller", y.address()));
     CHECK_SAME(y, JSVAL_NULL);
 
     return true;
 }
--- a/js/src/jsapi-tests/testGCOutOfMemory.cpp
+++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp
@@ -16,17 +16,17 @@ ErrorCounter(JSContext *cx, const char *
 {
     ++errorCount;
 }
 
 BEGIN_TEST(testGCOutOfMemory)
 {
     JS_SetErrorReporter(cx, ErrorCounter);
 
-    JS::RootedValue root(cx);
+    js::RootedValue root(cx);
 
     static const char source[] =
         "var max = 0; (function() {"
         "    var array = [];"
         "    for (; ; ++max)"
         "        array.push({});"
         "    array = []; array.push(0);"
         "})();";
--- a/js/src/jsapi-tests/testGetPropertyDefault.cpp
+++ b/js/src/jsapi-tests/testGetPropertyDefault.cpp
@@ -21,17 +21,17 @@ stringToId(JSContext *cx, const char *s,
     return JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
 }
 
 BEGIN_TEST(testGetPropertyDefault_bug594060)
 {
     {
         // Check JS_GetPropertyDefault
 
-        JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
+        js::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
         CHECK(obj);
 
         jsval v0 = JSVAL_TRUE;
         CHECK(JS_SetProperty(cx, obj, "here", &v0));
 
         jsval v1;
         CHECK(JS_GetPropertyDefault(cx, obj, "here", JSVAL_FALSE, &v1));
         CHECK(JSVAL_IS_TRUE(v1));
@@ -39,17 +39,17 @@ BEGIN_TEST(testGetPropertyDefault_bug594
         jsval v2;
         CHECK(JS_GetPropertyDefault(cx, obj, "nothere", JSVAL_FALSE, &v2));
         CHECK(JSVAL_IS_FALSE(v2));
     }
 
     {
         // Check JS_GetPropertyByIdDefault
 
-        JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
+        js::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
         CHECK(obj);
 
         jsid hereid;
         CHECK(stringToId(cx, "here", &hereid));
 
         jsid nothereid;
         CHECK(stringToId(cx, "nothere", &nothereid));
 
--- a/js/src/jsapi-tests/testIntString.cpp
+++ b/js/src/jsapi-tests/testIntString.cpp
@@ -6,17 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 #include "vm/String.h"
 
 BEGIN_TEST(testIntString_bug515273)
 {
-    JS::RootedValue v(cx);
+    js::RootedValue v(cx);
 
     EVAL("'1';", v.address());
     JSString *str = JSVAL_TO_STRING(v);
     CHECK(JS_StringHasBeenInterned(cx, str));
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "1"));
 
     EVAL("'42';", v.address());
     str = JSVAL_TO_STRING(v);
--- a/js/src/jsapi-tests/testJSEvaluateScript.cpp
+++ b/js/src/jsapi-tests/testJSEvaluateScript.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et tw=99:
  */
 
 #include "tests.h"
 
 BEGIN_TEST(testJSEvaluateScript)
 {
-    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, global));
+    js::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, global));
     CHECK(obj);
 
     uint32_t options = JS_GetOptions(cx);
     CHECK(options & JSOPTION_VAROBJFIX);
 
     static const char src[] = "var x = 5;";
 
     JS::Value retval;
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -9,45 +9,45 @@
 #include "tests.h"
 #include "jsfun.h"  // for js::IsInternalFunctionObject
 
 #include "jsobjinlines.h"
 
 BEGIN_TEST(testLookup_bug522590)
 {
     // Define a function that makes method-bearing objects.
-    JS::RootedValue x(cx);
+    js::RootedValue x(cx);
     EXEC("function mkobj() { return {f: function () {return 2;}} }");
 
     // Calling mkobj() multiple times must create multiple functions in ES5.
     EVAL("mkobj().f !== mkobj().f", x.address());
     CHECK_SAME(x, JSVAL_TRUE);
 
     // Now make x.f a method.
     EVAL("mkobj()", x.address());
-    JS::RootedObject xobj(cx, JSVAL_TO_OBJECT(x));
+    js::RootedObject xobj(cx, JSVAL_TO_OBJECT(x));
 
     // This lookup must not return an internal function object.
-    JS::RootedValue r(cx);
+    js::RootedValue r(cx);
     CHECK(JS_LookupProperty(cx, xobj, "f", r.address()));
     CHECK(r.isObject());
     JSObject *funobj = &r.toObject();
     CHECK(funobj->isFunction());
     CHECK(!js::IsInternalFunctionObject(funobj));
 
     return true;
 }
 END_TEST(testLookup_bug522590)
 
 JSBool
 document_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                  JSMutableHandleObject objp)
 {
     // If id is "all", and we're not detecting, resolve document.all=true.
-    JS::RootedValue v(cx);
+    js::RootedValue v(cx);
     if (!JS_IdToValue(cx, id, v.address()))
         return false;
     if (JSVAL_IS_STRING(v)) {
         JSString *str = JSVAL_TO_STRING(v);
         JSFlatString *flatStr = JS_FlattenString(cx, str);
         if (!flatStr)
             return false;
         if (JS_FlatStringEqualsAscii(flatStr, "all") && !(flags & JSRESOLVE_DETECTING)) {
@@ -63,19 +63,19 @@ document_resolve(JSContext *cx, JSHandle
 static JSClass document_class = {
     "document", JSCLASS_NEW_RESOLVE,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, (JSResolveOp) document_resolve, JS_ConvertStub
 };
 
 BEGIN_TEST(testLookup_bug570195)
 {
-    JS::RootedObject obj(cx, JS_NewObject(cx, &document_class, NULL, NULL));
+    js::RootedObject obj(cx, JS_NewObject(cx, &document_class, NULL, NULL));
     CHECK(obj);
     CHECK(JS_DefineProperty(cx, global, "document", OBJECT_TO_JSVAL(obj), NULL, NULL, 0));
-    JS::RootedValue v(cx);
+    js::RootedValue v(cx);
     EVAL("document.all ? true : false", v.address());
     CHECK_SAME(v, JSVAL_FALSE);
     EVAL("document.hasOwnProperty('all')", v.address());
     CHECK_SAME(v, JSVAL_FALSE);
     return true;
 }
 END_TEST(testLookup_bug570195)
--- a/js/src/jsapi-tests/testNewObject.cpp
+++ b/js/src/jsapi-tests/testNewObject.cpp
@@ -12,17 +12,17 @@
 
 const size_t N = 1000;
 static jsval argv[N];
 
 static JSBool
 constructHook(JSContext *cx, unsigned argc, jsval *vp)
 {
     // Check that arguments were passed properly from JS_New.
-    JS::RootedObject callee(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
+    js::RootedObject callee(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
     JSObject *obj = JS_NewObjectForConstructor(cx, js::Jsvalify(&js::ObjectClass), vp);
     if (!obj) {
         JS_ReportError(cx, "test failed, could not construct object");
         return false;
     }
     if (strcmp(JS_GetClass(obj)->name, "Object") != 0) {
         JS_ReportError(cx, "test failed, wrong class for 'this'");
@@ -52,24 +52,24 @@ constructHook(JSContext *cx, unsigned ar
 
 BEGIN_TEST(testNewObject_1)
 {
     // Root the global argv test array. Only the first 2 entries really need to
     // be rooted, since we're only putting integers in the rest.
     CHECK(JS_AddNamedValueRoot(cx, &argv[0], "argv0"));
     CHECK(JS_AddNamedValueRoot(cx, &argv[1], "argv1"));
 
-    JS::RootedValue v(cx);
+    js::RootedValue v(cx);
     EVAL("Array", v.address());
-    JS::RootedObject Array(cx, JSVAL_TO_OBJECT(v));
+    js::RootedObject Array(cx, JSVAL_TO_OBJECT(v));
 
     // With no arguments.
-    JS::RootedObject obj(cx, JS_New(cx, Array, 0, NULL));
+    js::RootedObject obj(cx, JS_New(cx, Array, 0, NULL));
     CHECK(obj);
-    JS::RootedValue rt(cx, OBJECT_TO_JSVAL(obj));
+    js::RootedValue rt(cx, OBJECT_TO_JSVAL(obj));
     CHECK(JS_IsArrayObject(cx, obj));
     uint32_t len;
     CHECK(JS_GetArrayLength(cx, obj, &len));
     CHECK_EQUAL(len, 0);
 
     // With one argument.
     argv[0] = INT_TO_JSVAL(4);
     obj = JS_New(cx, Array, 1, argv);
@@ -94,19 +94,19 @@ BEGIN_TEST(testNewObject_1)
     // With JSClass.construct.
     static JSClass cls = {
         "testNewObject_1",
         0,
         JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
         NULL, NULL, NULL, constructHook
     };
-    JS::RootedObject ctor(cx, JS_NewObject(cx, &cls, NULL, NULL));
+    js::RootedObject ctor(cx, JS_NewObject(cx, &cls, NULL, NULL));
     CHECK(ctor);
-    JS::RootedValue rt2(cx, OBJECT_TO_JSVAL(ctor));
+    js::RootedValue rt2(cx, OBJECT_TO_JSVAL(ctor));
     obj = JS_New(cx, ctor, 3, argv);
     CHECK(obj);
     CHECK(JS_GetElement(cx, ctor, 0, v.address()));
     CHECK_SAME(v, JSVAL_ZERO);
 
     JS_RemoveValueRoot(cx, &argv[0]);
     JS_RemoveValueRoot(cx, &argv[1]);
 
--- a/js/src/jsapi-tests/testOps.cpp
+++ b/js/src/jsapi-tests/testOps.cpp
@@ -50,16 +50,16 @@ static JSFunctionSpec s_functions[] =
 
 BEGIN_TEST(testOps_bug559006)
 {
     CHECK(JS_DefineFunctions(cx, global, s_functions));
 
     EXEC("function main() { while(1) return 0 + createMyObject(); }");
 
     for (int i = 0; i < 9; i++) {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         CHECK(JS_CallFunctionName(cx, global, "main", 0, NULL, rval.address()));
         CHECK_SAME(rval, INT_TO_JSVAL(123));
     }
     return true;
 }
 END_TEST(testOps_bug559006)
 
--- a/js/src/jsapi-tests/testOriginPrincipals.cpp
+++ b/js/src/jsapi-tests/testOriginPrincipals.cpp
@@ -56,17 +56,17 @@ bool
 eval(const char *asciiChars, JSPrincipals *principals, JSPrincipals *originPrincipals, jsval *rval)
 {
     size_t len = strlen(asciiChars);
     jschar *chars = new jschar[len+1];
     for (size_t i = 0; i < len; ++i)
         chars[i] = asciiChars[i];
     chars[len] = 0;
 
-    JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), principals));
+    js::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), principals));
     CHECK(global);
     JSAutoCompartment ac(cx, global);
     CHECK(JS_InitStandardClasses(cx, global));
     bool ok = JS_EvaluateUCScriptForPrincipalsVersionOrigin(cx, global,
                                                             principals,
                                                             originPrincipals,
                                                             chars, len, "", 0, rval,
                                                             JSVERSION_DEFAULT);
--- a/js/src/jsapi-tests/testParseJSON.cpp
+++ b/js/src/jsapi-tests/testParseJSON.cpp
@@ -52,17 +52,17 @@ BEGIN_TEST(testParseJSON_success)
     CHECK(TryParse(cx, "0", INT_TO_JSVAL(0)));
     CHECK(TryParse(cx, "1", INT_TO_JSVAL(1)));
     CHECK(TryParse(cx, "-1", INT_TO_JSVAL(-1)));
     CHECK(TryParse(cx, "1", DOUBLE_TO_JSVAL(1)));
     CHECK(TryParse(cx, "1.75", DOUBLE_TO_JSVAL(1.75)));
     CHECK(TryParse(cx, "9e9", DOUBLE_TO_JSVAL(9e9)));
     CHECK(TryParse(cx, "9e99999", DOUBLE_TO_JSVAL(std::numeric_limits<double>::infinity())));
 
-    JS::Rooted<JSFlatString*> str(cx);
+    js::Rooted<JSFlatString*> str(cx);
 
     const jschar emptystr[] = { '\0' };
     str = js_NewStringCopyN(cx, emptystr, 0);
     CHECK(str);
     CHECK(TryParse(cx, "\"\"", STRING_TO_JSVAL(str)));
 
     const jschar nullstr[] = { '\0' };
     str = NewString(cx, nullstr);
@@ -78,18 +78,18 @@ BEGIN_TEST(testParseJSON_success)
     const jschar newlinestr[] = { '\n', };
     str = NewString(cx, newlinestr);
     CHECK(str);
     CHECK(TryParse(cx, "\"\\n\"", STRING_TO_JSVAL(str)));
     CHECK(TryParse(cx, "\"\\u000A\"", STRING_TO_JSVAL(str)));
 
 
     // Arrays
-    JS::RootedValue v(cx), v2(cx);
-    JS::RootedObject obj(cx);
+    js::RootedValue v(cx), v2(cx);
+    js::RootedObject obj(cx);
 
     CHECK(Parse(cx, "[]", v.address()));
     CHECK(!JSVAL_IS_PRIMITIVE(v));
     obj = JSVAL_TO_OBJECT(v);
     CHECK(JS_IsArrayObject(cx, obj));
     CHECK(JS_GetProperty(cx, obj, "length", v2.address()));
     CHECK_SAME(v2, JSVAL_ZERO);
 
@@ -127,17 +127,17 @@ Parse(JSContext *cx, const char (&input)
     CHECK(JS_ParseJSON(cx, str.chars(), str.length(), vp));
     return true;
 }
 
 template<size_t N> inline bool
 TryParse(JSContext *cx, const char (&input)[N], const jsval &expectedArg)
 {
     AutoInflatedString str(cx);
-    JS::RootedValue expected(cx, expectedArg);
+    js::RootedValue expected(cx, expectedArg);
     jsval v;
     str = input;
     CHECK(JS_ParseJSON(cx, str.chars(), str.length(), &v));
     CHECK_SAME(v, expected);
     return true;
 }
 END_TEST(testParseJSON_success)
 
@@ -210,32 +210,32 @@ Censor(JSContext *cx, unsigned argc, jsv
     return true;
 }
 
 BEGIN_TEST(testParseJSON_reviver)
 {
     JSFunction *fun = JS_NewFunction(cx, Censor, 0, 0, global, "censor");
     CHECK(fun);
 
-    JS::RootedValue filter(cx, OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)));
+    js::RootedValue filter(cx, OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)));
 
     CHECK(TryParse(cx, "true", filter));
     CHECK(TryParse(cx, "false", filter));
     CHECK(TryParse(cx, "null", filter));
     CHECK(TryParse(cx, "1", filter));
     CHECK(TryParse(cx, "1.75", filter));
     CHECK(TryParse(cx, "[]", filter));
     CHECK(TryParse(cx, "[1]", filter));
     CHECK(TryParse(cx, "{}", filter));
     return true;
 }
 
 template<size_t N> inline bool
 TryParse(JSContext *cx, const char (&input)[N], JS::HandleValue filter)
 {
     AutoInflatedString str(cx);
-    JS::RootedValue v(cx);
+    js::RootedValue v(cx);
     str = input;
     CHECK(JS_ParseJSONWithReviver(cx, str.chars(), str.length(), filter, v.address()));
     CHECK_SAME(v, JSVAL_NULL);
     return true;
 }
 END_TEST(testParseJSON_reviver)
--- a/js/src/jsapi-tests/testProfileStrings.cpp
+++ b/js/src/jsapi-tests/testProfileStrings.cpp
@@ -37,17 +37,17 @@ test_fn(JSContext *cx, unsigned argc, js
     max_stack = psize;
     return JS_TRUE;
 }
 
 static JSBool
 test_fn2(JSContext *cx, unsigned argc, jsval *vp)
 {
     jsval r;
-    JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+    js::RootedObject global(cx, JS_GetGlobalObject(cx));
     return JS_CallFunctionName(cx, global, "d", 0, NULL, &r);
 }
 
 static JSBool
 enable(JSContext *cx, unsigned argc, jsval *vp)
 {
     js::EnableRuntimeProfilingStack(cx->runtime, true);
     return JS_TRUE;
@@ -77,17 +77,17 @@ static JSFunctionSpec ptestFunctions[] =
     JS_FS("disable", disable, 0, 0),
     JS_FS_END
 };
 
 static JSObject*
 initialize(JSContext *cx)
 {
     js::SetRuntimeProfilingStack(cx->runtime, pstack, &psize, 10);
-    JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+    js::RootedObject global(cx, JS_GetGlobalObject(cx));
     return JS_InitClass(cx, global, NULL, &ptestClass, Prof, 0,
                         NULL, ptestFunctions, NULL, NULL);
 }
 
 BEGIN_TEST(testProfileStrings_isCalledWithInterpreter)
 {
     CHECK(initialize(cx));
 
@@ -98,42 +98,42 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     EXEC("function c() { d(); }");
     EXEC("function b() { c(); }");
     EXEC("function a() { b(); }");
     EXEC("function check() { var p = new Prof(); p.test_fn(); a(); }");
     EXEC("function check2() { var p = new Prof(); p.test_fn2(); }");
 
     reset(cx);
     {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 8);
         /* Make sure the stack resets and we added no new entries */
         max_stack = 0;
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 8);
     }
     reset(cx);
     {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         CHECK(JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.address()));
         CHECK(cx->runtime->spsProfiler.stringsCount() == 5);
         CHECK(max_stack >= 6);
         CHECK(psize == 0);
     }
     js::EnableRuntimeProfilingStack(cx->runtime, false);
     js::SetRuntimeProfilingStack(cx->runtime, pstack, &psize, 3);
     reset(cx);
     {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         pstack[3].setLabel((char*) 1234);
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK((size_t) pstack[3].label() == 1234);
         CHECK(max_stack >= 8);
         CHECK(psize == 0);
     }
     return true;
 }
@@ -152,17 +152,17 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     EXEC("function c() { d(); }");
     EXEC("function b() { c(); }");
     EXEC("function a() { b(); }");
     EXEC("function check() { var p = new Prof(); p.test_fn(); a(); }");
     EXEC("function check2() { var p = new Prof(); p.test_fn2(); }");
 
     reset(cx);
     {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
 
         /* Make sure the stack resets and we added no new entries */
         uint32_t cnt = cx->runtime->spsProfiler.stringsCount();
         max_stack = 0;
@@ -172,17 +172,17 @@ BEGIN_TEST(testProfileStrings_isCalledWi
         CHECK(max_stack >= 8);
     }
 
     js::EnableRuntimeProfilingStack(cx->runtime, false);
     js::SetRuntimeProfilingStack(cx->runtime, pstack, &psize, 3);
     reset(cx);
     {
         /* Limit the size of the stack and make sure we don't overflow */
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         pstack[3].setLabel((char*) 1234);
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
         CHECK((size_t) pstack[3].label() == 1234);
     }
     return true;
 }
@@ -192,17 +192,17 @@ BEGIN_TEST(testProfileStrings_isCalledWh
 {
     CHECK(initialize(cx));
     JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS);
 
     EXEC("function check2() { throw 'a'; }");
 
     reset(cx);
     {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.address());
         CHECK(psize == 0);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 1);
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWhenError)
@@ -213,50 +213,50 @@ BEGIN_TEST(testProfileStrings_worksWhenE
     JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS);
 
     EXEC("function b(p) { p.test_fn(); }");
     EXEC("function a() { var p = new Prof(); p.enable(); b(p); }");
     reset(cx);
     js::EnableRuntimeProfilingStack(cx->runtime, false);
     {
         /* enable it in the middle of JS and make sure things check out */
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         JS_CallFunctionName(cx, global, "a", 0, NULL, rval.address());
         CHECK(psize == 0);
         CHECK(max_stack >= 1);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 1);
     }
 
     EXEC("function d(p) { p.disable(); }");
     EXEC("function c() { var p = new Prof(); d(p); }");
     reset(cx);
     {
         /* now disable in the middle of js */
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         JS_CallFunctionName(cx, global, "c", 0, NULL, rval.address());
         CHECK(psize == 0);
     }
 
     EXEC("function e() { var p = new Prof(); d(p); p.enable(); b(p); }");
     reset(cx);
     {
         /* now disable in the middle of js, but re-enable before final exit */
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         JS_CallFunctionName(cx, global, "e", 0, NULL, rval.address());
         CHECK(psize == 0);
         CHECK(max_stack >= 3);
     }
 
     EXEC("function h() { }");
     EXEC("function g(p) { p.disable(); for (var i = 0; i < 100; i++) i++; }");
     EXEC("function f() { g(new Prof()); }");
     reset(cx);
     cx->runtime->spsProfiler.enableSlowAssertions(false);
     {
-        JS::RootedValue rval(cx);
+        js::RootedValue rval(cx);
         /* disable, and make sure that if we try to re-enter the JIT the pop
          * will still happen */
         JS_CallFunctionName(cx, global, "f", 0, NULL, rval.address());
         CHECK(psize == 0);
     }
     return true;
 }
 END_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
--- a/js/src/jsapi-tests/testRegExp.cpp
+++ b/js/src/jsapi-tests/testRegExp.cpp
@@ -1,34 +1,34 @@
 /* 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 "tests.h"
 
 BEGIN_TEST(testObjectIsRegExp)
 {
-    JS::RootedValue val(cx);
+    js::RootedValue val(cx);
 
     EVAL("new Object", val.address());
-    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val));
+    js::RootedObject obj(cx, JSVAL_TO_OBJECT(val));
     CHECK(!JS_ObjectIsRegExp(cx, obj));
 
     EVAL("/foopy/", val.address());
     obj = JSVAL_TO_OBJECT(val);
     CHECK(JS_ObjectIsRegExp(cx, obj));
 
     return true;
 }
 END_TEST(testObjectIsRegExp)
 
 BEGIN_TEST(testGetRegExpFlags)
 {
-    JS::RootedValue val(cx);
-    JS::RootedObject obj(cx);
+    js::RootedValue val(cx);
+    js::RootedObject obj(cx);
 
     EVAL("/foopy/", val.address());
     obj = JSVAL_TO_OBJECT(val);
     CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), 0);
 
     EVAL("/foopy/g", val.address());
     obj = JSVAL_TO_OBJECT(val);
     CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), JSREG_GLOB);
@@ -38,18 +38,18 @@ BEGIN_TEST(testGetRegExpFlags)
     CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), (JSREG_FOLD | JSREG_GLOB));
 
     return true;
 }
 END_TEST(testGetRegExpFlags)
 
 BEGIN_TEST(testGetRegExpSource)
 {
-    JS::RootedValue val(cx);
-    JS::RootedObject obj(cx);
+    js::RootedValue val(cx);
+    js::RootedObject obj(cx);
 
     EVAL("/foopy/", val.address());
     obj = JSVAL_TO_OBJECT(val);
     JSString *source = JS_GetRegExpSource(cx, obj);
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(source), "foopy"));
 
     return true;
 }
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -16,17 +16,17 @@ struct ScriptObjectFixture : public JSAP
     ScriptObjectFixture()
     {
         for (int i = 0; i < code_size; i++)
             uc_code[i] = code[i];
     }
 
     bool tryScript(JS::HandleObject global, JSScript *scriptArg)
     {
-        JS::RootedScript script(cx, scriptArg);
+        js::RootedScript script(cx, scriptArg);
         CHECK(script);
 
         JS_GC(rt);
 
         /* After a garbage collection, the script should still work. */
         jsval result;
         CHECK(JS_ExecuteScript(cx, global, script, &result));
 
--- a/js/src/jsapi-tests/testSetProperty.cpp
+++ b/js/src/jsapi-tests/testSetProperty.cpp
@@ -12,19 +12,19 @@ static JSBool
 nativeGet(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
 {
     vp.set(INT_TO_JSVAL(17));
     return JS_TRUE;
 }
 
 BEGIN_TEST(testSetProperty_NativeGetterStubSetter)
 {
-    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
+    js::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     CHECK(obj);
-    JS::RootedValue vobj(cx, OBJECT_TO_JSVAL(obj));
+    js::RootedValue vobj(cx, OBJECT_TO_JSVAL(obj));
 
     CHECK(JS_DefineProperty(cx, global, "globalProp", vobj,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE));
 
     CHECK(JS_DefineProperty(cx, obj, "prop", JSVAL_VOID,
                             nativeGet, JS_StrictPropertyStub,
                             JSPROP_SHARED));
--- a/js/src/jsapi-tests/testTrap.cpp
+++ b/js/src/jsapi-tests/testTrap.cpp
@@ -29,33 +29,33 @@ BEGIN_TEST(testTrap_gc)
 "while (i < 10) {\n"
 "    sum += i;\n"
 "    ++i;\n"
 "}\n"
 "({ result: sum });\n"
         ;
 
     // compile
-    JS::RootedScript script(cx, JS_CompileScript(cx, global, source, strlen(source), __FILE__, 1));
+    js::RootedScript script(cx, JS_CompileScript(cx, global, source, strlen(source), __FILE__, 1));
     CHECK(script);
 
     // execute
-    JS::RootedValue v2(cx);
+    js::RootedValue v2(cx);
     CHECK(JS_ExecuteScript(cx, global, script, v2.address()));
     CHECK(v2.isObject());
     CHECK_EQUAL(emptyTrapCallCount, 0);
 
     // Enable debug mode
     CHECK(JS_SetDebugMode(cx, JS_TRUE));
 
     static const char trapClosureText[] = "some trap closure";
 
     // scope JSScript  usage to make sure that it is not used after
     // JS_ExecuteScript. This way we avoid using Anchor.
-    JS::RootedString trapClosure(cx);
+    js::RootedString trapClosure(cx);
     {
         jsbytecode *line2 = JS_LineNumberToPC(cx, script, 1);
         CHECK(line2);
 
         jsbytecode *line6 = JS_LineNumberToPC(cx, script, 5);
         CHECK(line2);
 
         trapClosure = JS_NewStringCopyZ(cx, trapClosureText);
--- a/js/src/jsapi-tests/testTypedArrays.cpp
+++ b/js/src/jsapi-tests/testTypedArrays.cpp
@@ -25,17 +25,18 @@ BEGIN_TEST(testTypedArrays)
         TestPlainTypedArray<JS_NewUint32Array, uint32_t, JS_GetUint32ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewFloat32Array, float, JS_GetFloat32ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewFloat64Array, double, JS_GetFloat64ArrayData>(cx);
 
     size_t nbytes = sizeof(double) * 8;
     RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
     CHECK(JS_IsArrayBufferObject(buffer, cx));
 
-    RootedObject proto(cx, JS_GetPrototype(buffer));
+    RootedObject proto(cx);
+    JS_GetPrototype(cx, buffer, proto.address());
     CHECK(!JS_IsArrayBufferObject(proto, cx));
     RootedObject dummy(cx, JS_GetParent(proto));
     CHECK(!JS_IsArrayBufferObject(dummy, cx));
 
     CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer, cx), nbytes);
     memset(JS_GetArrayBufferData(buffer, cx), 1, nbytes);
 
     ok = ok &&
@@ -55,17 +56,18 @@ BEGIN_TEST(testTypedArrays)
 template<JSObject *Create(JSContext *, uint32_t),
          typename Element,
          Element *GetData(JSObject *, JSContext *)>
 bool
 TestPlainTypedArray(JSContext *cx)
 {
     RootedObject array(cx, Create(cx, 7));
     CHECK(JS_IsTypedArrayObject(array, cx));
-    RootedObject proto(cx, JS_GetPrototype(array));
+    RootedObject proto(cx);
+    JS_GetPrototype(cx, array, proto.address());
     CHECK(!JS_IsTypedArrayObject(proto, cx));
     RootedObject dummy(cx, JS_GetParent(proto));
     CHECK(!JS_IsTypedArrayObject(dummy, cx));
 
     CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), 7);
     CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
     CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), sizeof(Element) * 7);
 
--- a/js/src/jsapi-tests/testValueABI.cpp
+++ b/js/src/jsapi-tests/testValueABI.cpp
@@ -24,17 +24,17 @@ C_GetEmptyStringValue(JSContext *cx);
 
 extern size_t
 C_jsvalAlignmentTest();
 
 }
 
 BEGIN_TEST(testValueABI_retparam)
 {
-    JS::RootedObject obj(cx, JS_GetGlobalObject(cx));
+    js::RootedObject obj(cx, JS_GetGlobalObject(cx));
     jsval v = OBJECT_TO_JSVAL(obj);
     obj = NULL;
     CHECK(C_ValueToObject(cx, v, obj.address()));
     JSBool equal;
     CHECK(JS_StrictlyEqual(cx, v, OBJECT_TO_JSVAL(obj), &equal));
     CHECK(equal);
 
     v = C_GetEmptyStringValue(cx);
--- a/js/src/jsapi-tests/testVersion.cpp
+++ b/js/src/jsapi-tests/testVersion.cpp
@@ -34,30 +34,30 @@ struct VersionFixture : public JSAPITest
     JSVersion captured;
 
     virtual bool init() {
         if (!JSAPITest::init())
             return false;
         JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ALLOW_XML);
         callbackData = this;
         captured = JSVERSION_UNKNOWN;
-        JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+        js::RootedObject global(cx, JS_GetGlobalObject(cx));
         return JS_DefineFunction(cx, global, "checkVersionHasMoarXML", CheckVersionHasMoarXML, 0, 0) &&
                JS_DefineFunction(cx, global, "disableMoarXMLOption", DisableMoarXMLOption, 0, 0) &&
                JS_DefineFunction(cx, global, "callSetVersion17", CallSetVersion17, 0, 0) &&
                JS_DefineFunction(cx, global, "checkNewScriptNoXML", CheckNewScriptNoXML, 0, 0) &&
                JS_DefineFunction(cx, global, "overrideVersion15", OverrideVersion15, 0, 0) &&
                JS_DefineFunction(cx, global, "captureVersion", CaptureVersion, 0, 0) &&
                JS_DefineFunction(cx, global, "checkOverride", CheckOverride, 1, 0) &&
                JS_DefineFunction(cx, global, "evalScriptVersion16",
                                  EvalScriptVersion16, 0, 0);
     }
 
     JSScript *fakeScript(const char *contents, size_t length) {
-        JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+        js::RootedObject global(cx, JS_GetGlobalObject(cx));
         return JS_CompileScript(cx, global, contents, length, "<test>", 1);
     }
 
     bool hasMoarXML(unsigned version) {
         return VersionHasMoarXML(JSVersion(version));
     }
 
     bool hasMoarXML(JSScript *script) {
@@ -95,17 +95,17 @@ struct VersionFixture : public JSAPITest
         CHECK(JS_GetVersion(cx) != version);
         JS_SetVersion(cx, version);
         return true;
     }
 
     bool evalVersion(const jschar *chars, size_t len, JSVersion version) {
         CHECK(JS_GetVersion(cx) != version);
         jsval rval;
-        JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+        js::RootedObject global(cx, JS_GetGlobalObject(cx));
         CHECK(JS_EvaluateUCScriptForPrincipalsVersion(
                 cx, global, NULL, chars, len, "<test>", 0, &rval, version));
         return true;
     }
 
     bool toggleMoarXML(bool shouldEnable) {
         CHECK_EQUAL(hasMoarXML(), !shouldEnable);
         JS_ToggleOptions(cx, JSOPTION_MOAR_XML);
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -129,17 +129,17 @@ enum TestCase {
 };
 
 JSScript *createScriptViaXDR(JSPrincipals *prin, JSPrincipals *orig, int testCase)
 {
     const char src[] =
         "function f() { return 1; }\n"
         "f;\n";
 
-    JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+    js::RootedObject global(cx, JS_GetGlobalObject(cx));
     JSScript *script = CompileScriptForPrincipalsVersionOrigin(cx, global, prin, orig,
                                                                src, strlen(src), "test", 1,
                                                                JSVERSION_DEFAULT);
     if (!script)
         return NULL;
 
     if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
         script = FreezeThaw(cx, script);
@@ -148,17 +148,17 @@ JSScript *createScriptViaXDR(JSPrincipal
         if (testCase == TEST_SCRIPT)
             return script;
     }
 
     JS::Value v;
     JSBool ok = JS_ExecuteScript(cx, global, script, &v);
     if (!ok || !v.isObject())
         return NULL;
-    JS::RootedObject funobj(cx, &v.toObject());
+    js::RootedObject funobj(cx, &v.toObject());
     if (testCase == TEST_FUNCTION) {
         funobj = FreezeThaw(cx, funobj);
         if (!funobj)
             return NULL;
     }
     return GetScript(cx, funobj);
 }
 
@@ -180,17 +180,17 @@ BEGIN_TEST(testXDR_atline)
     CHECK(script = FreezeThaw(cx, script));
     CHECK(!strcmp("bar", JS_GetScriptFilename(cx, script)));
 
     JS::Value v;
     JSBool ok = JS_ExecuteScript(cx, global, script, &v);
     CHECK(ok);
     CHECK(v.isObject());
 
-    JS::RootedObject funobj(cx, &v.toObject());
+    js::RootedObject funobj(cx, &v.toObject());
     script = JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
     CHECK(!strcmp("foo", JS_GetScriptFilename(cx, script)));
 
     return true;
 }
 
 END_TEST(testXDR_atline)
 
@@ -207,25 +207,25 @@ BEGIN_TEST(testXDR_bug506491)
     // compile
     JSScript *script = JS_CompileScript(cx, global, s, strlen(s), __FILE__, __LINE__);
     CHECK(script);
 
     script = FreezeThaw(cx, script);
     CHECK(script);
 
     // execute
-    JS::RootedValue v2(cx);
+    js::RootedValue v2(cx);
     CHECK(JS_ExecuteScript(cx, global, script, v2.address()));
 
     // try to break the Block object that is the parent of f
     JS_GC(rt);
 
     // confirm
     EVAL("f() === 'ok';\n", v2.address());
-    JS::RootedValue trueval(cx, JSVAL_TRUE);
+    js::RootedValue trueval(cx, JSVAL_TRUE);
     CHECK_SAME(v2, trueval);
     return true;
 }
 END_TEST(testXDR_bug506491)
 
 BEGIN_TEST(testXDR_bug516827)
 {
     // compile an empty script
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -19,26 +19,26 @@ bool JSAPITest::init()
         return false;
     cx = createContext();
     if (!cx)
         return false;
 #ifdef JS_GC_ZEAL
     JS_SetGCZeal(cx, 0, 0);
 #endif
     JS_BeginRequest(cx);
-    JS::RootedObject global(cx, createGlobal());
+    js::RootedObject global(cx, createGlobal());
     if (!global)
         return false;
     oldCompartment = JS_EnterCompartment(cx, global);
     return oldCompartment != NULL;
 }
 
 bool JSAPITest::exec(const char *bytes, const char *filename, int lineno)
 {
-    JS::RootedValue v(cx);
+    js::RootedValue v(cx);
     JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&this->global);
     return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, v.address()) ||
         fail(bytes, filename, lineno);
 }
 
 bool JSAPITest::evaluate(const char *bytes, const char *filename, int lineno, jsval *vp)
 {
     JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&this->global);
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -198,17 +198,17 @@ class JSAPITest
 #define CHECK(expr) \
     do { \
         if (!(expr)) \
             return fail("CHECK failed: " #expr, __FILE__, __LINE__); \
     } while (false)
 
     bool fail(JSAPITestString msg = JSAPITestString(), const char *filename = "-", int lineno = 0) {
         if (JS_IsExceptionPending(cx)) {
-            JS::RootedValue v(cx);
+            js::RootedValue v(cx);
             JS_GetPendingException(cx, v.address());
             JS_ClearPendingException(cx);
             JSString *s = JS_ValueToString(cx, v);
             if (s) {
                 JSAutoByteString bytes(cx, s);
                 if (!!bytes)
                     msg += bytes.ptr();
             }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1571,17 +1571,17 @@ JS_TransplantObject(JSContext *cx, JSObj
         // There might already be a wrapper for the original object in
         // the new compartment. If there is, we use its identity and swap
         // in the contents of |target|.
         newIdentity = &p->value.toObject();
 
         // When we remove origv from the wrapper map, its wrapper, newIdentity,
         // must immediately cease to be a cross-compartment wrapper. Neuter it.
         map.remove(p);
-        NukeCrossCompartmentWrapper(newIdentity);
+        NukeCrossCompartmentWrapper(cx, newIdentity);
 
         if (!newIdentity->swap(cx, target))
             return NULL;
     } else {
         // Otherwise, we use |target| for the new identity object.
         newIdentity = target;
     }
 
@@ -1644,17 +1644,17 @@ js_TransplantObjectWithWrapper(JSContext
     if (WrapperMap::Ptr p = map.lookup(origv)) {
         // There is. Make the existing cross-compartment wrapper a same-
         // compartment wrapper.
         newWrapper = &p->value.toObject();
 
         // When we remove origv from the wrapper map, its wrapper, newWrapper,
         // must immediately cease to be a cross-compartment wrapper. Neuter it.
         map.remove(p);
-        NukeCrossCompartmentWrapper(newWrapper);
+        NukeCrossCompartmentWrapper(cx, newWrapper);
 
         if (!newWrapper->swap(cx, targetwrapper))
             return NULL;
     } else {
         // Otherwise, use the passed-in wrapper as the same-compartment wrapper.
         newWrapper = targetwrapper;
     }
 
@@ -1926,17 +1926,20 @@ JS_ResolveStandardClass(JSContext *cx, J
             if (!atom)
                 return false;
             if (idstr == atom) {
                 stdnm = &standard_class_names[i];
                 break;
             }
         }
 
-        if (!stdnm && !obj->getProto()) {
+        RootedObject proto(cx);
+        if (!JSObject::getProto(cx, obj, &proto))
+            return false;
+        if (!stdnm && !proto) {
             /*
              * Try even less frequently used names delegated from the global
              * object to Object.prototype, but only if the Object class hasn't
              * yet been initialized.
              */
             for (i = 0; object_prototype_names[i].init; i++) {
                 JS_ASSERT(object_prototype_names[i].clasp);
                 atom = StdNameToPropertyName(cx, &object_prototype_names[i]);
@@ -3260,20 +3263,24 @@ JS_PUBLIC_API(void *)
 JS_GetInstancePrivate(JSContext *cx, JSObject *objArg, JSClass *clasp, jsval *argv)
 {
     RootedObject obj(cx, objArg);
     if (!JS_InstanceOf(cx, obj, clasp, argv))
         return NULL;
     return obj->getPrivate();
 }
 
-JS_PUBLIC_API(JSObject *)
-JS_GetPrototype(RawObject obj)
-{
-    return obj->getProto();
+JS_PUBLIC_API(JSBool)
+JS_GetPrototype(JSContext *cx, JSObject *objArg, JSObject **protop)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject proto(cx);
+    bool rv = JSObject::getProto(cx, obj, &proto);
+    *protop = proto;
+    return rv;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPrototype(JSContext *cx, JSObject *objArg, JSObject *protoArg)
 {
     RootedObject obj(cx, objArg);
     RootedObject proto(cx, protoArg);
     AssertHeapIsIdle(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -812,45 +812,49 @@ PrivateUint32Value(uint32_t ui)
 }
 
 JS_ALWAYS_INLINE bool
 SameType(const Value &lhs, const Value &rhs)
 {
     return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
 }
 
+} /* namespace JS */
+
 /************************************************************************/
 
-template <> struct RootMethods<const Value>
+namespace js {
+
+template <> struct RootMethods<const JS::Value>
 {
-    static Value initial() { return UndefinedValue(); }
+    static JS::Value initial() { return UndefinedValue(); }
     static ThingRootKind kind() { return THING_ROOT_VALUE; }
-    static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
+    static bool poisoned(const JS::Value &v) { return IsPoisonedValue(v); }
 };
 
-template <> struct RootMethods<Value>
+template <> struct RootMethods<JS::Value>
 {
-    static Value initial() { return UndefinedValue(); }
+    static JS::Value initial() { return UndefinedValue(); }
     static ThingRootKind kind() { return THING_ROOT_VALUE; }
-    static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
+    static bool poisoned(const JS::Value &v) { return IsPoisonedValue(v); }
 };
 
 template <class Outer> class MutableValueOperations;
 
 /*
  * A class designed for CRTP use in implementing the non-mutating parts of the
  * Value interface in Value-like classes.  Outer must be a class inheriting
  * ValueOperations<Outer> with a visible extract() method returning the
  * const Value* abstracted by Outer.
  */
 template <class Outer>
 class ValueOperations
 {
     friend class MutableValueOperations<Outer>;
-    const Value * value() const { return static_cast<const Outer*>(this)->extract(); }
+    const JS::Value * value() const { return static_cast<const Outer*>(this)->extract(); }
 
   public:
     bool isUndefined() const { return value()->isUndefined(); }
     bool isNull() const { return value()->isNull(); }
     bool isBoolean() const { return value()->isBoolean(); }
     bool isTrue() const { return value()->isTrue(); }
     bool isFalse() const { return value()->isFalse(); }
     bool isNumber() const { return value()->isNumber(); }
@@ -885,17 +889,17 @@ class ValueOperations
  * A class designed for CRTP use in implementing the mutating parts of the
  * Value interface in Value-like classes.  Outer must be a class inheriting
  * MutableValueOperations<Outer> with visible extractMutable() and extract()
  * methods returning the const Value* and Value* abstracted by Outer.
  */
 template <class Outer>
 class MutableValueOperations : public ValueOperations<Outer>
 {
-    Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
+    JS::Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
 
   public:
     void setNull() { value()->setNull(); }
     void setUndefined() { value()->setUndefined(); }
     void setInt32(int32_t i) { value()->setInt32(i); }
     void setDouble(double d) { value()->setDouble(d); }
     void setString(JSString *str) { value()->setString(str); }
     void setString(const JS::Anchor<JSString *> &str) { value()->setString(str); }
@@ -907,62 +911,66 @@ class MutableValueOperations : public Va
     void setObjectOrNull(JSObject *arg) { value()->setObjectOrNull(arg); }
 };
 
 /*
  * Augment the generic Handle<T> interface when T = Value with type-querying
  * and value-extracting operations.
  */
 template <>
-class HandleBase<Value> : public ValueOperations<Handle<Value> >
+class HandleBase<JS::Value> : public ValueOperations<Handle<JS::Value> >
 {
-    friend class ValueOperations<Handle<Value> >;
-    const Value * extract() const {
-        return static_cast<const Handle<Value>*>(this)->address();
+    friend class ValueOperations<Handle<JS::Value> >;
+    const JS::Value * extract() const {
+        return static_cast<const Handle<JS::Value>*>(this)->address();
     }
 };
 
 /*
  * Augment the generic MutableHandle<T> interface when T = Value with
  * type-querying, value-extracting, and mutating operations.
  */
 template <>
-class MutableHandleBase<Value> : public MutableValueOperations<MutableHandle<Value> >
+class MutableHandleBase<JS::Value> : public MutableValueOperations<MutableHandle<JS::Value> >
 {
-    friend class ValueOperations<MutableHandle<Value> >;
-    const Value * extract() const {
-        return static_cast<const MutableHandle<Value>*>(this)->address();
+    friend class ValueOperations<MutableHandle<JS::Value> >;
+    const JS::Value * extract() const {
+        return static_cast<const MutableHandle<JS::Value>*>(this)->address();
     }
 
-    friend class MutableValueOperations<MutableHandle<Value> >;
-    Value * extractMutable() {
-        return static_cast<MutableHandle<Value>*>(this)->address();
+    friend class MutableValueOperations<MutableHandle<JS::Value> >;
+    JS::Value * extractMutable() {
+        return static_cast<MutableHandle<JS::Value>*>(this)->address();
     }
 };
 
 /*
  * Augment the generic Rooted<T> interface when T = Value with type-querying,
  * value-extracting, and mutating operations.
  */
 template <>
-class RootedBase<Value> : public MutableValueOperations<Rooted<Value> >
+class RootedBase<JS::Value> : public MutableValueOperations<Rooted<JS::Value> >
 {
-    friend class ValueOperations<Rooted<Value> >;
-    const Value * extract() const {
-        return static_cast<const Rooted<Value>*>(this)->address();
+    friend class ValueOperations<Rooted<JS::Value> >;
+    const JS::Value * extract() const {
+        return static_cast<const Rooted<JS::Value>*>(this)->address();
     }
 
-    friend class MutableValueOperations<Rooted<Value> >;
-    Value * extractMutable() {
-        return static_cast<Rooted<Value>*>(this)->address();
+    friend class MutableValueOperations<Rooted<JS::Value> >;
+    JS::Value * extractMutable() {
+        return static_cast<Rooted<JS::Value>*>(this)->address();
     }
 };
 
+} /* namespace js */
+
 /************************************************************************/
 
+namespace JS {
+
 #ifndef __GNUC__
 
 /*
  * The default assignment operator for |struct C| has the signature:
  *
  *   C& C::operator=(const C&)
  *
  * And in particular requires implicit conversion of |this| to type |C| for the
@@ -1210,17 +1218,17 @@ class AutoArrayRooter : private AutoGCRo
 
     Value *array;
 
     friend void AutoGCRooter::trace(JSTracer *trc);
 
   private:
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 
-    SkipRoot skip;
+    js::SkipRoot skip;
 };
 
 template<class T>
 class AutoVectorRooter : protected AutoGCRooter
 {
   public:
     explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag
                               JS_GUARD_OBJECT_NOTIFIER_PARAM)
@@ -1293,17 +1301,17 @@ class AutoVectorRooter : protected AutoG
         for (size_t i = oldLength; i < vector.length(); ++i, ++t)
             memset(t, 0, sizeof(T));
     }
 
     typedef js::Vector<T, 8> VectorImpl;
     VectorImpl vector;
 
     /* Prevent overwriting of inline elements in vector. */
-    SkipRoot vectorRoot;
+    js::SkipRoot vectorRoot;
 
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 class AutoValueVector : public AutoVectorRooter<Value>
 {
   public:
     explicit AutoValueVector(JSContext *cx
@@ -2637,18 +2645,18 @@ ToBooleanSlow(const JS::Value &v);
 namespace JS {
 
 /* ES5 9.3 ToNumber. */
 JS_ALWAYS_INLINE bool
 ToNumber(JSContext *cx, const Value &v, double *out)
 {
     AssertArgumentsAreSane(cx, v);
     {
-        JS::SkipRoot root(cx, &v);
-        MaybeCheckStackRoots(cx);
+        js::SkipRoot root(cx, &v);
+        js::MaybeCheckStackRoots(cx);
     }
 
     if (v.isNumber()) {
         *out = v.toNumber();
         return true;
     }
     return js::ToNumberSlow(cx, v, out);
 }
@@ -2731,83 +2739,83 @@ ToUint64Slow(JSContext *cx, const JS::Va
 
 namespace JS {
 
 JS_ALWAYS_INLINE bool
 ToUint16(JSContext *cx, const js::Value &v, uint16_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     {
-        SkipRoot skip(cx, &v);
-        MaybeCheckStackRoots(cx);
+        js::SkipRoot skip(cx, &v);
+        js::MaybeCheckStackRoots(cx);
     }
 
     if (v.isInt32()) {
         *out = uint16_t(v.toInt32());
         return true;
     }
     return js::ToUint16Slow(cx, v, out);
 }
 
 JS_ALWAYS_INLINE bool
 ToInt32(JSContext *cx, const js::Value &v, int32_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     {
-        JS::SkipRoot root(cx, &v);
-        MaybeCheckStackRoots(cx);
+        js::SkipRoot root(cx, &v);
+        js::MaybeCheckStackRoots(cx);
     }
 
     if (v.isInt32()) {
         *out = v.toInt32();
         return true;
     }
     return js::ToInt32Slow(cx, v, out);
 }
 
 JS_ALWAYS_INLINE bool
 ToUint32(JSContext *cx, const js::Value &v, uint32_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     {
-        JS::SkipRoot root(cx, &v);
-        MaybeCheckStackRoots(cx);
+        js::SkipRoot root(cx, &v);
+        js::MaybeCheckStackRoots(cx);
     }
 
     if (v.isInt32()) {
         *out = uint32_t(v.toInt32());
         return true;
     }
     return js::ToUint32Slow(cx, v, out);
 }
 
 JS_ALWAYS_INLINE bool
 ToInt64(JSContext *cx, const js::Value &v, int64_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     {
-        JS::SkipRoot skip(cx, &v);
-        MaybeCheckStackRoots(cx);
+        js::SkipRoot skip(cx, &v);
+        js::MaybeCheckStackRoots(cx);
     }
 
     if (v.isInt32()) {
         *out = int64_t(v.toInt32());
         return true;
     }
 
     return js::ToInt64Slow(cx, v, out);
 }
 
 JS_ALWAYS_INLINE bool
 ToUint64(JSContext *cx, const js::Value &v, uint64_t *out)
 {
     AssertArgumentsAreSane(cx, v);
     {
-        SkipRoot skip(cx, &v);
-        MaybeCheckStackRoots(cx);
+        js::SkipRoot skip(cx, &v);
+        js::MaybeCheckStackRoots(cx);
     }
 
     if (v.isInt32()) {
         /* Account for sign extension of negatives into the longer 64bit space. */
         *out = uint64_t(int64_t(v.toInt32()));
         return true;
     }
 
@@ -2921,31 +2929,28 @@ IsPoisonedId(jsid iden)
 {
     if (JSID_IS_STRING(iden))
         return JS::IsPoisonedPtr(JSID_TO_STRING(iden));
     if (JSID_IS_OBJECT(iden))
         return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden));
     return false;
 }
 
-template <> struct RootMethods<const jsid>
-{
-    static jsid initial() { return JSID_VOID; }
-    static ThingRootKind kind() { return THING_ROOT_ID; }
-    static bool poisoned(jsid id) { return IsPoisonedId(id); }
-};
+} /* namespace JS */
+
+namespace js {
 
 template <> struct RootMethods<jsid>
 {
     static jsid initial() { return JSID_VOID; }
     static ThingRootKind kind() { return THING_ROOT_ID; }
     static bool poisoned(jsid id) { return IsPoisonedId(id); }
 };
 
-} /* namespace JS */
+} /* namespace js */
 
 class JSAutoRequest {
   public:
     JSAutoRequest(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
         : mContext(cx) {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
         JS_BeginRequest(mContext);
     }
@@ -4329,18 +4334,18 @@ JS_GetPrivate(JSRawObject obj);
 
 extern JS_PUBLIC_API(void)
 JS_SetPrivate(JSRawObject obj, void *data);
 
 extern JS_PUBLIC_API(void *)
 JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
                       jsval *argv);
 
-extern JS_PUBLIC_API(JSObject *)
-JS_GetPrototype(JSRawObject obj);
+extern JS_PUBLIC_API(JSBool)
+JS_GetPrototype(JSContext *cx, JSObject *obj, JSObject **protop);
 
 extern JS_PUBLIC_API(JSBool)
 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetParent(JSRawObject obj);
 
 extern JS_PUBLIC_API(JSBool)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -499,24 +499,26 @@ js::SetLengthProperty(JSContext *cx, Han
  * to be careful about the length getter and setter being called on an object
  * not of Array class. For the getter, we search obj's prototype chain for the
  * array that caused this getter to be invoked. In the setter case to overcome
  * the JSPROP_SHARED attribute, we must define a shadowing length property.
  */
 static JSBool
 array_length_getter(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValue vp)
 {
-    JSObject *obj = obj_;
+    RootedObject obj(cx, obj_);
     do {
         if (obj->isArray()) {
             vp.setNumber(obj->getArrayLength());
-            return JS_TRUE;
+            return true;
         }
-    } while ((obj = obj->getProto()) != NULL);
-    return JS_TRUE;
+        if (!JSObject::getProto(cx, obj, &obj))
+            return false;
+    } while (obj);
+    return true;
 }
 
 static JSBool
 array_length_setter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)
 {
     if (!obj->isArray()) {
         return JSObject::defineProperty(cx, obj, cx->names().length, vp,
                                         NULL, NULL, JSPROP_ENUMERATE);
@@ -894,16 +896,18 @@ array_setSpecial(JSContext *cx, HandleOb
 {
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return array_setGeneric(cx, obj, id, vp, strict);
 }
 
 JSBool
 js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
 {
+    JS_ASSERT(obj->isDenseArray());
+
     /*
      * Walk up the prototype chain and see if this indexed element already
      * exists. If we hit the end of the prototype chain, it's safe to set the
      * element on the original object.
      */
     while ((obj = obj->getProto()) != NULL) {
         /*
          * If the prototype is a non-native object (possibly a dense array), or
@@ -3635,17 +3639,17 @@ NewArray(JSContext *cx, uint32_t length,
     RootedTypeObject type(cx, proto->getNewType(cx));
     if (!type)
         return NULL;
 
     /*
      * Get a shape with zero fixed slots, regardless of the size class.
      * See JSObject::createDenseArray.
      */
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayClass, proto,
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayClass, TaggedProto(proto),
                                                       cx->global(), gc::FINALIZE_OBJECT0));
     if (!shape)
         return NULL;
 
     JSObject* obj = JSObject::createDenseArray(cx, kind, shape, type, length);
     if (!obj)
         return NULL;
 
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -376,32 +376,28 @@ enum ESClassValue {
  */
 inline bool
 ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
 
 /* Just a helper that checks v.isObject before calling ObjectClassIs. */
 inline bool
 IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx);
 
-}  /* namespace js */
-
-namespace JS {
-
 inline bool
 IsPoisonedSpecialId(js::SpecialId iden)
 {
     if (iden.isObject())
         return IsPoisonedPtr(iden.toObject());
     return false;
 }
 
-template <> struct RootMethods<js::SpecialId>
+template <> struct RootMethods<SpecialId>
 {
-    static js::SpecialId initial() { return js::SpecialId(); }
+    static SpecialId initial() { return SpecialId(); }
     static ThingRootKind kind() { return THING_ROOT_ID; }
-    static bool poisoned(js::SpecialId id) { return IsPoisonedSpecialId(id); }
+    static bool poisoned(SpecialId id) { return IsPoisonedSpecialId(id); }
 };
 
-} /* namespace JS */
+}  /* namespace js */
 
 #endif  /* __cplusplus */
 
 #endif  /* jsclass_h__ */
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -307,17 +307,17 @@ class NewObjectCache
     /*
      * Return a new object from a cache hit produced by a lookup method, or
      * NULL if returning the object could possibly trigger GC (does not
      * indicate failure).
      */
     inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry);
 
     /* Fill an entry after a cache miss. */
-    inline void fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj);
+    inline void fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto, gc::AllocKind kind, JSObject *obj);
     inline void fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj);
     inline void fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj);
 
     /* Invalidate any entries which might produce an object with shape/proto. */
     void invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject *proto);
 
   private:
     inline bool lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry);
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -73,21 +73,21 @@ NewObjectCache::fill(EntryIndex entry_, 
     entry->key = key;
     entry->kind = kind;
 
     entry->nbytes = obj->sizeOfThis();
     js_memcpy(&entry->templateObject, obj, entry->nbytes);
 }
 
 inline void
-NewObjectCache::fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj)
+NewObjectCache::fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto, gc::AllocKind kind, JSObject *obj)
 {
-    JS_ASSERT(!proto->isGlobal());
-    JS_ASSERT(obj->getProto() == proto);
-    return fill(entry, clasp, proto, kind, obj);
+    JS_ASSERT_IF(proto.isObject(), !proto.toObject()->isGlobal());
+    JS_ASSERT(obj->getTaggedProto() == proto);
+    return fill(entry, clasp, proto.raw(), kind, obj);
 }
 
 inline void
 NewObjectCache::fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj)
 {
     //JS_ASSERT(global == obj->getGlobal());
     return fill(entry, clasp, global, kind, obj);
 }
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -59,17 +59,16 @@ JSCompartment::JSCompartment(JSRuntime *
     lastCodeRelease(0),
     analysisLifoAlloc(LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     typeLifoAlloc(LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     data(NULL),
     active(false),
     lastAnimationTime(0),
     regExps(rt),
     propertyTree(thisForCtor()),
-    emptyTypeObject(NULL),
     gcMallocAndFreeBytes(0),
     gcTriggerMallocAndFreeBytes(0),
     gcMallocBytes(0),
     debugModeBits(rt->debugMode ? DebugFromC : 0),
     watchpointMap(NULL),
     scriptCountsMap(NULL),
     debugScriptMap(NULL)
 #ifdef JS_ION
@@ -266,23 +265,17 @@ JSCompartment::wrap(JSContext *cx, Value
     RootedValue key(cx, *vp);
 
     /* If we already have a wrapper for this value, use it. */
     if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(key)) {
         *vp = p->value;
         if (vp->isObject()) {
             RootedObject obj(cx, &vp->toObject());
             JS_ASSERT(obj->isCrossCompartmentWrapper());
-            if (obj->getParent() != global) {
-                do {
-                    if (!JSObject::setParent(cx, obj, global))
-                        return false;
-                    obj = obj->getProto();
-                } while (obj && obj->isCrossCompartmentWrapper());
-            }
+            JS_ASSERT(obj->getParent() == global);
         }
         return true;
     }
 
     if (vp->isString()) {
         RootedValue orig(cx, *vp);
         JSStableString *str = vp->toString()->ensureStable(cx);
         if (!str)
@@ -291,29 +284,17 @@ JSCompartment::wrap(JSContext *cx, Value
         if (!wrapped)
             return false;
         vp->setString(wrapped);
         return crossCompartmentWrappers.put(orig, *vp);
     }
 
     RootedObject obj(cx, &vp->toObject());
 
-    /*
-     * Recurse to wrap the prototype. Long prototype chains will run out of
-     * stack, causing an error in CHECK_RECURSE.
-     *
-     * Wrapping the proto before creating the new wrapper and adding it to the
-     * cache helps avoid leaving a bad entry in the cache on OOM. But note that
-     * if we wrapped both proto and parent, we would get infinite recursion
-     * here (since Object.prototype->parent->proto leads to Object.prototype
-     * itself).
-     */
-    RootedObject proto(cx, obj->getProto());
-    if (!wrap(cx, proto.address()))
-        return false;
+    JSObject *proto = Proxy::LazyProto;
 
     /*
      * We hand in the original wrapped object into the wrap hook to allow
      * the wrap hook to reason over what wrappers are currently applied
      * to the object.
      */
     RootedObject wrapper(cx, cx->runtime->wrapObjectCallback(cx, obj, proto, global, flags));
     if (!wrapper)
@@ -553,19 +534,16 @@ JSCompartment::sweep(FreeOp *fop, bool r
 
         /* Remove dead references held weakly by the compartment. */
 
         sweepBaseShapeTable();
         sweepInitialShapeTable();
         sweepNewTypeObjectTable(newTypeObjects);
         sweepNewTypeObjectTable(lazyTypeObjects);
 
-        if (emptyTypeObject && !IsTypeObjectMarked(emptyTypeObject.unsafeGet()))
-            emptyTypeObject = NULL;
-
         sweepBreakpoints(fop);
 
         if (global_ && !IsObjectMarked(&global_))
             global_ = NULL;
 
 #ifdef JS_ION
         if (ionCompartment_)
             ionCompartment_->sweep(fop);
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -294,22 +294,20 @@ struct JSCompartment
     js::InitialShapeSet          initialShapes;
     void sweepInitialShapeTable();
 
     /* Set of default 'new' or lazy types in the compartment. */
     js::types::TypeObjectSet     newTypeObjects;
     js::types::TypeObjectSet     lazyTypeObjects;
     void sweepNewTypeObjectTable(js::types::TypeObjectSet &table);
 
-    js::ReadBarriered<js::types::TypeObject> emptyTypeObject;
+    js::types::TypeObject *getNewType(JSContext *cx, js::TaggedProto proto,
+                                      JSFunction *fun = NULL, bool isDOM = false);
 
-    /* Get the default 'new' type for objects with a NULL prototype. */
-    inline js::types::TypeObject *getEmptyType(JSContext *cx);
-
-    js::types::TypeObject *getLazyType(JSContext *cx, js::HandleObject proto);
+    js::types::TypeObject *getLazyType(JSContext *cx, js::Handle<js::TaggedProto> proto);
 
     /*
      * Keeps track of the total number of malloc bytes connected to a
      * compartment's GC things. This counter should be used in preference to
      * gcMallocBytes. These counters affect collection in the same way as
      * gcBytes and gcTriggerBytes.
      */
     size_t                       gcMallocAndFreeBytes;
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -92,17 +92,18 @@ JS_SplicePrototype(JSContext *cx, JSObje
     if (!obj->hasSingletonType()) {
         /*
          * We can see non-singleton objects when trying to splice prototypes
          * due to mutable __proto__ (ugh).
          */
         return JS_SetPrototype(cx, obj, proto);
     }
 
-    return obj->splicePrototype(cx, proto);
+    Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
+    return obj->splicePrototype(cx, tagged);
 }
 
 JS_FRIEND_API(JSObject *)
 JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *protoArg, JSObject *parentArg)
 {
     RootedObject proto(cx, protoArg);
     RootedObject parent(cx, parentArg);
     RootedObject obj(cx, JS_NewObject(cx, clasp, proto, parent));
@@ -533,16 +534,25 @@ js::VisitGrayWrapperTargets(JSCompartmen
 }
 
 JS_FRIEND_API(void)
 JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback)
 {
     rt->telemetryCallback = callback;
 }
 
+JS_FRIEND_API(JSObject *)
+JS_CloneObject(JSContext *cx, JSObject *obj_, JSObject *proto_, JSObject *parent_)
+{
+    RootedObject obj(cx, obj_);
+    Rooted<js::TaggedProto> proto(cx, proto_);
+    RootedObject parent(cx, parent_);
+    return CloneObject(cx, obj, proto, parent);
+}
+
 #ifdef DEBUG
 JS_FRIEND_API(void)
 js_DumpString(JSString *str)
 {
     str->dump();
 }
 
 JS_FRIEND_API(void)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -392,20 +392,29 @@ InitClassWithReserved(JSContext *cx, JSO
                       JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
 
 JS_FRIEND_API(const Value &)
 GetFunctionNativeReserved(RawObject fun, size_t which);
 
 JS_FRIEND_API(void)
 SetFunctionNativeReserved(RawObject fun, size_t which, const Value &val);
 
-inline JSObject *
-GetObjectProto(RawObject obj)
+inline bool
+GetObjectProto(JSContext *cx, JSObject *obj, JSObject **proto)
 {
-    return reinterpret_cast<const shadow::Object*>(obj)->type->proto;
+    js::Class *clasp = GetObjectClass(obj);
+    if (clasp == &js::ObjectProxyClass ||
+        clasp == &js::OuterWindowProxyClass ||
+        clasp == &js::FunctionProxyClass)
+    {
+        return JS_GetPrototype(cx, obj, proto);
+    }
+
+    *proto = reinterpret_cast<const shadow::Object*>(obj)->type->proto;
+    return true;
 }
 
 inline void *
 GetObjectPrivate(RawObject obj)
 {
     const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
     void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
     return *addr;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -69,19 +69,20 @@ using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::frontend;
 
 static JSBool
 fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValue vp)
 {
-    JSObject *obj = obj_;
+    RootedObject obj(cx, obj_);
     while (!obj->isFunction()) {
-        obj = obj->getProto();
+        if (!JSObject::getProto(cx, obj, &obj))
+            return false;
         if (!obj)
             return true;
     }
     RootedFunction fun(cx, obj->toFunction());
 
     /*
      * Mark the function's script as uninlineable, to expand any of its
      * frames on the stack before we go looking for them. This allows the
@@ -478,30 +479,34 @@ fun_hasInstance(JSContext *cx, HandleObj
     while (obj->isFunction()) {
         if (!obj->isBoundFunction())
             break;
         obj = obj->toFunction()->getBoundFunctionTarget();
     }
 
     RootedValue pval(cx);
     if (!JSObject::getProperty(cx, obj, obj, cx->names().classPrototype, &pval))
-        return JS_FALSE;
+        return false;
 
     if (pval.isPrimitive()) {
         /*
          * Throw a runtime error if instanceof is called on a function that
          * has a non-object as its .prototype value.
          */
         RootedValue val(cx, ObjectValue(*obj));
         js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, val, NullPtr());
-        return JS_FALSE;
+        return false;
     }
 
-    *bp = js_IsDelegate(cx, &pval.toObject(), v);
-    return JS_TRUE;
+    RootedObject pobj(cx, &pval.toObject());
+    bool isDelegate;
+    if (!IsDelegate(cx, pobj, v, &isDelegate))
+        return false;
+    *bp = isDelegate;
+    return true;
 }
 
 inline void
 JSFunction::trace(JSTracer *trc)
 {
     if (isExtended()) {
         MarkValueRange(trc, ArrayLength(toExtended()->extendedSlots),
                        toExtended()->extendedSlots, "nativeReserved");
@@ -1582,16 +1587,17 @@ js_DefineFunction(JSContext *cx, HandleO
 void
 js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp)
 {
     Value thisv = call.thisv();
 
 #ifdef DEBUG
     if (thisv.isObject()) {
         JS_ASSERT(thisv.toObject().getClass() != clasp ||
+                  !thisv.toObject().isNative() ||
                   !thisv.toObject().getProto() ||
                   thisv.toObject().getProto()->getClass() != clasp);
     } else if (thisv.isString()) {
         JS_ASSERT(clasp != &StringClass);
     } else if (thisv.isNumber()) {
         JS_ASSERT(clasp != &NumberClass);
     } else if (thisv.isBoolean()) {
         JS_ASSERT(clasp != &BooleanClass);
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -149,16 +149,17 @@ IsNativeFunction(const js::Value &v, JSN
  * or shadowed. However, we can still do better than the general case by
  * hard-coding the necessary properties for us to find the native we expect.
  *
  * TODO: a per-thread shape-based cache would be faster and simpler.
  */
 static JS_ALWAYS_INLINE bool
 ClassMethodIsNative(JSContext *cx, HandleObject obj, Class *clasp, HandleId methodid, JSNative native)
 {
+    JS_ASSERT(!obj->isProxy());
     JS_ASSERT(obj->getClass() == clasp);
 
     Value v;
     if (!HasDataProperty(cx, obj, methodid, &v)) {
         RootedObject proto(cx, obj->getProto());
         if (!proto || proto->getClass() != clasp || !HasDataProperty(cx, proto, methodid, &v))
             return false;
     }
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -107,19 +107,20 @@
 #if JS_TRACE_LOGGING
 #include "TraceLogging.h"
 #endif
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 
-void * const JS::InternalHandleBase::zeroPointer = NULL;
-
 namespace js {
+
+void * const InternalHandleBase::zeroPointer = NULL;
+
 namespace gc {
 
 /*
  * Lower limit after which we limit the heap growth
  */
 const size_t GC_ALLOCATION_THRESHOLD = 30 * 1024 * 1024;
 
 /* Perform a Full GC every 20 seconds if MaybeGC is called */
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1843,27 +1843,27 @@ int
 StackTypeSet::getTypedArrayType()
 {
     AutoAssertNoGC nogc;
 
     int arrayType = TypedArray::TYPE_MAX;
     unsigned count = getObjectCount();
 
     for (unsigned i = 0; i < count; i++) {
-        RawObject proto = NULL;
+        TaggedProto proto;
         if (RawObject object = getSingleObject(i)) {
-            proto = object->getProto();
+            proto = object->getTaggedProto();
         } else if (TypeObject *object = getTypeObject(i)) {
             JS_ASSERT(!object->hasAnyFlags(OBJECT_FLAG_NON_TYPED_ARRAY));
-            proto = object->proto;
+            proto = TaggedProto(object->proto);
         }
-        if (!proto)
+        if (!proto.isObject())
             continue;
 
-        int objArrayType = proto->getClass() - TypedArray::protoClasses;
+        int objArrayType = proto.toObject()->getClass() - TypedArray::protoClasses;
         JS_ASSERT(objArrayType >= 0 && objArrayType < TypedArray::TYPE_MAX);
 
         /*
          * Set arrayType to the type of the first array. Return if there is an array
          * of another type.
          */
         if (arrayType == TypedArray::TYPE_MAX)
             arrayType = objArrayType;
@@ -2058,20 +2058,20 @@ TypeCompartment::init(JSContext *cx)
         JSC::MacroAssembler masm;
         if (masm.supportsFloatingPoint())
 #endif
             inferenceEnabled = true;
     }
 }
 
 TypeObject *
-TypeCompartment::newTypeObject(JSContext *cx, JSProtoKey key, HandleObject proto,
+TypeCompartment::newTypeObject(JSContext *cx, JSProtoKey key, Handle<TaggedProto> proto,
                                bool unknown, bool isDOM)
 {
-    JS_ASSERT_IF(proto, cx->compartment == proto->compartment());
+    JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
 
     TypeObject *object = gc::NewGCThing<TypeObject>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
     if (!object)
         return NULL;
     new(object) TypeObject(proto, key == JSProto_Function, unknown);
 
     if (!cx->typeInferenceEnabled()) {
         object->flags |= OBJECT_FLAG_UNKNOWN_MASK;
@@ -2214,17 +2214,18 @@ TypeCompartment::addAllocationSiteTypeOb
     }
 
     if (!res) {
         RootedObject proto(cx);
         if (!js_GetClassPrototype(cx, key.kind, &proto, NULL))
             return NULL;
 
         RootedScript keyScript(cx, key.script);
-        res = newTypeObject(cx, key.kind, proto);
+        Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
+        res = newTypeObject(cx, key.kind, tagged);
         if (!res) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return NULL;
         }
         key.script = keyScript;
     }
 
     if (JSOp(*pc) == JSOP_NEWOBJECT) {
@@ -2886,30 +2887,30 @@ TypeCompartment::fixArrayType(JSContext 
  * are weak the hash entries would usually be collected on GC even if objects
  * with the new type/shape are still live.
  */
 struct types::ObjectTableKey
 {
     jsid *ids;
     uint32_t nslots;
     uint32_t nfixed;
-    JSObject *proto;
+    TaggedProto proto;
 
     typedef JSObject * Lookup;
 
     static inline uint32_t hash(JSObject *obj) {
         return (uint32_t) (JSID_BITS(obj->lastProperty()->propid().get()) ^
                          obj->slotSpan() ^ obj->numFixedSlots() ^
-                         ((uint32_t)(size_t)obj->getProto() >> 2));
+                         ((uint32_t)obj->getTaggedProto().toWord() >> 2));
     }
 
     static inline bool match(const ObjectTableKey &v, JSObject *obj) {
         if (obj->slotSpan() != v.nslots ||
             obj->numFixedSlots() != v.nfixed ||
-            obj->getProto() != v.proto) {
+            obj->getTaggedProto() != v.proto) {
             return false;
         }
         Shape *shape = obj->lastProperty();
         while (!shape->isEmptyShape()) {
             if (shape->propid() != v.ids[shape->slot()])
                 return false;
             shape = shape->previous();
         }
@@ -2977,17 +2978,17 @@ TypeCompartment::fixObjectType(JSContext
                     return;
                 }
             }
         }
 
         obj->setType(p->value.object);
     } else {
         /* Make a new type to use for the object and similar future ones. */
-        RootedObject objProto(cx, obj->getProto());
+        Rooted<TaggedProto> objProto(cx, obj->getTaggedProto());
         TypeObject *objType = newTypeObject(cx, JSProto_Object, objProto);
         if (!objType || !objType->addDefiniteProperties(cx, obj)) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
 
         jsid *ids = cx->pod_calloc<jsid>(obj->slotSpan());
         if (!ids) {
@@ -3011,17 +3012,17 @@ TypeCompartment::fixObjectType(JSContext
             }
             shape = shape->previous();
         }
 
         ObjectTableKey key;
         key.ids = ids;
         key.nslots = obj->slotSpan();
         key.nfixed = obj->numFixedSlots();
-        key.proto = obj->getProto();
+        key.proto = obj->getTaggedProto();
         JS_ASSERT(ObjectTableKey::match(key, obj.get()));
 
         ObjectTableEntry entry;
         entry.object = objType;
         entry.types = types;
 
         p = objectTypeTable->lookupForAdd(obj.get());
         if (!objectTypeTable->add(p, key, entry)) {
@@ -3043,16 +3044,21 @@ TypeObject::getFromPrototypes(JSContext 
     if (!force && types->hasPropagatedProperty())
         return;
 
     types->setPropagatedProperty();
 
     if (!proto)
         return;
 
+    if (proto == Proxy::LazyProto) {
+        JS_ASSERT(unknownProperties());
+        return;
+    }
+
     if (proto->getType(cx)->unknownProperties()) {
         types->addType(cx, Type::UnknownType());
         return;
     }
 
     HeapTypeSet *protoTypes = proto->getType(cx)->getProperty(cx, id, false);
     if (!protoTypes)
         return;
@@ -5580,54 +5586,54 @@ JSObject::shouldSplicePrototype(JSContex
      * has had its __proto__ set after creation.
      */
     if (getProto() != NULL)
         return false;
     return !cx->typeInferenceEnabled() || hasSingletonType();
 }
 
 bool
-JSObject::splicePrototype(JSContext *cx, HandleObject proto)
+JSObject::splicePrototype(JSContext *cx, Handle<TaggedProto> proto)
 {
     JS_ASSERT(cx->compartment == compartment());
 
     RootedObject self(cx, this);
 
     /*
      * For singleton types representing only a single JSObject, the proto
      * can be rearranged as needed without destroying type information for
      * the old or new types. Note that type constraints propagating properties
      * from the old prototype are not removed.
      */
     JS_ASSERT_IF(cx->typeInferenceEnabled(), self->hasSingletonType());
 
     /* Inner objects may not appear on prototype chains. */
-    JS_ASSERT_IF(proto, !proto->getClass()->ext.outerObject);
+    JS_ASSERT_IF(proto.isObject(), !proto.toObject()->getClass()->ext.outerObject);
 
     /*
      * Force type instantiation when splicing lazy types. This may fail,
      * in which case inference will be disabled for the compartment.
      */
     Rooted<TypeObject*> type(cx, self->getType(cx));
     Rooted<TypeObject*> protoType(cx, NULL);
-    if (proto) {
-        protoType = proto->getType(cx);
-        if (!proto->getNewType(cx))
+    if (proto.isObject()) {
+        protoType = proto.toObject()->getType(cx);
+        if (!proto.toObject()->getNewType(cx))
             return false;
     }
 
     if (!cx->typeInferenceEnabled()) {
-        TypeObject *type = proto ? proto->getNewType(cx) : cx->compartment->getEmptyType(cx);
+        TypeObject *type = cx->compartment->getNewType(cx, proto);
         if (!type)
             return false;
         self->type_ = type;
         return true;
     }
 
-    type->proto = proto;
+    type->proto = proto.raw();
 
     AutoEnterTypeInference enter(cx);
 
     if (protoType && protoType->unknownProperties() && !type->unknownProperties()) {
         type->markUnknown(cx);
         return true;
     }
 
@@ -5647,17 +5653,17 @@ JSObject::splicePrototype(JSContext *cx,
 TypeObject *
 JSObject::makeLazyType(JSContext *cx)
 {
     JS_ASSERT(hasLazyType());
     JS_ASSERT(cx->compartment == compartment());
 
     RootedObject self(cx, this);
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(getClass());
-    RootedObject proto(cx, getProto());
+    Rooted<TaggedProto> proto(cx, getTaggedProto());
     TypeObject *type = cx->compartment->types.newTypeObject(cx, key, proto);
     AutoAssertNoGC nogc;
     if (!type) {
         if (cx->typeInferenceEnabled())
             cx->compartment->types.setPendingNukeTypes(cx);
         return self->type_;
     }
 
@@ -5707,25 +5713,25 @@ JSObject::makeLazyType(JSContext *cx)
         type->flags |= OBJECT_FLAG_NON_TYPED_ARRAY;
 
     self->type_ = type;
 
     return type;
 }
 
 /* static */ inline HashNumber
-TypeObjectEntry::hash(RawObject proto)
-{
-    return PointerHasher<JSObject *, 3>::hash(proto);
+TypeObjectEntry::hash(TaggedProto proto)
+{
+    return PointerHasher<JSObject *, 3>::hash(proto.raw());
 }
 
 /* static */ inline bool
-TypeObjectEntry::match(TypeObject *key, RawObject lookup)
-{
-    return key->proto == lookup;
+TypeObjectEntry::match(TypeObject *key, TaggedProto lookup)
+{
+    return key->proto == lookup.raw();
 }
 
 #ifdef DEBUG
 bool
 JSObject::hasNewType(TypeObject *type)
 {
     TypeObjectSet &table = compartment()->newTypeObjects;
 
@@ -5753,26 +5759,25 @@ JSObject::setNewTypeUnknown(JSContext *c
         if (TypeObjectSet::Ptr p = table.lookup(this))
             MarkTypeObjectUnknownProperties(cx, *p);
     }
 
     return true;
 }
 
 TypeObject *
-JSObject::getNewType(JSContext *cx, JSFunction *fun_, bool isDOM)
-{
-    JS_ASSERT(cx->compartment == compartment());
-
-    TypeObjectSet &table = cx->compartment->newTypeObjects;
-
-    if (!table.initialized() && !table.init())
+JSCompartment::getNewType(JSContext *cx, TaggedProto proto_, JSFunction *fun_, bool isDOM)
+{
+    JS_ASSERT_IF(fun_, proto_.isObject());
+    JS_ASSERT_IF(proto_.isObject(), cx->compartment == proto_.toObject()->compartment());
+
+    if (!newTypeObjects.initialized() && !newTypeObjects.init())
         return NULL;
 
-    TypeObjectSet::AddPtr p = table.lookupForAdd(this);
+    TypeObjectSet::AddPtr p = newTypeObjects.lookupForAdd(proto_);
     if (p) {
         TypeObject *type = *p;
 
         /*
          * If set, the type's newScript indicates the script used to create
          * all objects in existence which have this type. If there are objects
          * in existence which are not created by calling 'new' on newScript,
          * we must clear the new script information from the type and will not
@@ -5786,76 +5791,86 @@ JSObject::getNewType(JSContext *cx, JSFu
             type->clearNewScript(cx);
 
         if (!isDOM && !type->hasAnyFlags(OBJECT_FLAG_NON_DOM))
             type->setFlags(cx, OBJECT_FLAG_NON_DOM);
 
         return type;
     }
 
-    RootedObject self(cx, this);
     RootedFunction fun(cx, fun_);
-
-    if (!setDelegate(cx))
+    Rooted<TaggedProto> proto(cx, proto_);
+
+    if (proto.isObject() && !proto.toObject()->setDelegate(cx))
         return NULL;
 
-    bool markUnknown = self->lastProperty()->hasObjectFlag(BaseShape::NEW_TYPE_UNKNOWN);
+    bool markUnknown =
+        proto.isObject()
+        ? proto.toObject()->lastProperty()->hasObjectFlag(BaseShape::NEW_TYPE_UNKNOWN)
+        : true;
 
     RootedTypeObject type(cx);
-    type = cx->compartment->types.newTypeObject(cx, JSProto_Object, self, markUnknown, isDOM);
+    type = types.newTypeObject(cx, JSProto_Object, proto, markUnknown, isDOM);
     if (!type)
         return NULL;
 
-    if (!table.relookupOrAdd(p, self, type.get()))
+    if (!newTypeObjects.relookupOrAdd(p, proto, type.get()))
         return NULL;
 
     if (!cx->typeInferenceEnabled())
         return type;
 
     AutoEnterTypeInference enter(cx);
 
     /*
      * Set the special equality flag for types whose prototype also has the
      * flag set. This is a hack, :XXX: need a real correspondence between
      * types and the possible js::Class of objects with that type.
      */
-    if (self->hasSpecialEquality())
-        type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
-
-    if (fun)
-        CheckNewScriptProperties(cx, type, fun);
+    if (proto.isObject()) {
+        JSObject *obj = proto.toObject();
+
+        if (obj->hasSpecialEquality())
+            type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
+
+        if (fun)
+            CheckNewScriptProperties(cx, type, fun);
 
 #if JS_HAS_XML_SUPPORT
-    /* Special case for XML object equality, see makeLazyType(). */
-    if (self->isXML() && !type->unknownProperties())
-        type->flags |= OBJECT_FLAG_UNKNOWN_MASK;
+        /* Special case for XML object equality, see makeLazyType(). */
+        if (obj->isXML() && !type->unknownProperties())
+            type->flags |= OBJECT_FLAG_UNKNOWN_MASK;
 #endif
-
-    if (self->getClass()->ext.equality)
-        type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
+    }
 
     /*
      * The new type is not present in any type sets, so mark the object as
      * unknown in all type sets it appears in. This allows the prototype of
      * such objects to mutate freely without triggering an expensive walk of
      * the compartment's type sets. (While scripts normally don't mutate
      * __proto__, the browser will for proxies and such, and we need to
      * accommodate this behavior).
      */
     if (type->unknownProperties())
         type->flags |= OBJECT_FLAG_SETS_MARKED_UNKNOWN;
 
     return type;
 }
 
 TypeObject *
-JSCompartment::getLazyType(JSContext *cx, HandleObject proto)
+JSObject::getNewType(JSContext *cx, JSFunction *fun_, bool isDOM)
+{
+    return cx->compartment->getNewType(cx, this, fun_, isDOM);
+}
+
+TypeObject *
+JSCompartment::getLazyType(JSContext *cx, Handle<TaggedProto> proto)
 {
     JS_ASSERT(cx->compartment == this);
-    JS_ASSERT_IF(proto, cx->compartment == proto->compartment());
+    JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
 
     MaybeCheckStackRoots(cx);
 
     TypeObjectSet &table = cx->compartment->lazyTypeObjects;
 
     if (!table.initialized() && !table.init())
         return NULL;
 
@@ -6082,17 +6097,17 @@ TypeCompartment::sweep(FreeOp *fop)
                 e.removeFront();
         }
     }
 
     if (objectTypeTable) {
         for (ObjectTypeTable::Enum e(*objectTypeTable); !e.empty(); e.popFront()) {
             const ObjectTableKey &key = e.front().key;
             ObjectTableEntry &entry = e.front().value;
-            JS_ASSERT(entry.object->proto == key.proto);
+            JS_ASSERT(uintptr_t(entry.object->proto.get()) == key.proto.toWord());
 
             bool remove = false;
             if (!IsTypeObjectMarked(entry.object.unsafeGet()))
                 remove = true;
             for (unsigned i = 0; !remove && i < key.nslots; i++) {
                 if (JSID_IS_STRING(key.ids[i])) {
                     JSString *str = JSID_TO_STRING(key.ids[i]);
                     if (!IsStringMarked(&str))
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -22,16 +22,91 @@
 #include "js/Vector.h"
 
 namespace JS {
 struct TypeInferenceSizes;
 }
 
 namespace js {
 
+class TaggedProto
+{
+  public:
+    TaggedProto() : proto(NULL) {}
+    TaggedProto(JSObject *proto) : proto(proto) {}
+
+    uintptr_t toWord() const { return uintptr_t(proto); }
+
+    inline bool isLazy() const;
+    inline bool isObject() const;
+    inline JSObject *toObject() const;
+    inline JSObject *toObjectOrNull() const;
+    JSObject *raw() const { return proto; }
+
+    bool operator ==(const TaggedProto &other) { return proto == other.proto; }
+    bool operator !=(const TaggedProto &other) { return proto != other.proto; }
+
+  private:
+    JSObject *proto;
+};
+
+template <>
+struct RootKind<TaggedProto>
+{
+    static ThingRootKind rootKind() { return THING_ROOT_OBJECT; };
+};
+
+template <> struct RootMethods<const TaggedProto>
+{
+    static TaggedProto initial() { return TaggedProto(); }
+    static ThingRootKind kind() { return THING_ROOT_OBJECT; }
+    static bool poisoned(const TaggedProto &v) { return IsPoisonedPtr(v.raw()); }
+};
+
+template <> struct RootMethods<TaggedProto>
+{
+    static TaggedProto initial() { return TaggedProto(); }
+    static ThingRootKind kind() { return THING_ROOT_OBJECT; }
+    static bool poisoned(const TaggedProto &v) { return IsPoisonedPtr(v.raw()); }
+};
+
+template<class Outer>
+class TaggedProtoOperations
+{
+    const TaggedProto *value() const {
+        return static_cast<const Outer*>(this)->extract();
+    }
+
+  public:
+    uintptr_t toWord() const { return value()->toWord(); }
+    inline bool isLazy() const;
+    inline bool isObject() const;
+    inline JSObject *toObject() const;
+    inline JSObject *toObjectOrNull() const;
+    JSObject *raw() const { return value()->raw(); }
+};
+
+template <>
+class HandleBase<TaggedProto> : public TaggedProtoOperations<Handle<TaggedProto> >
+{
+    friend class TaggedProtoOperations<Handle<TaggedProto> >;
+    const TaggedProto * extract() const {
+        return static_cast<const Handle<TaggedProto>*>(this)->address();
+    }
+};
+
+template <>
+class RootedBase<TaggedProto> : public TaggedProtoOperations<Rooted<TaggedProto> >
+{
+    friend class TaggedProtoOperations<Rooted<TaggedProto> >;
+    const TaggedProto *extract() const {
+        return static_cast<const Rooted<TaggedProto> *>(this)->address();
+    }
+};
+
 class CallObject;
 
 namespace mjit {
     struct JITScript;
 }
 
 namespace ion {
     struct IonScript;
@@ -869,17 +944,17 @@ struct TypeObject : gc::Cell
 
     /* If this is an interpreted function, the function object. */
     HeapPtrFunction interpretedFunction;
 
 #if JS_BITS_PER_WORD == 32
     void *padding;
 #endif
 
-    inline TypeObject(RawObject proto, bool isFunction, bool unknown);
+    inline TypeObject(TaggedProto proto, bool isFunction, bool unknown);
 
     bool isFunction() { return !!(flags & OBJECT_FLAG_FUNCTION); }
 
     bool hasAnyFlags(TypeObjectFlags flags) {
         JS_ASSERT((flags & OBJECT_FLAG_DYNAMIC_MASK) == flags);
         return !!(this->flags & flags);
     }
     bool hasAllFlags(TypeObjectFlags flags) {
@@ -965,20 +1040,20 @@ struct TypeObject : gc::Cell
 };
 
 /*
  * Entries for the per-compartment set of type objects which are the default
  * 'new' or the lazy types of some prototype.
  */
 struct TypeObjectEntry
 {
-    typedef JSObject *Lookup;
+    typedef TaggedProto Lookup;
 
-    static inline HashNumber hash(RawObject base);
-    static inline bool match(TypeObject *key, RawObject lookup);
+    static inline HashNumber hash(TaggedProto base);
+    static inline bool match(TypeObject *key, TaggedProto lookup);
 };
 typedef HashSet<ReadBarriered<TypeObject>, TypeObjectEntry, SystemAllocPolicy> TypeObjectSet;
 
 /* Whether to use a new type object when calling 'new' at script/pc. */
 bool
 UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc);
 
 /* Whether to use a new type object for an initializer opcode at script/pc. */
@@ -1253,17 +1328,17 @@ struct TypeCompartment
     void print(JSContext *cx, bool force);
 
     /*
      * Make a function or non-function object associated with an optional
      * script. The 'key' parameter here may be an array, typed array, function
      * or JSProto_Object to indicate a type whose class is unknown (not just
      * js_ObjectClass).
      */
-    TypeObject *newTypeObject(JSContext *cx, JSProtoKey kind, HandleObject proto,
+    TypeObject *newTypeObject(JSContext *cx, JSProtoKey kind, Handle<TaggedProto> proto,
                               bool unknown = false, bool isDOM = false);
 
     /* Get or make an object for an allocation site, and add to the allocation site table. */
     TypeObject *addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey key);
 
     void nukeTypes(FreeOp *fop);
     void processPendingRecompiles(FreeOp *fop);
 
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -16,16 +16,71 @@
 #include "vm/GlobalObject.h"
 #include "ion/IonFrames.h"
 
 #include "vm/Stack-inl.h"
 
 #ifndef jsinferinlines_h___
 #define jsinferinlines_h___
 
+inline bool
+js::TaggedProto::isObject() const
+{
+    /* Skip NULL and Proxy::LazyProto. */
+    return uintptr_t(proto) > uintptr_t(Proxy::LazyProto);
+}
+
+inline bool
+js::TaggedProto::isLazy() const
+{
+    return proto == Proxy::LazyProto;
+}
+
+inline JSObject *
+js::TaggedProto::toObject() const
+{
+    JS_ASSERT(isObject());
+    return proto;
+}
+
+inline JSObject *
+js::TaggedProto::toObjectOrNull() const
+{
+    JS_ASSERT(!proto || isObject());
+    return proto;
+}
+
+template<class Outer>
+inline bool
+js::TaggedProtoOperations<Outer>::isLazy() const
+{
+    return value()->isLazy();
+}
+
+template<class Outer>
+inline bool
+js::TaggedProtoOperations<Outer>::isObject() const
+{
+    return value()->isObject();
+}
+
+template<class Outer>
+inline JSObject *
+js::TaggedProtoOperations<Outer>::toObject() const
+{
+    return value()->toObject();
+}
+
+template<class Outer>
+inline JSObject *
+js::TaggedProtoOperations<Outer>::toObjectOrNull() const
+{
+    return value()->toObjectOrNull();
+}
+
 namespace js {
 namespace types {
 
 /////////////////////////////////////////////////////////////////////
 // CompilerOutput & RecompileInfo
 /////////////////////////////////////////////////////////////////////
 
 inline
@@ -407,17 +462,17 @@ struct AutoEnterCompilation
 
 /*
  * Get the default 'new' object for a given standard class, per the currently
  * active global.
  */
 inline TypeObject *
 GetTypeNewObject(JSContext *cx, JSProtoKey key)
 {
-    RootedObject proto(cx);
+    js::RootedObject proto(cx);
     if (!js_GetClassPrototype(cx, key, &proto))
         return NULL;
     return proto->getNewType(cx);
 }
 
 /* Get a type object for the immediate allocation site within a native. */
 inline TypeObject *
 GetTypeCallerInitObject(JSContext *cx, JSProtoKey key)
@@ -449,21 +504,21 @@ MarkIteratorUnknown(JSContext *cx)
  * from within the interpreter.
  */
 inline bool
 TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
 {
     extern void TypeMonitorCallSlow(JSContext *cx, HandleObject callee,
                                     const CallArgs &args, bool constructing);
 
-    RootedObject callee(cx, &args.callee());
+    js::RootedObject callee(cx, &args.callee());
     if (callee->isFunction()) {
         JSFunction *fun = callee->toFunction();
         if (fun->isInterpreted()) {
-            RootedScript script(cx, fun->script());
+            js::RootedScript script(cx, fun->script());
             if (!script->ensureRanAnalysis(cx))
                 return false;
             if (cx->typeInferenceEnabled())
                 TypeMonitorCallSlow(cx, callee, args, constructing);
         }
     }
 
     return true;
@@ -697,17 +752,17 @@ TypeScript::SlotTypes(JSScript *script, 
     JS_ASSERT(slot < js::analyze::TotalSlots(script));
     TypeSet *types = script->types->typeArray() + script->nTypeSets + slot;
     return types->toStackTypeSet();
 }
 
 /* static */ inline TypeObject *
 TypeScript::StandardType(JSContext *cx, JSScript *script, JSProtoKey key)
 {
-    RootedObject proto(cx);
+    js::RootedObject proto(cx);
     if (!js_GetClassPrototype(cx, key, &proto, NULL))
         return NULL;
     return proto->getNewType(cx);
 }
 
 struct AllocationSiteKey {
     JSScript *script;
 
@@ -1395,24 +1450,24 @@ TypeCallsite::TypeCallsite(JSContext *cx
     /* Caller must check for failure. */
     argumentTypes = cx->analysisLifoAlloc().newArray<StackTypeSet*>(argumentCount);
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeObject
 /////////////////////////////////////////////////////////////////////
 
-inline TypeObject::TypeObject(RawObject proto, bool function, bool unknown)
+inline TypeObject::TypeObject(TaggedProto proto, bool function, bool unknown)
 {
     PodZero(this);
 
     /* Inner objects may not appear on prototype chains. */
-    JS_ASSERT_IF(proto, !proto->getClass()->ext.outerObject);
+    JS_ASSERT_IF(proto.isObject(), !proto.toObject()->getClass()->ext.outerObject);
 
-    this->proto = proto;
+    this->proto = proto.raw();
 
     if (function)
         flags |= OBJECT_FLAG_FUNCTION;
     if (unknown)
         flags |= OBJECT_FLAG_UNKNOWN_MASK;
 
     InferSpew(ISpewOps, "newObject: %s", TypeObjectString(this));
 }
@@ -1635,17 +1690,17 @@ JSScript::ensureRanAnalysis(JSContext *c
         return false;
     JS_ASSERT(self->analysis()->ranBytecode());
     return true;
 }
 
 inline bool
 JSScript::ensureRanInference(JSContext *cx)
 {
-    JS::RootedScript self(cx, this);
+    js::RootedScript self(cx, this);
     if (!ensureRanAnalysis(cx))
         return false;
     if (!self->analysis()->ranInference()) {
         js::types::AutoEnterTypeInference enter(cx);
         self->analysis()->analyzeTypes(cx);
     }
     return !self->analysis()->OOM() &&
         !cx->compartment->types.pendingNukeTypes;
@@ -1681,49 +1736,39 @@ JSScript::clearPropertyReadTypes()
 inline void
 js::analyze::ScriptAnalysis::addPushedType(JSContext *cx, uint32_t offset, uint32_t which,
                                            js::types::Type type)
 {
     js::types::TypeSet *pushed = pushedTypes(offset, which);
     pushed->addType(cx, type);
 }
 
-inline js::types::TypeObject *
-JSCompartment::getEmptyType(JSContext *cx)
-{
-    JS::MaybeCheckStackRoots(cx);
-
-    if (!emptyTypeObject) {
-        JS::RootedObject nullproto(cx, NULL);
-        emptyTypeObject = types.newTypeObject(cx, JSProto_Object, nullproto, true);
-    }
-    return emptyTypeObject;
-}
-
-namespace JS {
-
-template<> class AnchorPermitted<js::types::TypeObject *> { };
+namespace js {
 
 template <>
-struct RootMethods<const js::types::Type>
+struct RootMethods<const types::Type>
 {
-    static js::types::Type initial() { return js::types::Type::UnknownType(); }
+    static types::Type initial() { return types::Type::UnknownType(); }
     static ThingRootKind kind() { return THING_ROOT_TYPE; }
-    static bool poisoned(const js::types::Type &v) {
+    static bool poisoned(const types::Type &v) {
         return (v.isTypeObject() && IsPoisonedPtr(v.typeObject()))
             || (v.isSingleObject() && IsPoisonedPtr(v.singleObject()));
     }
 };
 
 template <>
-struct RootMethods<js::types::Type>
+struct RootMethods<types::Type>
 {
-    static js::types::Type initial() { return js::types::Type::UnknownType(); }
+    static types::Type initial() { return types::Type::UnknownType(); }
     static ThingRootKind kind() { return THING_ROOT_TYPE; }
-    static bool poisoned(const js::types::Type &v) {
+    static bool poisoned(const types::Type &v) {
         return (v.isTypeObject() && IsPoisonedPtr(v.typeObject()))
             || (v.isSingleObject() && IsPoisonedPtr(v.singleObject()));
     }
 };
 
+} // namespace js
+
+namespace JS {
+template<> class AnchorPermitted<js::types::TypeObject *> { };
 }  // namespace JS
 
 #endif // jsinferinlines_h___
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -97,31 +97,31 @@ Enumerate(JSContext *cx, HandleObject po
     /*
      * We implement __proto__ using a property on |Object.prototype|, but
      * because __proto__ is highly deserving of removal, we don't want it to
      * show up in property enumeration, even if only for |Object.prototype|
      * (think introspection by Prototype-like frameworks that add methods to
      * the built-in prototypes).  So exclude __proto__ if the object where the
      * property was found has no [[Prototype]] and might be |Object.prototype|.
      */
-    if (JS_UNLIKELY(!pobj->getProto() && JSID_IS_ATOM(id, cx->names().proto)))
+    if (JS_UNLIKELY(!pobj->getTaggedProto().isObject() && JSID_IS_ATOM(id, cx->names().proto)))
         return true;
 
     if (!(flags & JSITER_OWNONLY) || pobj->isProxy() || pobj->getOps()->enumerate) {
         /* If we've already seen this, we definitely won't add it. */
         IdSet::AddPtr p = ht.lookupForAdd(id);
         if (JS_UNLIKELY(!!p))
             return true;
 
         /*
          * It's not necessary to add properties to the hash table at the end of
          * the prototype chain, but custom enumeration behaviors might return
          * duplicated properties, so always add in such cases.
          */
-        if ((pobj->getProto() || pobj->isProxy() || pobj->getOps()->enumerate) && !ht.add(p, id))
+        if ((pobj->isProxy() || pobj->getProto() || pobj->getOps()->enumerate) && !ht.add(p, id))
             return false;
     }
 
     if (enumerable || (flags & JSITER_HIDDEN))
         return props->append(id);
 
     return true;
 }
@@ -399,17 +399,17 @@ Compare(T *a, T *b, size_t c)
     }
     return true;
 }
 
 static inline PropertyIteratorObject *
 NewPropertyIteratorObject(JSContext *cx, unsigned flags)
 {
     if (flags & JSITER_ENUMERATE) {
-        RootedTypeObject type(cx, cx->compartment->getEmptyType(cx));
+        RootedTypeObject type(cx, cx->compartment->getNewType(cx, NULL));
         if (!type)
             return NULL;
 
         RootedShape shape(cx, EmptyShape::getInitialShape(cx, &PropertyIteratorObject::class_,
                                                           NULL, NULL, ITERATOR_FINALIZE_KIND));
         if (!shape)
             return NULL;
 
@@ -622,28 +622,31 @@ GetIterator(JSContext *cx, HandleObject 
             /*
              * Check to see if this is the same as the most recent object which
              * was iterated over.  We don't explicitly check for shapeless
              * objects here, as they are not inserted into the cache and
              * will result in a miss.
              */
             PropertyIteratorObject *last = cx->runtime->nativeIterCache.last;
             if (last) {
-                RawObject proto = obj->getProto();
                 NativeIterator *lastni = last->getNativeIterator();
                 if (!(lastni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
                     obj->isNative() &&
-                    obj->lastProperty() == lastni->shapes_array[0] &&
-                    proto && proto->isNative() &&
-                    proto->lastProperty() == lastni->shapes_array[1] &&
-                    !proto->getProto()) {
-                    vp.setObject(*last);
-                    UpdateNativeIterator(lastni, obj);
-                    RegisterEnumerator(cx, last, lastni);
-                    return true;
+                    obj->lastProperty() == lastni->shapes_array[0])
+                {
+                    JSObject *proto = obj->getProto();
+                    if (proto->isNative() &&
+                        proto->lastProperty() == lastni->shapes_array[1] &&
+                        !proto->getProto())
+                    {
+                        vp.setObject(*last);
+                        UpdateNativeIterator(lastni, obj);
+                        RegisterEnumerator(cx, last, lastni);
+                        return true;
+                    }
                 }
             }
 
             /*
              * The iterator object for JSITER_ENUMERATE never escapes, so we
              * don't care for the proper parent/proto to be set. This also
              * allows us to re-use a previous iterator object that is not
              * currently active.
@@ -1088,18 +1091,21 @@ SuppressDeletedPropertyHelper(JSContext 
             HeapPtr<JSFlatString> *props_cursor = ni->current();
             HeapPtr<JSFlatString> *props_end = ni->end();
             for (HeapPtr<JSFlatString> *idp = props_cursor; idp < props_end; ++idp) {
                 if (predicate(*idp)) {
                     /*
                      * Check whether another property along the prototype chain
                      * became visible as a result of this deletion.
                      */
-                    if (obj->getProto()) {
-                        RootedObject proto(cx, obj->getProto()), obj2(cx);
+                    RootedObject proto(cx);
+                    if (!JSObject::getProto(cx, obj, &proto))
+                        return false;
+                    if (proto) {
+                        RootedObject obj2(cx);
                         RootedShape prop(cx);
                         RootedId id(cx);
                         if (!ValueToId(cx, StringValue(*idp), id.address()))
                             return false;
                         if (!JSObject::lookupGeneric(cx, proto, id, &obj2, &prop))
                             return false;
                         if (prop) {
                             unsigned attrs;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -560,17 +560,20 @@ obj_isPrototypeOf(JSContext *cx, unsigne
     }
 
     /* Step 2. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     /* Step 3. */
-    args.rval().setBoolean(js_IsDelegate(cx, obj, args[0]));
+    bool isDelegate;
+    if (!IsDelegate(cx, obj, args[0], &isDelegate))
+        return false;
+    args.rval().setBoolean(isDelegate);
     return true;
 }
 
 /* ES5 15.2.4.7. */
 static JSBool
 obj_propertyIsEnumerable(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1890,17 +1893,17 @@ JSObject::sealOrFreeze(JSContext *cx, Ha
         /*
          * Seal/freeze non-dictionary objects by constructing a new shape
          * hierarchy mirroring the original one, which can be shared if many
          * objects with the same structure are sealed/frozen. If we use the
          * generic path below then any non-empty object will be converted to
          * dictionary mode.
          */
         Shape *last = EmptyShape::getInitialShape(cx, obj->getClass(),
-                                                  obj->getProto(),
+                                                  obj->getTaggedProto(),
                                                   obj->getParent(),
                                                   obj->getAllocKind(),
                                                   obj->lastProperty()->getObjectFlags());
         if (!last)
             return false;
 
         /* Get an in order list of the shapes in this object. */
         AutoShapeVector shapes(cx);
@@ -2115,17 +2118,18 @@ NewObject(JSContext *cx, Class *clasp, t
 {
     JS_ASSERT(clasp != &ArrayClass);
     JS_ASSERT_IF(clasp == &FunctionClass,
                  kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
     JS_ASSERT_IF(parent, &parent->global() == cx->compartment->maybeGlobal());
 
     RootedTypeObject type(cx, type_);
 
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, type->proto, parent, kind));
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, TaggedProto(type->proto),
+                                                      parent, kind));
     if (!shape)
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
         return NULL;
 
     JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
@@ -2141,47 +2145,50 @@ NewObject(JSContext *cx, Class *clasp, t