Merge mozilla-central to b2g-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 04 Mar 2015 15:38:27 +0100
changeset 231809 7af4ffef0d260ab107d481a9defa0848566bcbc2
parent 231808 69e148c8a28cf6868a5ff60a791ea7d4898cdf70 (current diff)
parent 231787 a27dd304348daabacf8fe6de3b70cd645d357014 (diff)
child 231810 31f0623519d1af382e0c0921cc49425dbc0aacf2
push id28360
push userryanvm@gmail.com
push dateWed, 04 Mar 2015 20:58:22 +0000
treeherdermozilla-central@04653ab2dcb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to b2g-inbound
testing/config/mozharness/android_arm_4_4_config.py
--- a/accessible/atk/Platform.cpp
+++ b/accessible/atk/Platform.cpp
@@ -13,18 +13,19 @@
 #include "AtkSocketAccessible.h"
 #include "prenv.h"
 #include "prlink.h"
 
 #ifdef MOZ_ENABLE_DBUS
 #include <dbus/dbus.h>
 #endif
 #include <gtk/gtk.h>
+
 #if (MOZ_WIDGET_GTK == 3)
-#include <atk-bridge.h>
+extern "C" __attribute__((weak,visibility("default"))) int atk_bridge_adaptor_init(int*, char **[]);
 #endif
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 int atkMajorVersion = 1, atkMinorVersion = 12;
 
 extern "C" {
@@ -41,17 +42,16 @@ static const char sATKHyperlinkImplGetTy
 gboolean toplevel_event_watcher(GSignalInvocationHint*, guint, const GValue*,
                                 gpointer);
 static bool sToplevel_event_hook_added = false;
 static gulong sToplevel_show_hook = 0;
 static gulong sToplevel_hide_hook = 0;
 
 GType g_atk_hyperlink_impl_type = G_TYPE_INVALID;
 
-#if (MOZ_WIDGET_GTK == 2)
 struct GnomeAccessibilityModule
 {
     const char *libName;
     PRLibrary *lib;
     const char *initName;
     GnomeAccessibilityInit init;
     const char *shutdownName;
     GnomeAccessibilityShutdown shutdown;
@@ -62,21 +62,23 @@ static GnomeAccessibilityModule sAtkBrid
     "libatk-bridge.a(libatk-bridge.so.0)", nullptr,
 #else
     "libatk-bridge.so", nullptr,
 #endif
     "gnome_accessibility_module_init", nullptr,
     "gnome_accessibility_module_shutdown", nullptr
 };
 
+#if (MOZ_WIDGET_GTK == 2)
 static GnomeAccessibilityModule sGail = {
     "libgail.so", nullptr,
     "gnome_accessibility_module_init", nullptr,
     "gnome_accessibility_module_shutdown", nullptr
 };
+#endif
 
 static nsresult
 LoadGtkModule(GnomeAccessibilityModule& aModule)
 {
     NS_ENSURE_ARG(aModule.libName);
 
     if (!(aModule.lib = PR_LoadLibrary(aModule.libName))) {
         //try to load the module with "gtk-2.0/modules" appended
@@ -93,17 +95,21 @@ LoadGtkModule(GnomeAccessibilityModule& 
         int16_t subLen = 0;
         while (loc2 >= 0) {
             loc2 = libPath.FindChar(':', loc1);
             if (loc2 < 0)
                 subLen = libPath.Length() - loc1;
             else
                 subLen = loc2 - loc1;
             nsAutoCString sub(Substring(libPath, loc1, subLen));
+#if (MOZ_WIDGET_GTK == 2)
             sub.AppendLiteral("/gtk-2.0/modules/");
+#else
+            sub.AppendLiteral("/gtk-3.0/modules/");
+#endif
             sub.Append(aModule.libName);
             aModule.lib = PR_LoadLibrary(sub.get());
             if (aModule.lib)
                 break;
 
             loc1 = loc2+1;
         }
         if (!aModule.lib)
@@ -118,17 +124,16 @@ LoadGtkModule(GnomeAccessibilityModule& 
 
         //fail, :(
         PR_UnloadLibrary(aModule.lib);
         aModule.lib = nullptr;
         return NS_ERROR_FAILURE;
     }
     return NS_OK;
 }
-#endif // (MOZ_WIDGET_GTK == 2)
 
 void
 a11y::PlatformInit()
 {
   if (!ShouldA11yBeEnabled())
     return;
 
   sATKLib = PR_LoadLibrary(sATKLibName);
@@ -170,24 +175,27 @@ a11y::PlatformInit()
     (*sGail.init)();
 #endif
 
   // Initialize the MAI Utility class, it will overwrite gail_util.
   g_type_class_unref(g_type_class_ref(mai_util_get_type()));
 
   // Init atk-bridge now
   PR_SetEnv("NO_AT_BRIDGE=0");
-#if (MOZ_WIDGET_GTK == 2)
-  rv = LoadGtkModule(sAtkBridge);
-  if (NS_SUCCEEDED(rv)) {
-    (*sAtkBridge.init)();
+#if (MOZ_WIDGET_GTK == 3)
+  if (atk_bridge_adaptor_init) {
+    atk_bridge_adaptor_init(nullptr, nullptr);
+  } else
+#endif
+  {
+    nsresult rv = LoadGtkModule(sAtkBridge);
+    if (NS_SUCCEEDED(rv)) {
+      (*sAtkBridge.init)();
+    }
   }
-#else
-  atk_bridge_adaptor_init(nullptr, nullptr);
-#endif
 
   if (!sToplevel_event_hook_added) {
     sToplevel_event_hook_added = true;
     sToplevel_show_hook =
       g_signal_add_emission_hook(g_signal_lookup("show", GTK_TYPE_WINDOW),
                                  0, toplevel_event_watcher,
                                  reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW),
                                  nullptr);
@@ -205,27 +213,27 @@ a11y::PlatformShutdown()
     if (sToplevel_event_hook_added) {
       sToplevel_event_hook_added = false;
       g_signal_remove_emission_hook(g_signal_lookup("show", GTK_TYPE_WINDOW),
                                     sToplevel_show_hook);
       g_signal_remove_emission_hook(g_signal_lookup("hide", GTK_TYPE_WINDOW),
                                     sToplevel_hide_hook);
     }
 
-#if (MOZ_WIDGET_GTK == 2)
     if (sAtkBridge.lib) {
         // Do not shutdown/unload atk-bridge,
         // an exit function registered will take care of it
         // if (sAtkBridge.shutdown)
         //     (*sAtkBridge.shutdown)();
         // PR_UnloadLibrary(sAtkBridge.lib);
         sAtkBridge.lib = nullptr;
         sAtkBridge.init = nullptr;
         sAtkBridge.shutdown = nullptr;
     }
+#if (MOZ_WIDGET_GTK == 2)
     if (sGail.lib) {
         // Do not shutdown gail because
         // 1) Maybe it's not init-ed by us. e.g. GtkEmbed
         // 2) We need it to avoid assert in spi_atk_tidy_windows
         // if (sGail.shutdown)
         //   (*sGail.shutdown)();
         // PR_UnloadLibrary(sGail.lib);
         sGail.lib = nullptr;
--- a/accessible/generic/HyperTextAccessible-inl.h
+++ b/accessible/generic/HyperTextAccessible-inl.h
@@ -50,21 +50,32 @@ HyperTextAccessible::AddToSelection(int3
   dom::Selection* domSel = DOMSelection();
   return domSel &&
     SetSelectionBoundsAt(domSel->RangeCount(), aStartOffset, aEndOffset);
 }
 
 inline void
 HyperTextAccessible::ReplaceText(const nsAString& aText)
 {
-  int32_t numChars = CharacterCount();
-  if (numChars != 0)
-    DeleteText(0, numChars);
+  // We need to call DeleteText() even if there is no contents because we need
+  // to ensure to move focus to the editor via SetSelectionRange() called in
+  // DeleteText().
+  DeleteText(0, CharacterCount());
 
-  InsertText(aText, 0);
+  nsCOMPtr<nsIEditor> editor = GetEditor();
+  nsCOMPtr<nsIPlaintextEditor> plaintextEditor(do_QueryInterface(editor));
+  if (!plaintextEditor) {
+    return;
+  }
+
+  // DeleteText() may cause inserting <br> element in some cases. Let's
+  // select all again and replace whole contents.
+  editor->SelectAll();
+
+  plaintextEditor->InsertText(aText);
 }
 
 inline void
 HyperTextAccessible::InsertText(const nsAString& aText, int32_t aPosition)
 {
   nsCOMPtr<nsIEditor> editor = GetEditor();
   nsCOMPtr<nsIPlaintextEditor> peditor(do_QueryInterface(editor));
   if (peditor) {
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -347,35 +347,68 @@ HyperTextAccessible::TransformOffset(Acc
     descendant = parent;
   }
 
   // If the given a11y point cannot be mapped into offset relative this hypertext
   // offset then return length as fallback value.
   return CharacterCount();
 }
 
+/**
+ * GetElementAsContentOf() returns a content representing an element which is
+ * or includes aNode.
+ *
+ * XXX This method is enough to retrieve ::before or ::after pseudo element.
+ *     So, if you want to use this for other purpose, you might need to check
+ *     ancestors too.
+ */
+static nsIContent* GetElementAsContentOf(nsINode* aNode)
+{
+  if (aNode->IsElement()) {
+    return aNode->AsContent();
+  }
+  nsIContent* parent = aNode->GetParent();
+  return parent && parent->IsElement() ? parent : nullptr;
+}
+
 bool
 HyperTextAccessible::OffsetsToDOMRange(int32_t aStartOffset, int32_t aEndOffset,
                                        nsRange* aRange)
 {
   DOMPoint startPoint = OffsetToDOMPoint(aStartOffset);
   if (!startPoint.node)
     return false;
 
-  aRange->SetStart(startPoint.node, startPoint.idx);
+  // HyperTextAccessible manages pseudo elements generated by ::before or
+  // ::after.  However, contents of them are not in the DOM tree normally.
+  // Therefore, they are not selectable and editable.  So, when this creates
+  // a DOM range, it should not start from nor end in any pseudo contents.
+
+  nsIContent* container = GetElementAsContentOf(startPoint.node);
+  DOMPoint startPointForDOMRange =
+    ClosestNotGeneratedDOMPoint(startPoint, container);
+  aRange->SetStart(startPointForDOMRange.node, startPointForDOMRange.idx);
+
+  // If the caller wants collapsed range, let's collapse the range to its start.
   if (aStartOffset == aEndOffset) {
-    aRange->SetEnd(startPoint.node, startPoint.idx);
+    aRange->Collapse(true);
     return true;
   }
 
   DOMPoint endPoint = OffsetToDOMPoint(aEndOffset);
   if (!endPoint.node)
     return false;
 
-  aRange->SetEnd(endPoint.node, endPoint.idx);
+  if (startPoint.node != endPoint.node) {
+    container = GetElementAsContentOf(endPoint.node);
+  }
+
+  DOMPoint endPointForDOMRange =
+    ClosestNotGeneratedDOMPoint(endPoint, container);
+  aRange->SetEnd(endPointForDOMRange.node, endPointForDOMRange.idx);
   return true;
 }
 
 DOMPoint
 HyperTextAccessible::OffsetToDOMPoint(int32_t aOffset)
 {
   // 0 offset is valid even if no children. In this case the associated editor
   // is empty so return a DOM point for editor root element.
@@ -416,16 +449,46 @@ HyperTextAccessible::OffsetToDOMPoint(in
   NS_ASSERTION(innerOffset == 0 || innerOffset == 1, "A wrong inner offset!");
   nsINode* node = child->GetNode();
   nsINode* parentNode = node->GetParentNode();
   return parentNode ?
     DOMPoint(parentNode, parentNode->IndexOf(node) + innerOffset) :
     DOMPoint();
 }
 
+DOMPoint
+HyperTextAccessible::ClosestNotGeneratedDOMPoint(const DOMPoint& aDOMPoint,
+                                                 nsIContent* aElementContent)
+{
+  MOZ_ASSERT(aDOMPoint.node, "The node must not be null");
+
+  // ::before pseudo element
+  if (aElementContent &&
+      aElementContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore) {
+    MOZ_ASSERT(aElementContent->GetParent(),
+               "::before must have parent element");
+    // The first child of its parent (i.e., immediately after the ::before) is
+    // good point for a DOM range.
+    return DOMPoint(aElementContent->GetParent(), 0);
+  }
+
+  // ::after pseudo element
+  if (aElementContent &&
+      aElementContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter) {
+    MOZ_ASSERT(aElementContent->GetParent(),
+               "::after must have parent element");
+    // The end of its parent (i.e., immediately before the ::after) is good
+    // point for a DOM range.
+    return DOMPoint(aElementContent->GetParent(),
+                    aElementContent->GetParent()->GetChildCount());
+  }
+
+  return aDOMPoint;
+}
+
 uint32_t
 HyperTextAccessible::FindOffset(uint32_t aOffset, nsDirection aDirection,
                                 nsSelectionAmount aAmount,
                                 EWordMovementType aWordMovementType)
 {
   NS_ASSERTION(aDirection == eDirPrevious || aAmount != eSelectBeginLine,
                "eSelectBeginLine should only be used with eDirPrevious");
 
--- a/accessible/generic/HyperTextAccessible.h
+++ b/accessible/generic/HyperTextAccessible.h
@@ -134,17 +134,20 @@ public:
 
   /**
    * Transform the given a11y point into the offset relative this hypertext.
    */
   uint32_t TransformOffset(Accessible* aDescendant, uint32_t aOffset,
                            bool aIsEndOffset) const;
 
   /**
-   * Convert start and end hypertext offsets into DOM range.
+   * Convert start and end hypertext offsets into DOM range.  Note that if
+   * aStartOffset and/or aEndOffset is in generated content such as ::before or
+   * ::after, the result range excludes the generated content.  See also
+   * ClosestNotGeneratedDOMPoint() for more information.
    *
    * @param  aStartOffset  [in] the given start hypertext offset
    * @param  aEndOffset    [in] the given end hypertext offset
    * @param  aRange        [in, out] the range whose bounds to set
    * @return true   if conversion was successful
    */
   bool OffsetsToDOMRange(int32_t aStartOffset, int32_t aEndOffset,
                          nsRange* aRange);
@@ -513,16 +516,33 @@ protected:
 
   /**
    * Return selection ranges within the accessible subtree.
    */
   void GetSelectionDOMRanges(int16_t aType, nsTArray<nsRange*>* aRanges);
 
   nsresult SetSelectionRange(int32_t aStartPos, int32_t aEndPos);
 
+  /**
+   * Convert the given DOM point to a DOM point in non-generated contents.
+   *
+   * If aDOMPoint is in ::before, the result is immediately after it.
+   * If aDOMPoint is in ::after, the result is immediately before it.
+   *
+   * @param aDOMPoint       [in] A DOM node and an index of its child. This may
+   *                             be in a generated content such as ::before or
+   *                             ::after.
+   * @param aElementContent [in] An nsIContent representing an element of
+   *                             aDOMPoint.node.
+   * @return                An DOM point which must not be in generated
+   *                        contents.
+   */
+  DOMPoint ClosestNotGeneratedDOMPoint(const DOMPoint& aDOMPoint,
+                                       nsIContent* aElementContent);
+
   // Helpers
   nsresult GetDOMPointByFrameOffset(nsIFrame* aFrame, int32_t aOffset,
                                     Accessible* aAccessible,
                                     mozilla::a11y::DOMPoint* aPoint);
 
   /**
    * Set 'misspelled' text attribute and return range offsets where the
    * attibute is stretched. If the text is not misspelled at the given offset
--- a/accessible/tests/mochitest/editabletext/editabletext.js
+++ b/accessible/tests/mochitest/editabletext/editabletext.js
@@ -51,29 +51,32 @@ function editableTextTest(aID)
       this.unwrapNextTest();
       this.mEventQueueReady = true;
     }
   }
 
   /**
    * setTextContents test.
    */
-  this.setTextContents = function setTextContents(aValue)
+  this.setTextContents = function setTextContents(aValue, aSkipStartOffset)
   {
     var testID = "setTextContents '" + aValue + "' for " + prettyName(aID);
 
     function setTextContentsInvoke()
     {
       var acc = getAccessible(aID, nsIAccessibleEditableText);
       acc.setTextContents(aValue);
     }
 
-    var insertTripple = aValue ? [0, aValue.length, aValue] : null;
+    aSkipStartOffset = aSkipStartOffset || 0;
+    var insertTripple = aValue ?
+      [ aSkipStartOffset, aSkipStartOffset + aValue.length, aValue ] : null;
     var oldValue = getValue(aID);
-    var removeTripple = oldValue ? [0, oldValue.length, oldValue] : null;
+    var removeTripple = oldValue ?
+      [ aSkipStartOffset, aSkipStartOffset + oldValue.length, oldValue ] : null;
 
     this.generateTest(aID, removeTripple, insertTripple, setTextContentsInvoke,
                       getValueChecker(aID, aValue), testID);
   }
 
   /**
    * insertText test.
    */
--- a/accessible/tests/mochitest/editabletext/test_1.html
+++ b/accessible/tests/mochitest/editabletext/test_1.html
@@ -15,32 +15,34 @@ https://bugzilla.mozilla.org/show_bug.cg
           src="../common.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
   <script type="application/javascript"
           src="editabletext.js"></script>
 
   <script type="application/javascript">
 
-    function addTestEditable(aID, aTestRun)
+    function addTestEditable(aID, aTestRun, aBeforeContent, aAfterContent)
     {
       var et = new editableTextTest(aID);
+      var startOffset = aBeforeContent ? aBeforeContent.length : 0;
+      // XXX afterContent currently is not used
 
       //////////////////////////////////////////////////////////////////////////
       // setTextContents
-      et.scheduleTest(et.setTextContents, "hello");
-      et.scheduleTest(et.setTextContents, "olleh");
-      et.scheduleTest(et.setTextContents, "");
+      et.scheduleTest(et.setTextContents, "hello", startOffset);
+      et.scheduleTest(et.setTextContents, "olleh", startOffset);
+      et.scheduleTest(et.setTextContents, "", startOffset);
 
       //////////////////////////////////////////////////////////////////////////
       // insertText
-      et.scheduleTest(et.insertText, "hello", 0, "hello");
-      et.scheduleTest(et.insertText, "ma ", 0, "ma hello");
-      et.scheduleTest(et.insertText, "ma", 2, "mama hello");
-      et.scheduleTest(et.insertText, " hello", 10, "mama hello hello");
+      et.scheduleTest(et.insertText, "hello", startOffset, "hello");
+      et.scheduleTest(et.insertText, "ma ", startOffset, "ma hello");
+      et.scheduleTest(et.insertText, "ma", startOffset + 2, "mama hello");
+      et.scheduleTest(et.insertText, " hello", startOffset + 10, "mama hello hello");
 
       // XXX: bug 452584
 
       //////////////////////////////////////////////////////////////////////////
       // deleteText
 //      et.deleteText(0, 5, "hello hello");
 //      et.deleteText(5, 6, "hellohello");
 //      et.deleteText(5, 10, "hello");
@@ -66,17 +68,20 @@ https://bugzilla.mozilla.org/show_bug.cg
     //gA11yEventDumpToConsole = true; // debug stuff
 
     function runTest()
     {
       var testRun = new editableTextTestRun();
 
       addTestEditable("input", testRun);
       addTestEditable("div", testRun);
-      addTestEditable(getNode("frame").contentDocument, testRun, '\n');
+      addTestEditable("divb", testRun, "pseudo element", "");
+      addTestEditable("diva", testRun, "", "pseudo element");
+      addTestEditable("divba", testRun, "before", "after");
+      addTestEditable(getNode("frame").contentDocument, testRun);
 
       testRun.run(); // Will call SimpleTest.finish();
     }
 
     function doTest()
     {
       // Prepare tested elements.
 
@@ -85,31 +90,53 @@ https://bugzilla.mozilla.org/show_bug.cg
       var frame = getNode("frame");
       waitForEvent(EVENT_STATE_CHANGE, frame.contentDocument, runTest);
       frame.contentDocument.designMode = "on";
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
+  <style>
+    #divb::before,
+    #diva::after {
+      content: "pseudo element";
+    }
+    #divba::before {
+      content: "before";
+    }
+    #divba::after {
+      content: "after";
+    }
+  </style>
 </head>
 <body>
 
   <a target="_blank"
      title="nsIAccessibleEditableText chrome tests"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=452161">Mozilla Bug 452161</a>
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=452161">
+    Bug 452161
+  </a>
   <a target="_blank"
      title="Cache rendered text on a11y side"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=626660">
-    Mozilla Bug 626660
+    Bug 626660
+  </a>
+  <a target="_blank"
+     title="Pseudo element support test"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1105611">
+    Bug 1105611
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <input id="input"/>
 
-  <div id="div" contentEditable="true"></div>
+  <div id="div" contenteditable="true"></div>
+  <div id="divb" contenteditable="true"></div>
+  <div id="diva" contenteditable="true"></div>
+  <div id="divba" contenteditable="true"></div>
 
   <iframe id="frame"/>
 </body>
 </html>
--- a/config/system-headers
+++ b/config/system-headers
@@ -184,17 +184,16 @@ app/MessageRunner.h
 arpa/inet.h
 arpa/nameser.h
 asm/page.h
 asm/sigcontext.h
 asm/signal.h
 ASRegistry.h
 assert.h
 atk/atk.h
-atk-bridge.h
 atlcom.h
 atlconv.h
 atlctl.cpp
 atlctl.h
 ATLCTL.H
 atlhost.h
 atlimpl.cpp
 atlwin.cpp
--- a/configure.in
+++ b/configure.in
@@ -4403,17 +4403,17 @@ if test "$MOZ_ENABLE_XREMOTE"; then
 fi
 
 if test "$MOZ_INSTRUMENT_EVENT_LOOP"; then
    AC_DEFINE(MOZ_INSTRUMENT_EVENT_LOOP)
 fi
 
 if test "$COMPILE_ENVIRONMENT"; then
   if test "$MOZ_ENABLE_GTK3"; then
-    PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 atk-bridge-2.0 $GDK_PACKAGES)
+    PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
     MOZ_GTK3_CFLAGS="-I${_topsrcdir}/widget/gtk/compat-gtk3 $MOZ_GTK3_CFLAGS"
     dnl Contrary to MOZ_GTK2_LIBS, MOZ_GTK3_LIBS needs to be literally added to TK_LIBS instead
     dnl of a make reference because of how TK_LIBS is mangled in toolkit/library/moz.build
     dnl for GTK+3 builds.
     TK_LIBS=$MOZ_GTK3_LIBS
     GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32
   fi
   if test "$MOZ_ENABLE_GTK2"; then
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -14102,16 +14102,23 @@ nsGlobalWindow::ClearDocumentDependentSl
 /* static */
 JSObject*
 nsGlobalWindow::CreateNamedPropertiesObject(JSContext *aCx,
                                             JS::Handle<JSObject*> aProto)
 {
   return WindowNamedPropertiesHandler::Create(aCx, aProto);
 }
 
+bool
+nsGlobalWindow::GetIsPrerendered()
+{
+  nsIDocShell* docShell = GetDocShell();
+  return docShell && docShell->GetIsPrerendered();
+}
+
 #ifdef MOZ_B2G
 void
 nsGlobalWindow::EnableNetworkEvent(uint32_t aType)
 {
   MOZ_ASSERT(IsInnerWindow());
 
   nsCOMPtr<nsIPermissionManager> permMgr =
     services::GetPermissionManager();
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1267,16 +1267,18 @@ public:
   bool PopupWhitelisted();
   PopupControlState RevisePopupAbuseLevel(PopupControlState);
   void     FireAbuseEvents(bool aBlocked, bool aWindow,
                            const nsAString &aPopupURL,
                            const nsAString &aPopupWindowName,
                            const nsAString &aPopupWindowFeatures);
   void FireOfflineStatusEventIfChanged();
 
+  bool GetIsPrerendered();
+
   // Inner windows only.
   nsresult ScheduleNextIdleObserverCallback();
   uint32_t GetFuzzTimeMS();
   nsresult ScheduleActiveTimerCallback();
   uint32_t FindInsertionIndex(IdleObserverHolder* aIdleObserver);
   virtual nsresult RegisterIdleObserver(nsIIdleObserver* aIdleObserverPtr) MOZ_OVERRIDE;
   nsresult FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,
                                       int32_t* aRemoveElementIndex);
--- a/dom/base/nsPlainTextSerializer.cpp
+++ b/dom/base/nsPlainTextSerializer.cpp
@@ -83,17 +83,17 @@ nsPlainTextSerializer::nsPlainTextSerial
 
   // Line breaker
   mWrapColumn = 72;     // XXX magic number, we expect someone to reset this
   mCurrentLineWidth = 0;
 
   // Flow
   mEmptyLines = 1; // The start of the document is an "empty line" in itself,
   mInWhitespace = false;
-  mPreFormatted = false;
+  mPreFormattedMail = false;
   mStartedOutput = false;
 
   mPreformattedBlockBoundary = false;
 
   // initialize the tag stack to zero:
   // The stack only ever contains pointers to static atoms, so they don't
   // need refcounting.
   mTagStack = new nsIAtom*[TagStackSize];
@@ -494,33 +494,33 @@ nsPlainTextSerializer::DoOpenContainer(n
     // Ignore everything that follows the current tag in 
     // question until a matching end tag is encountered.
     mIgnoreAboveIndex = mTagStackIndex - 1;
     return NS_OK;
   }
 
   if (aTag == nsGkAtoms::body) {
     // Try to figure out here whether we have a
-    // preformatted style attribute.
+    // preformatted style attribute set by Thunderbird.
     //
     // Trigger on the presence of a "pre-wrap" in the
     // style attribute. That's a very simplistic way to do
     // it, but better than nothing.
     // Also set mWrapColumn to the value given there
     // (which arguably we should only do if told to do so).
     nsAutoString style;
     int32_t whitespace;
     if (NS_SUCCEEDED(GetAttributeValue(nsGkAtoms::style, style)) &&
        (kNotFound != (whitespace = style.Find("white-space:")))) {
 
       if (kNotFound != style.Find("pre-wrap", true, whitespace)) {
 #ifdef DEBUG_preformatted
-        printf("Set mPreFormatted based on style pre-wrap\n");
+        printf("Set mPreFormattedMail based on style pre-wrap\n");
 #endif
-        mPreFormatted = true;
+        mPreFormattedMail = true;
         int32_t widthOffset = style.Find("width:");
         if (widthOffset >= 0) {
           // We have to search for the ch before the semicolon,
           // not for the semicolon itself, because nsString::ToInteger()
           // considers 'c' to be a valid numeric char (even if radix=10)
           // but then gets confused if it sees it next to the number
           // when the radix specified was 10, and returns an error code.
           int32_t semiOffset = style.Find("ch", false, widthOffset+6);
@@ -536,26 +536,26 @@ nsPlainTextSerializer::DoOpenContainer(n
 #ifdef DEBUG_preformatted
             printf("Set wrap column to %d based on style\n", mWrapColumn);
 #endif
           }
         }
       }
       else if (kNotFound != style.Find("pre", true, whitespace)) {
 #ifdef DEBUG_preformatted
-        printf("Set mPreFormatted based on style pre\n");
+        printf("Set mPreFormattedMail based on style pre\n");
 #endif
-        mPreFormatted = true;
+        mPreFormattedMail = true;
         mWrapColumn = 0;
       }
     } 
     else {
       /* See comment at end of function. */
       mInWhitespace = true;
-      mPreFormatted = false;
+      mPreFormattedMail = false;
     }
 
     return NS_OK;
   }
 
   // Keep this in sync with DoCloseContainer!
   if (!DoOutput()) {
     return NS_OK;
@@ -1030,17 +1030,17 @@ nsPlainTextSerializer::DoAddText(bool aI
   if (aIsLineBreak) {
     // The only times we want to pass along whitespace from the original
     // html source are if we're forced into preformatted mode via flags,
     // or if we're prettyprinting and we're inside a <pre>.
     // Otherwise, either we're collapsing to minimal text, or we're
     // prettyprinting to mimic the html format, and in neither case
     // does the formatting of the html source help us.
     if ((mFlags & nsIDocumentEncoder::OutputPreformatted) ||
-        (mPreFormatted && !mWrapColumn) ||
+        (mPreFormattedMail && !mWrapColumn) ||
         IsInPre()) {
       EnsureVerticalSpace(mEmptyLines+1);
     }
     else if (!mInWhitespace) {
       Write(kSpace);
       mInWhitespace = true;
     }
     return;
@@ -1551,24 +1551,24 @@ nsPlainTextSerializer::Write(const nsASt
       else
         break;
     }
   }
 
   // We have two major codepaths here. One that does preformatted text and one
   // that does normal formatted text. The one for preformatted text calls
   // Output directly while the other code path goes through AddToLine.
-  if ((mPreFormatted && !mWrapColumn) || IsInPre()
+  if ((mPreFormattedMail && !mWrapColumn) || (IsInPre() && !mPreFormattedMail)
       || ((mSpanLevel > 0 || mDontWrapAnyQuotes)
           && mEmptyLines >= 0 && str.First() == char16_t('>'))) {
     // No intelligent wrapping.
 
     // This mustn't be mixed with intelligent wrapping without clearing
     // the mCurrentLine buffer before!!!
-    NS_ASSERTION(mCurrentLine.IsEmpty() || IsInPre(),
+    NS_ASSERTION(mCurrentLine.IsEmpty() || (IsInPre() && !mPreFormattedMail),
                  "Mixed wrapping data and nonwrapping data on the same line");
     if (!mCurrentLine.IsEmpty()) {
       FlushLine();
     }
 
     // Put the mail quote "> " chars in, if appropriate.
     // Have to put it in before every line.
     while(bol<totLen) {
@@ -1696,17 +1696,17 @@ nsPlainTextSerializer::Write(const nsASt
         if (offsetIntoBuffer[0] == '\n' && IS_CJ_CHAR(offsetIntoBuffer[-1]) && IS_CJ_CHAR(offsetIntoBuffer[1])) {
           offsetIntoBuffer = str.get() + bol;
           AddToLine(offsetIntoBuffer, nextpos-bol);
           bol = nextpos + 1;
           continue;
         }
       }
       // If we're already in whitespace and not preformatted, just skip it:
-      if (mInWhitespace && (nextpos == bol) && !mPreFormatted &&
+      if (mInWhitespace && (nextpos == bol) && !mPreFormattedMail &&
           !(mFlags & nsIDocumentEncoder::OutputPreformatted)) {
         // Skip whitespace
         bol++;
         continue;
       }
 
       if (nextpos == bol) {
         // Note that we are in whitespace.
@@ -1715,17 +1715,17 @@ nsPlainTextSerializer::Write(const nsASt
         AddToLine(offsetIntoBuffer, 1);
         bol++;
         continue;
       }
       
       mInWhitespace = true;
       
       offsetIntoBuffer = str.get() + bol;
-      if (mPreFormatted || (mFlags & nsIDocumentEncoder::OutputPreformatted)) {
+      if (mPreFormattedMail || (mFlags & nsIDocumentEncoder::OutputPreformatted)) {
         // Preserve the real whitespace character
         nextpos++;
         AddToLine(offsetIntoBuffer, nextpos-bol);
         bol = nextpos;
       } 
       else {
         // Replace the whitespace with a space
         AddToLine(offsetIntoBuffer, nextpos-bol);
--- a/dom/base/nsPlainTextSerializer.h
+++ b/dom/base/nsPlainTextSerializer.h
@@ -159,17 +159,18 @@ private:
   int32_t          mSpanLevel;
 
 
   int32_t          mEmptyLines; // Will be the number of empty lines before
                                 // the current. 0 if we are starting a new
                                 // line and -1 if we are in a line.
 
   bool             mInWhitespace;
-  bool             mPreFormatted;
+  bool             mPreFormattedMail; // we're dealing with special DOM
+                                      // used by Thunderbird code.
   bool             mStartedOutput; // we've produced at least a character
 
   // While handling a new tag, this variable should remind if any line break
   // is due because of a closing tag. Setting it to "TRUE" while closing the tags.
   // Hence opening tags are guaranteed to start with appropriate line breaks.
   bool             mLineBreakDue;
 
   bool             mPreformattedBlockBoundary;
--- a/dom/base/test/TestPlainTextSerializer.cpp
+++ b/dom/base/test/TestPlainTextSerializer.cpp
@@ -158,16 +158,49 @@ TestBlockElement()
     return NS_ERROR_FAILURE;
   }
 
   passed("prettyprinted HTML to text serialization test");
   return NS_OK;
 }
 
 nsresult
+TestPreWrapElementForThunderbird()
+{
+  // This test examines the magic pre-wrap setup that Thunderbird relies on.
+  nsString test;
+  test.AppendLiteral(
+    "<html>" NS_LINEBREAK
+    "<body style=\"white-space: pre-wrap; width: 10ch;\">" NS_LINEBREAK
+    "<pre>" NS_LINEBREAK
+    "  first line is too long" NS_LINEBREAK
+    "  second line is even loooonger  " NS_LINEBREAK
+    "</pre>" NS_LINEBREAK
+    "</body>" NS_LINEBREAK "</html>");
+
+  ConvertBufToPlainText(test, nsIDocumentEncoder::OutputWrap);
+  // "\n\n  first\nline is\ntoo long\n  second\nline is\neven\nloooonger\n\n\n"
+  if (!test.EqualsLiteral(NS_LINEBREAK NS_LINEBREAK
+                          "  first" NS_LINEBREAK
+                          "line is" NS_LINEBREAK
+                          "too long" NS_LINEBREAK
+                          "  second" NS_LINEBREAK
+                          "line is" NS_LINEBREAK
+                          "even" NS_LINEBREAK
+                          "loooonger" NS_LINEBREAK
+                          NS_LINEBREAK NS_LINEBREAK)) {
+    fail("Wrong prettyprinted html to text serialization");
+    return NS_ERROR_FAILURE;
+  }
+
+  passed("prettyprinted HTML to text serialization test");
+  return NS_OK;
+}
+
+nsresult
 TestPlainTextSerializer()
 {
   nsString test;
   test.AppendLiteral("<html><base>base</base><head><span>span</span></head>"
                      "<body>body</body></html>");
   ConvertBufToPlainText(test, 0);
   if (!test.EqualsLiteral("basespanbody")) {
     fail("Wrong html to text serialization");
@@ -186,16 +219,19 @@ TestPlainTextSerializer()
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = TestPreElement();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = TestBlockElement();
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = TestPreWrapElementForThunderbird();
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // Add new tests here...
   return NS_OK;
 }
 
 int main(int argc, char** argv)
 {
   ScopedXPCOM xpcom("PlainTextSerializer");
   if (xpcom.failed())
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2412,23 +2412,17 @@ EnforceNotInPrerendering(JSContext* aCx,
     return true;
   }
   nsGlobalWindow* window = xpc::WindowGlobalOrNull(thisObj);
   if (!window) {
     // Without a window, we cannot check the safety.
     return true;
   }
 
-  nsIDocShell* docShell = window->GetDocShell();
-  if (!docShell) {
-    // Without a docshell, we cannot check the safety.
-    return true;
-  }
-
-  if (docShell->GetIsPrerendered()) {
+  if (window->GetIsPrerendered()) {
     HandlePrerenderingViolation(window);
     // When the bindings layer sees a false return value, it returns false form
     // the JSNative in order to trigger an uncatchable exception.
     return false;
   }
 
   return true;
 }
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -217,17 +217,17 @@ GetDOMClass(JSObject* obj)
 inline nsISupports*
 UnwrapDOMObjectToISupports(JSObject* aObject)
 {
   const DOMJSClass* clasp = GetDOMClass(aObject);
   if (!clasp || !clasp->mDOMObjectIsISupports) {
     return nullptr;
   }
 
-  return UnwrapDOMObject<nsISupports>(aObject);
+  return UnwrapPossiblyNotInitializedDOMObject<nsISupports>(aObject);
 }
 
 inline bool
 IsDOMObject(JSObject* obj)
 {
   return IsDOMClass(js::GetObjectClass(obj));
 }
 
@@ -3031,62 +3031,64 @@ struct CreateGlobalOptions<nsGlobalWindo
   static MOZ_CONSTEXPR_VAR bool ForceInitStandardClassesToFalse = false;
   static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
   static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
 };
 
 nsresult
 RegisterDOMNames();
 
+// The return value is whatever the ProtoHandleGetter we used
+// returned.  This should be the DOM prototype for the global.
 template <class T, ProtoHandleGetter GetProto>
-bool
+JS::Handle<JSObject*>
 CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
              const JSClass* aClass, JS::CompartmentOptions& aOptions,
              JSPrincipals* aPrincipal, bool aInitStandardClasses,
              JS::MutableHandle<JSObject*> aGlobal)
 {
   aOptions.setTrace(CreateGlobalOptions<T>::TraceGlobal);
 
   aGlobal.set(JS_NewGlobalObject(aCx, aClass, aPrincipal,
                                  JS::DontFireOnNewGlobalHook, aOptions));
   if (!aGlobal) {
     NS_WARNING("Failed to create global");
-    return false;
+    return JS::NullPtr();
   }
 
   JSAutoCompartment ac(aCx, aGlobal);
 
   {
     js::SetReservedSlot(aGlobal, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aNative));
     NS_ADDREF(aNative);
 
     aCache->SetWrapper(aGlobal);
 
     dom::AllocateProtoAndIfaceCache(aGlobal,
                                     CreateGlobalOptions<T>::ProtoAndIfaceCacheKind);
 
     if (!CreateGlobalOptions<T>::PostCreateGlobal(aCx, aGlobal)) {
-      return false;
+      return JS::NullPtr();
     }
   }
 
   if (aInitStandardClasses &&
       !CreateGlobalOptions<T>::ForceInitStandardClassesToFalse &&
       !JS_InitStandardClasses(aCx, aGlobal)) {
     NS_WARNING("Failed to init standard classes");
-    return false;
+    return JS::NullPtr();
   }
 
   JS::Handle<JSObject*> proto = GetProto(aCx, aGlobal);
   if (!proto || !JS_SplicePrototype(aCx, aGlobal, proto)) {
     NS_WARNING("Failed to set proto");
-    return false;
+    return JS::NullPtr();
   }
 
-  return true;
+  return proto;
 }
 
 /*
  * Holds a jsid that is initialized to an interned string, with conversion to
  * Handle<jsid>.
  */
 class InternedStringId
 {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7,17 +7,17 @@
 import os
 import re
 import string
 import math
 import textwrap
 import functools
 
 from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLInterfaceMember, IDLUndefinedValue, IDLEmptySequenceValue, IDLDictionary
-from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, getAllTypes, Descriptor
+from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, getAllTypes, Descriptor, MemberIsUnforgeable
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 OBJECT_MOVED_HOOK_NAME = '_objectMoved'
 CONSTRUCT_HOOK_NAME = '_constructor'
 LEGACYCALLER_HOOK_NAME = '_legacycaller'
@@ -547,32 +547,16 @@ def PrototypeIDAndDepth(descriptor):
             prototypeID += "_workers"
         depth = "PrototypeTraits<%s>::Depth" % prototypeID
     else:
         prototypeID += "_ID_Count"
         depth = "0"
     return (prototypeID, depth)
 
 
-def MemberIsUnforgeable(member, descriptor):
-    # Note: "or" and "and" return either their LHS or RHS, not
-    # necessarily booleans.  Make sure to return a boolean from this
-    # method, because callers will compare its return value to
-    # booleans.
-    return bool((member.isAttr() or member.isMethod()) and
-                not member.isStatic() and
-                (member.isUnforgeable() or
-                 descriptor.interface.getExtendedAttribute("Unforgeable")))
-
-
-def HasUnforgeableMembers(descriptor):
-    return any(MemberIsUnforgeable(m, descriptor) for m in
-               descriptor.interface.members)
-
-
 def InterfacePrototypeObjectProtoGetter(descriptor):
     """
     Returns a tuple with two elements:
 
         1) The name of the function to call to get the prototype to use for the
            interface prototype object as a JSObject*.
 
         2) The name of the function to call to get the prototype to use for the
@@ -606,16 +590,18 @@ class CGPrototypeJSClass(CGThing):
 
     def declare(self):
         # We're purely for internal consumption
         return ""
 
     def define(self):
         prototypeID, depth = PrototypeIDAndDepth(self.descriptor)
         slotCount = "DOM_INTERFACE_PROTO_SLOTS_BASE"
+        if self.descriptor.hasUnforgeableMembers:
+            slotCount += " + 1 /* slot for the JSObject holding the unforgeable properties */"
         (protoGetter, _) = InterfacePrototypeObjectProtoGetter(self.descriptor)
         type = "eGlobalInterfacePrototype" if self.descriptor.isGlobal() else "eInterfacePrototype"
         return fill(
             """
             static const DOMIfaceAndProtoJSClass PrototypeClass = {
               {
                 "${name}Prototype",
                 JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(${slotCount}),
@@ -1519,18 +1505,19 @@ class CGAddPropertyHook(CGAbstractClassH
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('JS::MutableHandle<JS::Value>', 'vp')]
         CGAbstractClassHook.__init__(self, descriptor, ADDPROPERTY_HOOK_NAME,
                                      'bool', args)
 
     def generate_code(self):
         assert self.descriptor.wrapperCache
         return dedent("""
-            // We don't want to preserve if we don't have a wrapper.
-            if (self->GetWrapperPreserveColor()) {
+            // We don't want to preserve if we don't have a wrapper, and we
+            // obviously can't preserve if we're not initialized.
+            if (self && self->GetWrapperPreserveColor()) {
               PreserveWrapper(self);
             }
             return true;
             """)
 
 
 def finalizeHook(descriptor, hookName, freeOp):
     finalize = "JSBindingFinalized<%s>::Finalized(self);\n" % descriptor.nativeType
@@ -2629,16 +2616,65 @@ class CGCreateInterfaceObjectsMethod(CGA
             prefCache = CGWrapper(CGIndenter(CGList(prefCacheData)),
                                   pre=("static bool sPrefCachesInited = false;\n"
                                        "if (!sPrefCachesInited) {\n"
                                        "  sPrefCachesInited = true;\n"),
                                   post="}\n")
         else:
             prefCache = None
 
+        if self.descriptor.hasUnforgeableMembers:
+            assert needInterfacePrototypeObject
+            # We want to use the same JSClass and prototype as the object we'll
+            # end up defining the unforgeable properties on in the end, so that
+            # we can use JS_InitializePropertiesFromCompatibleNativeObject to do
+            # a fast copy.  In the case of proxies that's null, because the
+            # expando object is a vanilla object, but in the case of other DOM
+            # objects it's whatever our class is.
+            #
+            # Also, for a global we can't use the global's class; just use
+            # nullpr and when we do the copy off the holder we'll take a slower
+            # path.  This also means that we don't need to worry about matching
+            # the prototype.
+            if self.descriptor.proxy or self.descriptor.isGlobal():
+                holderClass = "nullptr"
+                holderProto = "nullptr"
+            else:
+                holderClass = "Class.ToJSClass()"
+                holderProto = "*protoCache"
+            failureCode = dedent(
+                """
+                *protoCache = nullptr;
+                if (interfaceCache) {
+                  *interfaceCache = nullptr;
+                }
+                return;
+                """)
+            createUnforgeableHolder = CGGeneric(fill(
+                """
+                JS::Rooted<JSObject*> unforgeableHolder(aCx);
+                {
+                  JS::Rooted<JSObject*> holderProto(aCx, ${holderProto});
+                  unforgeableHolder = JS_NewObjectWithoutMetadata(aCx, ${holderClass}, holderProto);
+                  if (!unforgeableHolder) {
+                    $*{failureCode}
+                  }
+                }
+                """,
+                holderProto=holderProto,
+                holderClass=holderClass,
+                failureCode=failureCode))
+            defineUnforgeables = InitUnforgeablePropertiesOnHolder(self.descriptor,
+                                                                   self.properties,
+                                                                   failureCode)
+            createUnforgeableHolder = CGList(
+                [createUnforgeableHolder, defineUnforgeables])
+        else:
+            createUnforgeableHolder = None
+
         getParentProto = fill(
             """
             JS::${type}<JSObject*> parentProto(${getParentProto});
             if (!parentProto) {
               return;
             }
             """,
             type=parentProtoType,
@@ -2694,38 +2730,52 @@ class CGCreateInterfaceObjectsMethod(CGA
             chromeProperties = "nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr"
         elif self.properties.hasChromeOnly():
             chromeProperties = "!GlobalPropertiesAreOwn() && nsContentUtils::ThreadsafeIsCallerChrome() ? &sChromeOnlyNativeProperties : nullptr"
         else:
             chromeProperties = "nullptr"
 
         call = fill(
             """
+            JS::Heap<JSObject*>* protoCache = ${protoCache};
+            JS::Heap<JSObject*>* interfaceCache = ${interfaceCache};
             dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
-                                        ${protoClass}, ${protoCache},
+                                        ${protoClass}, protoCache,
                                         constructorProto, ${interfaceClass}, ${constructHookHolder}, ${constructArgs}, ${namedConstructors},
-                                        ${interfaceCache},
+                                        interfaceCache,
                                         ${properties},
                                         ${chromeProperties},
                                         ${name}, aDefineOnGlobal);
             """,
             protoClass=protoClass,
             protoCache=protoCache,
             interfaceClass=interfaceClass,
             constructHookHolder=constructHookHolder,
             constructArgs=constructArgs,
             namedConstructors=namedConstructors,
             interfaceCache=interfaceCache,
             properties=properties,
             chromeProperties=chromeProperties,
             name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr")
 
+        if self.descriptor.hasUnforgeableMembers:
+            assert needInterfacePrototypeObject
+            setUnforgeableHolder = CGGeneric(fill(
+                """
+                if (*protoCache) {
+                  js::SetReservedSlot(*protoCache, DOM_INTERFACE_PROTO_SLOTS_BASE,
+                                      JS::ObjectValue(*unforgeableHolder));
+                }
+                """,
+                name=self.descriptor.name))
+        else:
+            setUnforgeableHolder = None
         return CGList(
             [CGGeneric(getParentProto), CGGeneric(getConstructorProto), initIds,
-             prefCache, CGGeneric(call)],
+             prefCache, CGGeneric(call), createUnforgeableHolder, setUnforgeableHolder],
             "\n").define()
 
 
 class CGGetPerInterfaceObject(CGAbstractMethod):
     """
     A method for getting a per-interface object (a prototype object or interface
     constructor object).
     """
@@ -3018,25 +3068,81 @@ def CreateBindingJSObject(descriptor, pr
             creator.CreateObject(aCx, Class.ToJSClass(), proto, aObject, aReflector);
             if (!aReflector) {
               return false;
             }
             """)
     return objDecl + create
 
 
-def InitUnforgeableProperties(descriptor, properties, wrapperCache):
-    """
-    properties is a PropertyArrays instance
-    """
-    unforgeableAttrs = properties.unforgeableAttrs
-    if not unforgeableAttrs.hasNonChromeOnly() and not unforgeableAttrs.hasChromeOnly():
+def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode):
+    """
+    Define the unforgeable properties on the unforgeable holder for
+    the interface represented by descriptor.
+
+    properties is a PropertyArrays instance.
+
+    """
+    assert (properties.unforgeableAttrs.hasNonChromeOnly() or
+            properties.unforgeableAttrs.hasChromeOnly() or
+            properties.unforgeableMethods.hasNonChromeOnly() or
+            properties.unforgeableMethods.hasChromeOnly)
+
+    unforgeables = []
+
+    defineUnforgeableAttrs = fill(
+        """
+        if (!DefineUnforgeableAttributes(aCx, unforgeableHolder, %s)) {
+          $*{failureCode}
+        }
+        """,
+        failureCode=failureCode)
+    defineUnforgeableMethods = fill(
+        """
+        if (!DefineUnforgeableMethods(aCx, unforgeableHolder, %s)) {
+          $*{failureCode}
+        }
+        """,
+        failureCode=failureCode)
+
+    unforgeableMembers = [
+        (defineUnforgeableAttrs, properties.unforgeableAttrs),
+        (defineUnforgeableMethods, properties.unforgeableMethods)
+    ]
+    for (template, array) in unforgeableMembers:
+        if array.hasNonChromeOnly():
+            unforgeables.append(CGGeneric(template % array.variableName(False)))
+        if array.hasChromeOnly():
+            unforgeables.append(
+                CGIfWrapper(CGGeneric(template % array.variableName(True)),
+                            "nsContentUtils::ThreadsafeIsCallerChrome()"))
+
+    if descriptor.interface.getExtendedAttribute("Unforgeable"):
+        # We do our undefined toJSON here, not as a regular property
+        # because we don't have a concept of value props anywhere in IDL.
+        unforgeables.append(CGGeneric(fill(
+            """
+            if (!JS_DefineProperty(aCx, unforgeableHolder, "toJSON", JS::UndefinedHandleValue,
+                                   JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
+              $*{failureCode}
+            }
+            """,
+            failureCode=failureCode)))
+
+    return CGWrapper(CGList(unforgeables), pre="\n")
+
+def CopyUnforgeablePropertiesToInstance(descriptor, wrapperCache):
+    """
+    Copy the unforgeable properties from the unforgeable holder for
+    this interface to the instance object we have.
+    """
+    if not descriptor.hasUnforgeableMembers:
         return ""
 
-    unforgeables = [
+    copyCode = [
         CGGeneric(dedent(
             """
             // Important: do unforgeable property setup after we have handed
             // over ownership of the C++ object to obj as needed, so that if
             // we fail and it ends up GCed it won't have problems in the
             // finalizer trying to drop its ownership of the C++ object.
             """))
     ]
@@ -3048,76 +3154,54 @@ def InitUnforgeableProperties(descriptor
             aCache->ClearWrapper();
             """)
     else:
         cleanup = ""
 
     # For proxies, we want to define on the expando object, not directly on the
     # reflector, so we can make sure we don't get confused by named getters.
     if descriptor.proxy:
-        unforgeables.append(CGGeneric(fill(
+        copyCode.append(CGGeneric(fill(
             """
             JS::Rooted<JSObject*> expando(aCx,
               DOMProxyHandler::EnsureExpandoObject(aCx, aReflector));
             if (!expando) {
               $*{cleanup}
               return false;
             }
             """,
             cleanup=cleanup)))
         obj = "expando"
     else:
         obj = "aReflector"
 
-    defineUnforgeableAttrs = fill(
+    # We can't do the fast copy for globals, because we can't allocate the
+    # unforgeable holder for those with the right JSClass.  Luckily, there
+    # aren't too many globals being created.
+    if descriptor.isGlobal():
+        copyFunc = "JS_CopyPropertiesFrom"
+    else:
+        copyFunc = "JS_InitializePropertiesFromCompatibleNativeObject"
+    copyCode.append(CGGeneric(fill(
         """
-        if (!DefineUnforgeableAttributes(aCx, ${obj}, %s)) {
-          $*{cleanup}
-          return false;
-        }
-        """,
-        obj=obj,
-        cleanup=cleanup)
-    defineUnforgeableMethods = fill(
-        """
-        if (!DefineUnforgeableMethods(aCx, ${obj}, %s)) {
+        // XXXbz Once we allow subclassing, we'll want to make sure that
+        // this uses the canonical proto, not whatever random passed-in
+        // proto we end up using for the object.
+        JS::Rooted<JSObject*> unforgeableHolder(aCx,
+          &js::GetReservedSlot(proto, DOM_INTERFACE_PROTO_SLOTS_BASE).toObject());
+        if (!${copyFunc}(aCx, ${obj}, unforgeableHolder)) {
           $*{cleanup}
           return false;
         }
         """,
+        copyFunc=copyFunc,
         obj=obj,
-        cleanup=cleanup)
-
-    unforgeableMembers = [
-        (defineUnforgeableAttrs, properties.unforgeableAttrs),
-        (defineUnforgeableMethods, properties.unforgeableMethods)
-    ]
-    for (template, array) in unforgeableMembers:
-        if array.hasNonChromeOnly():
-            unforgeables.append(CGGeneric(template % array.variableName(False)))
-        if array.hasChromeOnly():
-            unforgeables.append(
-                CGIfWrapper(CGGeneric(template % array.variableName(True)),
-                            "nsContentUtils::ThreadsafeIsCallerChrome()"))
-
-    if descriptor.interface.getExtendedAttribute("Unforgeable"):
-        # We do our undefined toJSON here, not as a regular property
-        # because we don't have a concept of value props anywhere.
-        unforgeables.append(CGGeneric(fill(
-            """
-            if (!JS_DefineProperty(aCx, ${obj}, "toJSON", JS::UndefinedHandleValue,
-                                   JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
-              $*{cleanup}
-              return false;
-            }
-            """,
-            obj=obj,
-            cleanup=cleanup)))
-
-    return CGWrapper(CGList(unforgeables), pre="\n").define()
+        cleanup=cleanup)))
+
+    return CGWrapper(CGList(copyCode), pre="\n").define()
 
 
 def AssertInheritanceChain(descriptor):
     asserts = ""
     iface = descriptor.interface
     while iface:
         desc = descriptor.getDescriptor(iface.identifier.name)
         asserts += (
@@ -3169,26 +3253,16 @@ class CGWrapWithCacheMethod(CGAbstractMe
         args = [Argument('JSContext*', 'aCx'),
                 Argument(descriptor.nativeType + '*', 'aObject'),
                 Argument('nsWrapperCache*', 'aCache'),
                 Argument('JS::MutableHandle<JSObject*>', 'aReflector')]
         CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'bool', args)
         self.properties = properties
 
     def definition_body(self):
-        # For proxies, we have to SetWrapper() before we init unforgeables.  But
-        # for non-proxies we'd rather do it the other way around, so our
-        # unforgeables don't force preservation of the wrapper.
-        setWrapper = "aCache->SetWrapper(aReflector);\n"
-        if self.descriptor.proxy:
-            setWrapperProxy = setWrapper
-            setWrapperNonProxy = ""
-        else:
-            setWrapperProxy = ""
-            setWrapperNonProxy = setWrapper
         return fill(
             """
             $*{assertion}
 
             MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
                        "nsISupports must be on our primary inheritance chain");
 
             JS::Rooted<JSObject*> parent(aCx, WrapNativeParent(aCx, aObject->GetParentObject()));
@@ -3207,28 +3281,25 @@ class CGWrapWithCacheMethod(CGAbstractMe
             JS::Rooted<JSObject*> global(aCx, js::GetGlobalForObjectCrossCompartment(parent));
             JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, global);
             if (!proto) {
               return false;
             }
 
             $*{createObject}
 
-            $*{setWrapperProxy}
+            aCache->SetWrapper(aReflector);
             $*{unforgeable}
-            $*{setWrapperNonProxy}
             $*{slots}
             creator.InitializationSucceeded();
             return true;
             """,
             assertion=AssertInheritanceChain(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
-            setWrapperProxy=setWrapperProxy,
-            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties, True),
-            setWrapperNonProxy=setWrapperNonProxy,
+            unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor, True),
             slots=InitMemberSlots(self.descriptor, True))
 
 
 class CGWrapMethod(CGAbstractMethod):
     def __init__(self, descriptor):
         # XXX can we wrap if we don't have an interface prototype object?
         assert descriptor.interface.hasInterfacePrototypeObject()
         args = [Argument('JSContext*', 'aCx'),
@@ -3275,17 +3346,17 @@ class CGWrapNonWrapperCacheMethod(CGAbst
             $*{unforgeable}
 
             $*{slots}
             creator.InitializationSucceeded();
             return true;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
-            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties, False),
+            unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor, False),
             slots=InitMemberSlots(self.descriptor, False))
 
 
 class CGWrapGlobalMethod(CGAbstractMethod):
     """
     Create a wrapper JSObject for a global.  The global must implement
     nsWrapperCache.
 
@@ -3316,33 +3387,44 @@ class CGWrapGlobalMethod(CGAbstractMetho
 
         if self.descriptor.workers:
             fireOnNewGlobal = """// XXXkhuey can't do this yet until workers can lazy resolve.
 // JS_FireOnNewGlobalObject(aCx, aReflector);
 """
         else:
             fireOnNewGlobal = ""
 
+        if self.descriptor.hasUnforgeableMembers:
+            declareProto = "JS::Handle<JSObject*> proto =\n"
+            assertProto = (
+                "MOZ_ASSERT(proto &&\n"
+                "           IsDOMIfaceAndProtoClass(js::GetObjectClass(proto)));\n")
+        else:
+            declareProto = ""
+            assertProto = ""
+
         return fill(
             """
             $*{assertions}
             MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
                        "nsISupports must be on our primary inheritance chain");
 
-            CreateGlobal<${nativeType}, GetProtoObjectHandle>(aCx,
+            $*{declareProto}
+              CreateGlobal<${nativeType}, GetProtoObjectHandle>(aCx,
                                              aObject,
                                              aCache,
                                              Class.ToJSClass(),
                                              aOptions,
                                              aPrincipal,
                                              aInitStandardClasses,
                                              aReflector);
             if (!aReflector) {
               return false;
             }
+            $*{assertProto}
 
             // aReflector is a new global, so has a new compartment.  Enter it
             // before doing anything with it.
             JSAutoCompartment ac(aCx, aReflector);
 
             if (!DefineProperties(aCx, aReflector, ${properties}, ${chromeProperties})) {
               return false;
             }
@@ -3350,19 +3432,21 @@ class CGWrapGlobalMethod(CGAbstractMetho
 
             $*{slots}
             $*{fireOnNewGlobal}
 
             return true;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
             nativeType=self.descriptor.nativeType,
+            declareProto=declareProto,
+            assertProto=assertProto,
             properties=properties,
             chromeProperties=chromeProperties,
-            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties, True),
+            unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor, True),
             slots=InitMemberSlots(self.descriptor, True),
             fireOnNewGlobal=fireOnNewGlobal)
 
 
 class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'aCx'),
                 Argument('JS::Handle<JSObject*>', 'aWrapper'),
@@ -10173,17 +10257,17 @@ class CGDOMJSProxyHandler_defineProperty
                 if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
                   return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, "${name}");
                 }
                 """,
                 name=self.descriptor.name)
 
         namedSetter = self.descriptor.operations['NamedSetter']
         if namedSetter:
-            if HasUnforgeableMembers(self.descriptor):
+            if self.descriptor.hasUnforgeableMembers:
                 raise TypeError("Can't handle a named setter on an interface "
                                 "that has unforgeables.  Figure out how that "
                                 "should work!")
             if self.descriptor.operations['NamedCreator'] is not namedSetter:
                 raise TypeError("Can't handle creator that's different from the setter")
             # If we support indexed properties, we won't get down here for
             # indices, so we can just do our setter unconditionally here.
             set += fill(
@@ -10230,17 +10314,17 @@ class CGDOMJSProxyHandler_delete(ClassMe
     def getBody(self):
         def getDeleterBody(type, foundVar=None):
             """
             type should be "Named" or "Indexed"
             """
             assert type in ("Named", "Indexed")
             deleter = self.descriptor.operations[type + 'Deleter']
             if deleter:
-                if HasUnforgeableMembers(self.descriptor):
+                if self.descriptor.hasUnforgeableMembers:
                     raise TypeError("Can't handle a deleter on an interface "
                                     "that has unforgeables.  Figure out how "
                                     "that should work!")
                 decls = ""
                 if (not deleter.signatures()[0][0].isPrimitive() or
                     deleter.signatures()[0][0].nullable() or
                     deleter.signatures()[0][0].tag() != IDLType.Tags.bool):
                     setBp = "*bp = true;\n"
@@ -10586,17 +10670,17 @@ class CGDOMJSProxyHandler_setCustom(Clas
             self.descriptor.interface.getExtendedAttribute('OverrideBuiltins')):
             # Check assumptions.
             if self.descriptor.supportsIndexedProperties():
                 raise ValueError("In interface " + self.descriptor.name + ": " +
                                  "Can't cope with [OverrideBuiltins] and an indexed getter")
             if self.descriptor.operations['NamedCreator'] is not namedSetter:
                 raise ValueError("In interface " + self.descriptor.name + ": " +
                                  "Can't cope with named setter that is not also a named creator")
-            if HasUnforgeableMembers(self.descriptor):
+            if self.descriptor.hasUnforgeableMembers:
                 raise ValueError("In interface " + self.descriptor.name + ": " +
                                  "Can't cope with [OverrideBuiltins] and unforgeable members")
 
             callSetter = CGProxyNamedSetter(self.descriptor, argumentMutableValue="vp")
             return (assertion +
                     callSetter.define() +
                     "*done = true;\n"
                     "return true;\n")
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -289,16 +289,28 @@ def methodReturnsJSObject(method):
 
     for signature in method.signatures():
         returnType = signature[0]
         if returnType.isObject() or returnType.isSpiderMonkeyInterface():
             return True
 
     return False
 
+
+def MemberIsUnforgeable(member, descriptor):
+    # Note: "or" and "and" return either their LHS or RHS, not
+    # necessarily booleans.  Make sure to return a boolean from this
+    # method, because callers will compare its return value to
+    # booleans.
+    return bool((member.isAttr() or member.isMethod()) and
+                not member.isStatic() and
+                (member.isUnforgeable() or
+                 descriptor.interface.getExtendedAttribute("Unforgeable")))
+
+
 class Descriptor(DescriptorProvider):
     """
     Represents a single descriptor for an interface. See Bindings.conf.
     """
     def __init__(self, config, interface, desc):
         DescriptorProvider.__init__(self, config, desc.get('workers', False))
         self.interface = interface
 
@@ -365,16 +377,19 @@ class Descriptor(DescriptorProvider):
 
         self.hasXPConnectImpls = desc.get('hasXPConnectImpls', False)
 
         # If we're concrete, we need to crawl our ancestor interfaces and mark
         # them as having a concrete descendant.
         self.concrete = (not self.interface.isExternal() and
                          not self.interface.isCallback() and
                          desc.get('concrete', True))
+        self.hasUnforgeableMembers = (self.concrete and
+                                      any(MemberIsUnforgeable(m, self) for m in
+                                          self.interface.members))
         self.operations = {
             'IndexedGetter': None,
             'IndexedSetter': None,
             'IndexedCreator': None,
             'IndexedDeleter': None,
             'NamedGetter': None,
             'NamedSetter': None,
             'NamedCreator': None,
--- a/dom/bindings/JSSlots.h
+++ b/dom/bindings/JSSlots.h
@@ -21,12 +21,13 @@
 // Specific objects may have more for storing cached values.
 #define DOM_INSTANCE_RESERVED_SLOTS 1
 
 // Interface objects store a number of reserved slots equal to
 // DOM_INTERFACE_SLOTS_BASE + number of named constructors.
 #define DOM_INTERFACE_SLOTS_BASE 0
 
 // Interface prototype objects store a number of reserved slots equal to
-// DOM_INTERFACE_PROTO_SLOTS_BASE.
+// DOM_INTERFACE_PROTO_SLOTS_BASE or DOM_INTERFACE_PROTO_SLOTS_BASE + 1 if a
+// slot for the unforgeable holder is needed.
 #define DOM_INTERFACE_PROTO_SLOTS_BASE 0
 
 #endif /* mozilla_dom_DOMSlots_h */
--- a/dom/bindings/test/chrome.ini
+++ b/dom/bindings/test/chrome.ini
@@ -6,8 +6,10 @@
 [test_dom_xrays.html]
 [test_proxies_via_xray.html]
 [test_document_location_via_xray_cached.html]
 [test_blacklisted_prerendering_function.xul]
 support-files =
   file_focuser.html
   file_fullScreenPropertyAccessor.html
 skip-if = e10s # prerendering doesn't work in e10s yet
+[test_kill_longrunning_prerendered_content.xul]
+skip-if = e10s # prerendering doesn't work in e10s yet
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_kill_longrunning_prerendered_content.xul
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        xmlns:html="http://www.w3.org/1999/xhtml"
+        onload="runTest();">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+  SimpleTest.waitForExplicitFinish();
+
+  function Listener(aBrowser, aPrerendered, aCallback) {
+    this.init(aBrowser, aPrerendered, aCallback);
+  }
+
+  Listener.prototype = {
+    init: function(aBrowser, aCallback) {
+      this.mBrowser = aBrowser;
+      this.mCallback = aCallback;
+    },
+    QueryInterface: function(aIID) {
+      if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
+          aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
+          aIID.equals(Components.interfaces.nsISupports))
+        return this;
+      throw Components.results.NS_NOINTERFACE;
+    },
+    onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) {
+      if ((aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) &&
+          (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT)) {
+        setTimeout(this.mCallback, 0);
+      }
+    },
+    onProgressChange : function(aWebProgress, aRequest,
+                                aCurSelfProgress, aMaxSelfProgress,
+                                aCurTotalProgress, aMaxTotalProgress) {},
+    onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) {},
+    onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
+    onSecurityChange : function(aWebProgress, aRequest, aState) {},
+    mBrowser: null,
+    mPrerendered: false,
+    mCallback: null
+  };
+
+  var progress, progressListener;
+
+  function runTest() {
+    SpecialPowers.pushPrefEnv({
+      "set": [
+        ["dom.max_script_run_time", 1]
+      ]
+    }, function() {
+      test(function() {
+        ok("The page is successfully interrupted.");
+        SimpleTest.finish();
+      });
+    });
+  }
+
+  function test(aCallback) {
+    var browser = document.getElementById("prerendered");;
+    progressListener = new Listener(browser, aCallback);
+    var docShell = browser.docShell;
+    progress = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                       .getInterface(Components.interfaces.nsIWebProgress);
+    progress.addProgressListener(progressListener,
+                                 Components.interfaces.nsIWebProgress.NOTIFY_ALL);
+    browser.loadURI("data:text/html,<script>;for(;;);</script" + ">");
+  }
+
+]]>
+</script>
+
+<body  id="html_body" xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1050456">Mozilla Bug 1050456</a>
+<p id="display"></p>
+
+<pre id="test">
+</pre>
+</body>
+<browser prerendered="true" id="prerendered"/>
+</window>
--- a/dom/contacts/tests/test_contacts_cache.xul
+++ b/dom/contacts/tests/test_contacts_cache.xul
@@ -12,17 +12,16 @@
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
   <script type="application/javascript;version=1.7">
   <![CDATA[
   "use strict";
 
   const { 'utils': Cu } = Components;
   Cu.import("resource://gre/modules/ContactDB.jsm", window);
-  Cu.importGlobalProperties(["indexedDB"]);
 
   let contactsDB = new ContactDB();
   contactsDB.init();
 
   function makeFailure(reason, skipDelete) {
     return function() {
       ok(false, reason);
       if (skipDelete) {
--- a/dom/contacts/tests/test_contacts_upgrade.xul
+++ b/dom/contacts/tests/test_contacts_upgrade.xul
@@ -137,17 +137,16 @@
     return function() {
       ok(false, reason);
       SimpleTest.finish();
     };
   };
 
   const { 'utils': Cu } = Components;
   Cu.import("resource://gre/modules/ContactDB.jsm", window);
-  Cu.importGlobalProperties(["indexedDB"]);
 
   let cdb = new ContactDB();
   cdb.init();
 
   let CONTACT_PROPS = {
     id: "ab74671e36be41b680f8f030e7e24ea2",
     properties: {
       name: ["Magnificentest foo bar the third"],
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -7214,17 +7214,17 @@ HTMLInputElement::GetCols()
   }
 
   return DEFAULT_COLS;
 }
 
 NS_IMETHODIMP_(int32_t)
 HTMLInputElement::GetWrapCols()
 {
-  return -1; // only textarea's can have wrap cols
+  return 0; // only textarea's can have wrap cols
 }
 
 NS_IMETHODIMP_(int32_t)
 HTMLInputElement::GetRows()
 {
   return DEFAULT_ROWS;
 }
 
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -1475,17 +1475,17 @@ HTMLTextAreaElement::GetCols()
 NS_IMETHODIMP_(int32_t)
 HTMLTextAreaElement::GetWrapCols()
 {
   // wrap=off means -1 for wrap width no matter what cols is
   nsHTMLTextWrap wrapProp;
   nsITextControlElement::GetWrapPropertyEnum(this, wrapProp);
   if (wrapProp == nsITextControlElement::eHTMLTextWrap_Off) {
     // do not wrap when wrap=off
-    return -1;
+    return 0;
   }
 
   // Otherwise we just wrap at the given number of columns
   return GetCols();
 }
 
 
 NS_IMETHODIMP_(int32_t)
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -1708,17 +1708,17 @@ nsTextEditorState::InitializeRootNode()
   mRootNode->SetFlags(NODE_IS_EDITABLE);
 
   // Set the necessary classes on the text control. We use class values
   // instead of a 'style' attribute so that the style comes from a user-agent
   // style sheet and is still applied even if author styles are disabled.
   nsAutoString classValue;
   classValue.AppendLiteral("anonymous-div");
   int32_t wrapCols = GetWrapCols();
-  if (wrapCols >= 0) {
+  if (wrapCols > 0) {
     classValue.AppendLiteral(" wrap");
   }
   if (!IsSingleLineTextControl()) {
     // We can't just inherit the overflow because setting visible overflow will
     // crash when the number of lines exceeds the height of the textarea and
     // setting -moz-hidden-unscrollable overflow (NS_STYLE_OVERFLOW_CLIP)
     // doesn't paint the caret for some reason.
     const nsStyleDisplay* disp = mBoundFrame->StyleDisplay();
--- a/dom/indexedDB/test/chromeHelpers.js
+++ b/dom/indexedDB/test/chromeHelpers.js
@@ -5,18 +5,16 @@
 
 const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu } = Components;
 
 let testGenerator = testSteps();
 
 if (!window.runTest) {
   window.runTest = function()
   {
-    Cu.importGlobalProperties(["indexedDB"]);
-
     SimpleTest.waitForExplicitFinish();
 
     testGenerator.next();
   }
 }
 
 function finishTest()
 {
--- a/dom/media/eme/CDMCaps.cpp
+++ b/dom/media/eme/CDMCaps.cpp
@@ -76,17 +76,21 @@ CDMCaps::AutoLock::CallOnMainThreadWhenC
 }
 
 bool
 CDMCaps::AutoLock::IsKeyUsable(const CencKeyId& aKeyId)
 {
   mData.mMonitor.AssertCurrentThreadOwns();
   const auto& keys = mData.mKeyStatuses;
   for (size_t i = 0; i < keys.Length(); i++) {
-    if (keys[i].mId == aKeyId && keys[i].mStatus == kGMPUsable) {
+    if (keys[i].mId != aKeyId) {
+      continue;
+    }
+    if (keys[i].mStatus == kGMPUsable ||
+        keys[i].mStatus == kGMPOutputDownscaled) {
       return true;
     }
   }
   return false;
 }
 
 bool
 CDMCaps::AutoLock::SetKeyStatus(const CencKeyId& aKeyId,
@@ -101,22 +105,30 @@ CDMCaps::AutoLock::SetKeyStatus(const Ce
     // Return true if the element is found to notify key changes.
     return mData.mKeyStatuses.RemoveElement(key);
   }
 
   if (index != mData.mKeyStatuses.NoIndex) {
     if (mData.mKeyStatuses[index].mStatus == aStatus) {
       return false;
     }
+    auto oldStatus = mData.mKeyStatuses[index].mStatus;
     mData.mKeyStatuses[index].mStatus = aStatus;
+    if (oldStatus == kGMPUsable || oldStatus == kGMPOutputDownscaled) {
+      return true;
+    }
   } else {
     mData.mKeyStatuses.AppendElement(key);
   }
 
-  if (aStatus != kGMPUsable) {
+  // Both kGMPUsable and kGMPOutputDownscaled are treated able to decrypt.
+  // We don't need to notify when transition happens between kGMPUsable and
+  // kGMPOutputDownscaled. Only call NotifyUsable() when we are going from
+  // ![kGMPUsable|kGMPOutputDownscaled] to [kGMPUsable|kGMPOutputDownscaled]
+  if (aStatus != kGMPUsable && aStatus != kGMPOutputDownscaled) {
     return true;
   }
 
   auto& waiters = mData.mWaitForKeys;
   size_t i = 0;
   while (i < waiters.Length()) {
     auto& w = waiters[i];
     if (w.mKeyId == aKeyId) {
--- a/dom/media/gmp/GMPDecryptorChild.cpp
+++ b/dom/media/gmp/GMPDecryptorChild.cpp
@@ -8,25 +8,17 @@
 #include "mozilla/TimeStamp.h"
 #include "mozilla/unused.h"
 #include "runnable_utils.h"
 #include <ctime>
 
 #define ON_GMP_THREAD() (mPlugin->GMPMessageLoop() == MessageLoop::current())
 
 #define CALL_ON_GMP_THREAD(_func, ...) \
-  do { \
-    if (ON_GMP_THREAD()) { \
-      _func(__VA_ARGS__); \
-    } else { \
-      mPlugin->GMPMessageLoop()->PostTask( \
-        FROM_HERE, NewRunnableMethod(this, &GMPDecryptorChild::_func, __VA_ARGS__) \
-      ); \
-    } \
-  } while(false)
+  CallOnGMPThread(&GMPDecryptorChild::_func, __VA_ARGS__)
 
 namespace mozilla {
 namespace gmp {
 
 GMPDecryptorChild::GMPDecryptorChild(GMPChild* aPlugin,
                                      const nsTArray<uint8_t>& aPluginVoucher,
                                      const nsTArray<uint8_t>& aSandboxVoucher)
   : mSession(nullptr)
@@ -36,16 +28,48 @@ GMPDecryptorChild::GMPDecryptorChild(GMP
 {
   MOZ_ASSERT(mPlugin);
 }
 
 GMPDecryptorChild::~GMPDecryptorChild()
 {
 }
 
+template <typename MethodType, typename... ParamType>
+void
+GMPDecryptorChild::CallMethod(MethodType aMethod, ParamType&&... aParams)
+{
+  MOZ_ASSERT(ON_GMP_THREAD());
+  // Don't send IPC messages after tear-down.
+  if (mSession) {
+    (this->*aMethod)(Forward<ParamType>(aParams)...);
+  }
+}
+
+template<typename T>
+struct AddConstReference {
+  typedef const typename RemoveReference<T>::Type& Type;
+};
+
+template<typename MethodType, typename... ParamType>
+void
+GMPDecryptorChild::CallOnGMPThread(MethodType aMethod, ParamType&&... aParams)
+{
+  if (ON_GMP_THREAD()) {
+    // Use forwarding reference when we can.
+    CallMethod(aMethod, Forward<ParamType>(aParams)...);
+  } else {
+    // Use const reference when we have to.
+    auto m = &GMPDecryptorChild::CallMethod<
+        decltype(aMethod), typename AddConstReference<ParamType>::Type...>;
+    auto t = NewRunnableMethod(this, m, aMethod, aParams...);
+    mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t);
+  }
+}
+
 void
 GMPDecryptorChild::Init(GMPDecryptor* aSession)
 {
   MOZ_ASSERT(aSession);
   mSession = aSession;
 }
 
 void
@@ -140,27 +164,30 @@ GMPDecryptorChild::KeyStatusChanged(cons
 }
 
 void
 GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
 {
   if (!ON_GMP_THREAD()) {
     // We should run this whole method on the GMP thread since the buffer needs
     // to be deleted after the SendDecrypted call.
-    CALL_ON_GMP_THREAD(Decrypted, aBuffer, aResult);
+    auto t = NewRunnableMethod(this, &GMPDecryptorChild::Decrypted, aBuffer, aResult);
+    mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t);
     return;
   }
 
   if (!aBuffer) {
     NS_WARNING("GMPDecryptorCallback passed bull GMPBuffer");
     return;
   }
 
   auto buffer = static_cast<GMPBufferImpl*>(aBuffer);
-  SendDecrypted(buffer->mId, aResult, buffer->mData);
+  if (mSession) {
+    SendDecrypted(buffer->mId, aResult, buffer->mData);
+  }
   delete buffer;
 }
 
 void
 GMPDecryptorChild::SetCapabilities(uint64_t aCaps)
 {
   CALL_ON_GMP_THREAD(SendSetCaps, aCaps);
 }
@@ -316,22 +343,26 @@ GMPDecryptorChild::RecvDecrypt(const uin
 
   mSession->Decrypt(buffer, metadata);
   return true;
 }
 
 bool
 GMPDecryptorChild::RecvDecryptingComplete()
 {
-  if (!mSession) {
+  // Reset |mSession| before calling DecryptingComplete(). We should not send
+  // any IPC messages during tear-down.
+  auto session = mSession;
+  mSession = nullptr;
+
+  if (!session) {
     return false;
   }
 
-  mSession->DecryptingComplete();
-  mSession = nullptr;
+  session->DecryptingComplete();
 
   unused << Send__delete__(this);
 
   return true;
 }
 
 } // namespace gmp
 } // namespace mozilla
--- a/dom/media/gmp/GMPDecryptorChild.h
+++ b/dom/media/gmp/GMPDecryptorChild.h
@@ -109,16 +109,22 @@ private:
                            const GMPDecryptionData& aMetadata) MOZ_OVERRIDE;
 
   // Resolve/reject promise on completion.
   virtual bool RecvSetServerCertificate(const uint32_t& aPromiseId,
                                         InfallibleTArray<uint8_t>&& aServerCert) MOZ_OVERRIDE;
 
   virtual bool RecvDecryptingComplete() MOZ_OVERRIDE;
 
+  template <typename MethodType, typename... ParamType>
+  void CallMethod(MethodType, ParamType&&...);
+
+  template<typename MethodType, typename... ParamType>
+  void CallOnGMPThread(MethodType, ParamType&&...);
+
   // GMP's GMPDecryptor implementation.
   // Only call into this on the (GMP process) main thread.
   GMPDecryptor* mSession;
   GMPChild* mPlugin;
 
   // Reference to the vouchers owned by the GMPChild.
   const nsTArray<uint8_t>& mPluginVoucher;
   const nsTArray<uint8_t>& mSandboxVoucher;
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -998,18 +998,18 @@ TrackBuffer::RangeRemoval(media::Microse
 
   if (aStart <= bufferedStart && aEnd < bufferedEnd) {
     // Evict data from beginning.
     for (size_t i = 0; i < decoders.Length(); ++i) {
       nsRefPtr<dom::TimeRanges> buffered = new dom::TimeRanges();
       decoders[i]->GetBuffered(buffered);
       if (media::Microseconds::FromSeconds(buffered->GetEndTime()) < aEnd) {
         // Can be fully removed.
-        MSE_DEBUG("remove all bufferedEnd=%f time=%f, size=%lld",
-                  buffered->GetEndTime(), time,
+        MSE_DEBUG("remove all bufferedEnd=%f size=%lld",
+                  buffered->GetEndTime(),
                   decoders[i]->GetResource()->GetSize());
         decoders[i]->GetResource()->EvictAll();
       } else {
         int64_t offset = decoders[i]->ConvertToByteOffset(aEnd.ToSeconds());
         MSE_DEBUG("removing some bufferedEnd=%f offset=%lld size=%lld",
                   buffered->GetEndTime(), offset,
                   decoders[i]->GetResource()->GetSize());
         if (offset > 0) {
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -1,13 +1,14 @@
 #!/usr/bin/env python
 
 import os
 
 import locale
+from collections import defaultdict
 locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
 
 header = """
 #
 #   #####   #######           #     #     #     #     #     #
 # ##     #  #     #          # #    #  #  #    # #     #   #
 # ##        #     #         #   #   #  #  #   #   #     # #
 # ##  ####  #     #        #     #  #  #  #  #     #     #
@@ -187,17 +188,17 @@ def generate_platform_sources():
 
   for plat in platforms:
     if os.system("cd trunk && GYP_GENERATORS=dump_mozbuild ./gyp_skia -D OS=%s gyp/skia_lib.gyp" % plat) != 0:
       print 'Failed to generate sources for ' + plat
       continue
 
 
     f = open('trunk/sources.json');
-    sources[plat] = set(json.load(f));
+    sources[plat] = set(v.replace('../', 'trunk/') for v in json.load(f));
     f.close()
 
   return dict(sources.items() + generate_opt_sources().items())
 
 
 def generate_separated_sources(platform_sources):
   blacklist = [
     'ChromeUtils',
@@ -232,17 +233,17 @@ def generate_separated_sources(platform_
 
   def isblacklisted(value):
     for item in blacklist:
       if value.find(item) >= 0:
         return True
 
     return False
 
-  separated = {
+  separated = defaultdict(set, {
     'common': {
       #'trunk/src/effects/gradients/SkGradientTileProc.cpp',
       'trunk/src/gpu/gl/GrGLCreateNativeInterface_none.cpp',
       'trunk/src/ports/SkDiscardableMemory_none.cpp',
       'trunk/src/ports/SkImageDecoder_empty.cpp',
       'trunk/src/ports/SkMemory_mozalloc.cpp',
       # 'trunk/src/images/SkImages.cpp',
       # 'trunk/src/images/SkImageRef.cpp',
@@ -277,69 +278,55 @@ def generate_separated_sources(platform_
       'trunk/src/core/SkUtilsArm.cpp',
     },
     'neon': {
       'trunk/src/opts/SkBitmapProcState_arm_neon.cpp',
     },
     'none': {
       'trunk/src/opts/SkUtils_opts_none.cpp',
     }
-  }
+  })
 
   for plat in platform_sources.keys():
-    if not separated.has_key(plat):
-      separated[plat] = set()
-
     for value in platform_sources[plat]:
       if isblacklisted(value):
         continue
 
-      if value.find('_SSE') > 0 or value.find('_SSSE') > 0 or value.find('_SSE4') > 0 : #lol
-        separated['intel'].add(value)
-        continue
-
-      if value.find('_neon') > 0:
-        separated['neon'].add(value)
-        continue
-
-      if value.find('_arm') > 0:
-        separated['arm'].add(value)
+      if value in separated['common']:
         continue
 
-      if value.find('_none') > 0:
-        separated['none'].add(value)
-        continue
-
-      found = True
-      for other in platforms:
-        if other == plat or not platform_sources.has_key(other):
-          continue
+      key = plat
 
-        if not value in platform_sources[other]:
-          found = False
-          break;
+      if '_SSE' in value or '_SSSE' in value:
+        key = 'intel'
+      elif '_neon' in value:
+        key = 'neon'
+      elif '_arm' in value:
+        key = 'arm'
+      elif '_none' in value:
+        key = 'none'
+      elif all(value in platform_sources.get(p, {})
+               for p in platforms if p != plat):
+        key = 'common'
 
-      if found:
-        separated['common'].add(value)
-      else:
-        separated[plat].add(value)
+      separated[key].add(value)
 
   return separated
 
 def uniq(seq):
   seen = set()
   seen_add = seen.add
   return [ x for x in seq if x not in seen and not seen_add(x)]
 
 def write_cflags(f, values, subsearch, cflag, indent):
   def write_indent(indent):
     for _ in range(indent):
         f.write(' ')
 
-  val_list = uniq(sorted(map(lambda val: val.replace('../', 'trunk/'), values), key=lambda x: x.lower()))
+  val_list = uniq(sorted(values, key=lambda x: x.lower()))
 
   if len(val_list) == 0:
     return
 
   for val in val_list:
     if val.find(subsearch) > 0:
       write_indent(indent)
       f.write("SOURCES[\'" + val + "\'].flags += [\'" + cflag + "\']\n")
@@ -391,17 +378,17 @@ def write_sources(f, values, indent):
   write_list(f, "UNIFIED_SOURCES", sources['unified'], indent)
   write_list(f, "SOURCES", sources['nonunified'], indent)
   
 def write_list(f, name, values, indent):
   def write_indent(indent):
     for _ in range(indent):
         f.write(' ')
 
-  val_list = uniq(sorted(map(lambda val: val.replace('../', 'trunk/'), values), key=lambda x: x.lower()))
+  val_list = uniq(sorted(values, key=lambda x: x.lower()))
 
   if len(val_list) == 0:
     return
 
   write_indent(indent)
   f.write(name + ' += [\n')
   for val in val_list:
     write_indent(indent + 4)
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -847,17 +847,16 @@ else:
         'trunk/src/opts/SkBitmapProcState_opts_none.cpp',
         'trunk/src/opts/SkBlitMask_opts_none.cpp',
         'trunk/src/opts/SkBlitRow_opts_none.cpp',
         'trunk/src/opts/SkBlurImage_opts_none.cpp',
         'trunk/src/opts/SkMorphology_opts_none.cpp',
         'trunk/src/opts/SkTextureCompression_opts_none.cpp',
         'trunk/src/opts/SkUtils_opts_none.cpp',
         'trunk/src/opts/SkXfermode_opts_none.cpp',
-        'trunk/src/ports/SkDiscardableMemory_none.cpp',
     ]
 
 
 # can we find a better way of dealing with asm sources?
 
 # left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with
 if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:
     SOURCES += [
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -190,41 +190,16 @@ SandboxImport(JSContext *cx, unsigned ar
     if (!JS_SetPropertyById(cx, thisObject, id, args[0]))
         return false;
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
-SandboxCreateXMLHttpRequest(JSContext *cx, unsigned argc, jsval *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
-    MOZ_ASSERT(global);
-
-    nsIScriptObjectPrincipal *sop =
-        static_cast<nsIScriptObjectPrincipal *>(xpc_GetJSPrivate(global));
-    nsCOMPtr<nsIGlobalObject> iglobal = do_QueryInterface(sop);
-
-    nsCOMPtr<nsIXMLHttpRequest> xhr = new nsXMLHttpRequest();
-    nsresult rv = xhr->Init(nsContentUtils::SubjectPrincipal(), nullptr,
-                            iglobal, nullptr, nullptr);
-    if (NS_FAILED(rv))
-        return false;
-
-    rv = nsContentUtils::WrapNative(cx, xhr, args.rval());
-    if (NS_FAILED(rv))
-        return false;
-
-    return true;
-}
-
-static bool
 SandboxCreateCrypto(JSContext *cx, JS::HandleObject obj)
 {
     MOZ_ASSERT(JS_IsGlobalObject(obj));
 
     nsIGlobalObject* native = xpc::NativeGlobal(obj);
     MOZ_ASSERT(native);
 
     dom::Crypto* crypto = new dom::Crypto();
@@ -838,17 +813,17 @@ xpc::GlobalProperties::Define(JSContext 
     if (CSS && !dom::CSSBinding::GetConstructorObject(cx, obj))
         return false;
 
     if (indexedDB && AccessCheck::isChrome(obj) &&
         !IndexedDatabaseManager::DefineIndexedDB(cx, obj))
         return false;
 
     if (XMLHttpRequest &&
-        !JS_DefineFunction(cx, obj, "XMLHttpRequest", SandboxCreateXMLHttpRequest, 0, JSFUN_CONSTRUCTOR))
+        !dom::XMLHttpRequestBinding::GetConstructorObject(cx, obj))
         return false;
 
     if (TextEncoder &&
         !dom::TextEncoderBinding::GetConstructorObject(cx, obj))
         return false;
 
     if (TextDecoder &&
         !dom::TextDecoderBinding::GetConstructorObject(cx, obj))
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -20,16 +20,17 @@
 #include "mozilla/Preferences.h"
 #include "nsJSEnvironment.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/StructuredCloneTags.h"
+#include "mozilla/dom/WindowBinding.h"
 #include "nsZipArchive.h"
 #include "nsIDOMFile.h"
 #include "nsIDOMFileList.h"
 #include "nsWindowMemoryReporter.h"
 #include "nsDOMClassInfo.h"
 #include "ShimInterfaceInfo.h"
 
 using namespace mozilla;
@@ -2714,16 +2715,23 @@ nsXPCComponents_Utils::Unload(const nsAC
  * JSObject importGlobalProperties (in jsval aPropertyList);
  */
 NS_IMETHODIMP
 nsXPCComponents_Utils::ImportGlobalProperties(HandleValue aPropertyList,
                                               JSContext* cx)
 {
     RootedObject global(cx, CurrentGlobalOrNull(cx));
     MOZ_ASSERT(global);
+
+    // Don't allow doing this if the global is a Window
+    nsGlobalWindow* win;
+    if (NS_SUCCEEDED(UNWRAP_OBJECT(Window, global, win))) {
+        return NS_ERROR_NOT_AVAILABLE;
+    }
+
     GlobalProperties options;
     NS_ENSURE_TRUE(aPropertyList.isObject(), NS_ERROR_INVALID_ARG);
     RootedObject propertyList(cx, &aPropertyList.toObject());
     NS_ENSURE_TRUE(JS_IsArrayObject(cx, propertyList), NS_ERROR_INVALID_ARG);
     if (!options.Parse(cx, propertyList) ||
         !options.Define(cx, global))
     {
         return NS_ERROR_FAILURE;
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -15,16 +15,17 @@
 #include "XPCJSMemoryReporter.h"
 #include "WrapperFactory.h"
 #include "mozJSComponentLoader.h"
 
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIDebug2.h"
+#include "nsIDocShell.h"
 #include "amIAddonManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Services.h"
 
 #include "nsContentUtils.h"
@@ -1447,16 +1448,23 @@ XPCJSRuntime::InterruptCallback(JSContex
             (proto = js::CheckedUnwrap(proto, /* stopAtOuter = */ false)))
         {
             win = WindowGlobalOrNull(proto);
         }
     }
     if (!win)
         return true;
 
+    if (win->GetIsPrerendered()) {
+        // We cannot display a dialog if the page is being prerendered, so
+        // just kill the page.
+        mozilla::dom::HandlePrerenderingViolation(win);
+        return false;
+    }
+
     // Show the prompt to the user, and kill if requested.
     nsGlobalWindow::SlowScriptResponse response = win->ShowSlowScriptDialog();
     if (response == nsGlobalWindow::KillSlowScript)
         return false;
 
     // The user chose to continue the script. Reset the timer, and disable this
     // machinery with a pref of the user opted out of future slow-script dialogs.
     if (response != nsGlobalWindow::ContinueSlowScriptAndKeepNotifying)
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -2010,31 +2010,33 @@ RestyleManager::DebugVerifyStyleTree(nsI
     VerifyStyleTree(mPresContext, aFrame, parentContext);
   }
 }
 
 #endif // DEBUG
 
 // aContent must be the content for the frame in question, which may be
 // :before/:after content
-/* static */ void
+/* static */ bool
 RestyleManager::TryStartingTransition(nsPresContext* aPresContext,
                                       nsIContent* aContent,
                                       nsStyleContext* aOldStyleContext,
                                       nsRefPtr<nsStyleContext>*
                                         aNewStyleContext /* inout */)
 {
   if (!aContent || !aContent->IsElement()) {
-    return;
+    return false;
   }
 
   // Notify the transition manager.  If it starts a transition,
   // it might modify the new style context.
+  nsRefPtr<nsStyleContext> sc = *aNewStyleContext;
   aPresContext->TransitionManager()->StyleContextChanged(
     aContent->AsElement(), aOldStyleContext, aNewStyleContext);
+  return *aNewStyleContext != sc;
 }
 
 static dom::Element*
 ElementForStyleContext(nsIContent* aParentContent,
                        nsIFrame* aFrame,
                        nsCSSPseudoElements::Type aPseudoType)
 {
   // We don't expect XUL tree stuff here.
@@ -3295,19 +3297,23 @@ ElementRestyler::RestyleSelf(nsIFrame* a
           // continue restyling children.
           LOG_RESTYLE_CONTINUE("there is different style data: %s",
                       RestyleManager::StructNamesToString(
                         ~equalStructs & NS_STYLE_INHERIT_MASK).get());
           result = eRestyleResult_Continue;
         }
       }
     } else {
-      RestyleManager::TryStartingTransition(mPresContext, aSelf->GetContent(),
-                                            oldContext, &newContext);
-
+      bool changedStyle =
+        RestyleManager::TryStartingTransition(mPresContext, aSelf->GetContent(),
+                                              oldContext, &newContext);
+      if (changedStyle) {
+        LOG_RESTYLE_CONTINUE("TryStartingTransition changed the new style context");
+        result = eRestyleResult_Continue;
+      }
       CaptureChange(oldContext, newContext, assumeDifferenceHint,
                     &equalStructs);
       if (equalStructs != NS_STYLE_INHERIT_MASK) {
         // At least one struct had different data in it, so we must
         // continue restyling children.
         LOG_RESTYLE_CONTINUE("there is different style data: %s",
                     RestyleManager::StructNamesToString(
                       ~equalStructs & NS_STYLE_INHERIT_MASK).get());
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -223,22 +223,23 @@ public:
    */
   ReframingStyleContexts* GetReframingStyleContexts() {
     return mReframingStyleContexts;
   }
 
   /**
    * Try starting a transition for an element or a ::before or ::after
    * pseudo-element, given an old and new style context.  This may
-   * change the new style context if a transition is started.
+   * change the new style context if a transition is started.  Returns
+   * true iff it does change aNewStyleContext.
    *
    * For the pseudo-elements, aContent must be the anonymous content
    * that we're creating for that pseudo-element, not the real element.
    */
-  static void
+  static bool
   TryStartingTransition(nsPresContext* aPresContext, nsIContent* aContent,
                         nsStyleContext* aOldStyleContext,
                         nsRefPtr<nsStyleContext>* aNewStyleContext /* inout */);
 
 private:
   void RestyleForEmptyChange(Element* aContainer);
 
 public:
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -1,14 +1,50 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('ActiveLayerTracker.*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('Display*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('FrameLayerBuilder.*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('LayerState.*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('MaskLayerImageCache.*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('PaintTracker.*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('nsCSSRendering.*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('nsDisplay*'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+with Files('Restyle*'):
+    BUG_COMPONENT = ('Core', 'CSS Parsing and Computation')
+
+with Files('nsStyle*'):
+    BUG_COMPONENT = ('Core', 'CSS Parsing and Computation')
+
+with Files('nsChangeHint.h'):
+    BUG_COMPONENT = ('Core', 'CSS Parsing and Computation')
+
+with Files('nsBidi*'):
+    BUG_COMPONENT = ('Core', 'Layout: Text')
+
 XPIDL_SOURCES += [
     'nsIStyleSheetService.idl',
 ]
 
 if CONFIG['MOZ_DEBUG']:
     UNIFIED_SOURCES += [
         'nsAutoLayoutPhase.cpp',
     ]
--- a/layout/forms/moz.build
+++ b/layout/forms/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Layout: Form Controls')
+
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 EXPORTS += [
     'nsIComboboxControlFrame.h',
     'nsIFormControlFrame.h',
     'nsIListControlFrame.h',
     'nsISelectControlFrame.h',
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -1,14 +1,70 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('nsBlock*'):
+    # Parts of these files are really Layout: Floats
+    BUG_COMPONENT = ('Core', 'Layout: Block and Inline')
+
+with Files('nsLine*'):
+    # Parts of these files are really Layout: Floats
+    BUG_COMPONENT = ('Core', 'Layout: Block and Inline')
+
+with Files('nsInlineFrame.*'):
+    BUG_COMPONENT = ('Core', 'Layout: Block and Inline')
+
+with Files('nsBRFrame.*'):
+    BUG_COMPONENT = ('Core', 'Layout: Block and Inline')
+
+with Files('nsBulletFrame.*'):
+    BUG_COMPONENT = ('Core', 'Layout: Block and Inline')
+
+with Files('nsFirstLetterFrame.*'):
+    BUG_COMPONENT = ('Core', 'Layout: Block and Inline')
+
+with Files('MathML*'):
+    BUG_COMPONENT = ('Core', 'MathML')
+
+with Files('Text*'):
+    BUG_COMPONENT = ('Core', 'Layout: Text')
+
+with Files('nsText*'):
+    BUG_COMPONENT = ('Core', 'Layout: Text')
+
+with Files('nsFrameSetFrame*'):
+    BUG_COMPONENT = ('Core', 'Layout: HTML Frames')
+
+with Files('nsSubDocumentFrame*'):
+    BUG_COMPONENT = ('Core', 'Layout: HTML Frames')
+
+with Files('nsFloatManager.*'):
+    BUG_COMPONENT = ('Core', 'Layout: Floats')
+
+with Files('nsIntervalSet.*'):
+    BUG_COMPONENT = ('Core', 'Layout: Floats')
+
+with Files('nsHTMLCanvasFrame.*'):
+    BUG_COMPONENT = ('Core', 'Layout: Images')
+
+with Files('nsImage*'):
+    BUG_COMPONENT = ('Core', 'Layout: Images')
+
+with Files('nsAbsoluteContainingBlock.*'):
+    BUG_COMPONENT = ('Core', 'Layout: R & A Pos')
+
+with Files('nsPluginFrame.*'):
+    BUG_COMPONENT = ('Core', 'Plug-ins')
+
+with Files('nsVideoFrame.*'):
+    BUG_COMPONENT = ('Core', 'Video/Audio')
+
 EXPORTS += [
     'nsCanvasFrame.h',
     'nsContainerFrame.h',
     'nsDirection.h',
     'nsFrame.h',
     'nsFrameIdList.h',
     'nsFrameList.h',
     'nsFrameSelection.h',
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -3013,27 +3013,16 @@ ScrollFrameHelper::BuildDisplayList(nsDi
       // If we are using containers for root frames, and we are the root
       // scroll frame for the display root, then we don't need a scroll
       // info layer. nsDisplayList::PaintForFrame already calls
       // ComputeFrameMetrics for us.
       (!(gfxPrefs::LayoutUseContainersForRootFrames() && mIsRoot) ||
        (aBuilder->RootReferenceFrame()->PresContext() != mOuter->PresContext()));
   }
 
-  if (aBuilder->IsPaintingToWindow() &&
-      !mShouldBuildScrollableLayer &&
-      shouldBuildLayer)
-  {
-    if (nsDisplayLayerEventRegions *eventRegions = aBuilder->GetLayerEventRegions()) {
-      // Make sure that APZ will dispatch events back to content so we can
-      // create a displayport for this frame.
-      eventRegions->AddInactiveScrollPort(mScrollPort + aBuilder->ToReferenceFrame(mOuter));
-    }
-  }
-
   mScrollParentID = aBuilder->GetCurrentScrollParentId();
 
   nsDisplayListCollection scrolledContent;
   {
     // Note that setting the current scroll parent id here means that positioned children
     // of this scroll info layer will pick up the scroll info layer as their scroll handoff
     // parent. This is intentional because that is what happens for positioned children
     // of scroll layers, and we want to maintain consistent behaviour between scroll layers
@@ -3133,41 +3122,59 @@ ScrollFrameHelper::BuildDisplayList(nsDi
       }
 
       // Once a displayport is set, assume that scrolling needs to be fast
       // so create a layer with all the content inside. The compositor
       // process will be able to scroll the content asynchronously.
       wrapper.WrapListsInPlace(aBuilder, mOuter, scrolledContent);
     }
 
+    // Make sure that APZ will dispatch events back to content so we can create
+    // a displayport for this frame. We'll add the item later on.
+    nsDisplayLayerEventRegions* inactiveRegionItem = nullptr;
+    if (aBuilder->IsPaintingToWindow() &&
+        !mShouldBuildScrollableLayer &&
+        shouldBuildLayer &&
+        gfxPrefs::LayoutEventRegionsEnabled())
+    {
+      inactiveRegionItem = new (aBuilder) nsDisplayLayerEventRegions(aBuilder, mScrolledFrame);
+      inactiveRegionItem->AddInactiveScrollPort(mScrollPort + aBuilder->ToReferenceFrame(mOuter));
+    }
+
     // In case we are not using displayport or the nsDisplayScrollLayers are
     // flattened during visibility computation, we still need to export the
     // metadata about this scroll box to the compositor process.
     nsDisplayScrollInfoLayer* layerItem = new (aBuilder) nsDisplayScrollInfoLayer(
       aBuilder, mScrolledFrame, mOuter);
+
     nsDisplayList* positionedDescendants = scrolledContent.PositionedDescendants();
+    nsDisplayList* destinationList = nullptr;
     if (BuildScrollContainerLayers()) {
       // We process display items from bottom to top, so if we need to flatten after
       // the scroll layer items have been processed we need to be on the top.
       if (!positionedDescendants->IsEmpty()) {
         layerItem->SetOverrideZIndex(MaxZIndexInList(positionedDescendants, aBuilder));
-        positionedDescendants->AppendNewToTop(layerItem);
+        destinationList = positionedDescendants;
       } else {
-        aLists.Outlines()->AppendNewToTop(layerItem);
+        destinationList = aLists.Outlines();
       }
     } else {
       int32_t zindex =
         MaxZIndexInListOfItemsContainedInFrame(positionedDescendants, mOuter);
       if (zindex >= 0) {
         layerItem->SetOverrideZIndex(zindex);
-        positionedDescendants->AppendNewToTop(layerItem);
+        destinationList = positionedDescendants;
       } else {
-        scrolledContent.Outlines()->AppendNewToTop(layerItem);
+        destinationList = scrolledContent.Outlines();
       }
     }
+    if (inactiveRegionItem) {
+      destinationList->AppendNewToTop(inactiveRegionItem);
+    }
+    destinationList->AppendNewToTop(layerItem);
   }
   // Now display overlay scrollbars and the resizer, if we have one.
   AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent, usingDisplayport,
                       createLayersForScrollbars, true);
   scrolledContent.MoveTo(aLists);
 }
 
 void
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -2890,17 +2890,20 @@ nsLineLayout::ApplyFrameJustification(Pe
 
 static nsIFrame*
 FindNearestRubyBaseAncestor(nsIFrame* aFrame)
 {
   MOZ_ASSERT(aFrame->StyleContext()->IsInlineDescendantOfRuby());
   while (aFrame && aFrame->GetType() != nsGkAtoms::rubyBaseFrame) {
     aFrame = aFrame->GetParent();
   }
-  MOZ_ASSERT(aFrame, "No ruby base ancestor?");
+  // XXX It is possible that no ruby base ancestor is found because of
+  // some edge cases like form control or canvas inside ruby text.
+  // See bug 1138092 comment 4.
+  NS_ASSERTION(aFrame, "No ruby base ancestor?");
   return aFrame;
 }
 
 /**
  * This method expands the given frame by the given reserved isize.
  */
 void
 nsLineLayout::ExpandRubyBox(PerFrameData* aFrame, nscoord aReservedISize,
@@ -3061,26 +3064,26 @@ nsLineLayout::TextAlignLine(nsLineBox* a
                               textAlign == NS_STYLE_TEXT_ALIGN_JUSTIFY))) {
     JustificationComputationState computeState;
     ComputeFrameJustification(psd, computeState);
     if (mHasRuby && computeState.mFirstParticipant) {
       PerFrameData* firstFrame = computeState.mFirstParticipant;
       if (firstFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) {
         MOZ_ASSERT(!firstFrame->mJustificationAssignment.mGapsAtStart);
         nsIFrame* rubyBase = FindNearestRubyBaseAncestor(firstFrame->mFrame);
-        if (IsRubyAlignSpaceAround(rubyBase)) {
+        if (rubyBase && IsRubyAlignSpaceAround(rubyBase)) {
           firstFrame->mJustificationAssignment.mGapsAtStart = 1;
           additionalGaps++;
         }
       }
       PerFrameData* lastFrame = computeState.mLastParticipant;
       if (lastFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) {
         MOZ_ASSERT(!lastFrame->mJustificationAssignment.mGapsAtEnd);
         nsIFrame* rubyBase = FindNearestRubyBaseAncestor(lastFrame->mFrame);
-        if (IsRubyAlignSpaceAround(rubyBase)) {
+        if (rubyBase && IsRubyAlignSpaceAround(rubyBase)) {
           lastFrame->mJustificationAssignment.mGapsAtEnd = 1;
           additionalGaps++;
         }
       }
     }
   }
 
   if (!isSVG && doTextAlign) {
--- a/layout/ipc/moz.build
+++ b/layout/ipc/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
 EXPORTS.mozilla.layout += [
     'RenderFrameChild.h',
     'RenderFrameParent.h',
     'VsyncChild.h',
     'VsyncParent.h',
 ]
 
 UNIFIED_SOURCES += [
--- a/layout/mathml/moz.build
+++ b/layout/mathml/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'MathML')
+
 if CONFIG['ENABLE_TESTS']:
     MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 
 UNIFIED_SOURCES += [
     'nsMathMLChar.cpp',
     'nsMathMLContainerFrame.cpp',
     'nsMathMLFrame.cpp',
     'nsMathMLmactionFrame.cpp',
--- a/layout/media/moz.build
+++ b/layout/media/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Video/Audio')
+
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     GeckoSharedLibrary('gkmedias', linkage=None)
     USE_LIBS += [
         'mozalloc',
         'nspr',
     ]
 else:
     Library('gkmedias')
--- a/layout/media/webrtc/moz.build
+++ b/layout/media/webrtc/moz.build
@@ -1,8 +1,11 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'WebRTC')
+
 Library('webrtc')
 FINAL_LIBRARY = 'xul'
--- a/layout/moz.build
+++ b/layout/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Layout')
+
 DIRS += [
     'style',
     'base',
     'generic',
     'forms',
     'tables',
     'svg',
     'xul',
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-ruby/lang-specific-style-1-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>Bug 1133624 - Test for lang-specific default stylesheet for ruby</title>
+  <link rel="stylesheet" href="common.css">
+</head>
+<body style="font: 200%/normal Ahem !important">
+  <p><ruby><rb>base x x<rt style="ruby-align: space-around; font-size: 50%">text x x</ruby></p>
+  <p><ruby><rb>base x x<rt style="ruby-align: space-around; font-size: 50%">text x x</ruby></p>
+  <p><ruby><rb>base x x<rt style="ruby-align: center; font-size: 50%">text x x</ruby></p>
+  <p><ruby><rb>base x x<rt style="ruby-align: center; font-size: 30%">text x x</ruby></p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-ruby/lang-specific-style-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="UTF-8">
+  <title>Bug 1133624 - Test for lang-specific default stylesheet for ruby</title>
+  <link rel="stylesheet" href="common.css">
+</head>
+<body style="font: 200%/normal Ahem !important">
+  <p lang="en"><ruby><rb>base x x<rt>text x x</ruby></p>
+  <p lang="ja"><ruby><rb>base x x<rt>text x x</ruby></p>
+  <p lang="zh-CN"><ruby><rb>base x x<rt>text x x</ruby></p>
+  <p lang="zh-TW"><ruby><rb>base x x<rt>text x x</ruby></p>
+</body>
+</html>
--- a/layout/reftests/css-ruby/reftest.list
+++ b/layout/reftests/css-ruby/reftest.list
@@ -18,16 +18,17 @@ default-preferences pref(layout.css.ruby
 == float-handling.html float-handling-ref.html
 test-pref(dom.meta-viewport.enabled,true) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == inflated-ruby-1.html inflated-ruby-1-ref.html
 == intra-level-whitespace-1.html intra-level-whitespace-1-ref.html
 == intra-level-whitespace-2.html intra-level-whitespace-2-ref.html
 == intra-level-whitespace-3.html intra-level-whitespace-3-ref.html
 == intrinsic-isize-1.html intrinsic-isize-1-ref.html
 == justification-1.html justification-1-ref.html
 == justification-2.html justification-2-ref.html
+fuzzy-if(winWidget,255,792) == lang-specific-style-1.html lang-specific-style-1-ref.html # bug 1134947
 == line-breaking-1.html line-breaking-1-ref.html
 == line-height-1.html line-height-1-ref.html
 == line-height-2.html line-height-2-ref.html
 == line-height-3.html line-height-3-ref.html
 == line-height-4.html line-height-4-ref.html
 load nested-ruby-1.html
 == no-transform.html no-transform-ref.html
 == relative-positioning-1.html relative-positioning-1-ref.html
--- a/layout/style/html.css
+++ b/layout/style/html.css
@@ -808,15 +808,21 @@ marquee[direction="up"], marquee[directi
   rtc {
     display: ruby-text-container;
   }
   rtc, rt {
     white-space: nowrap;
     font-size: 50%;
     line-height: 1;
   }
+  rtc:lang(zh), rt:lang(zh) {
+    ruby-align: center;
+  }
+  rtc:lang(zh-TW), rt:lang(zh-TW) {
+    font-size: 30%; /* bopomofo */
+  }
   rtc > rt {
     font-size: inherit;
   }
   ruby, rb, rt, rbc, rtc {
     unicode-bidi: isolate;
   }
 }
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -1,14 +1,29 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'CSS Parsing and Computation')
+
+with Files('nsComputedDOMStyle.*'):
+    BUG_COMPONENT = ('Core', 'DOM: CSS Object Model')
+
+with Files('nsROCSSPrimitiveValue.*'):
+    BUG_COMPONENT = ('Core', 'DOM: CSS Object Model')
+
+with Files('CSSRuleList.*'):
+    BUG_COMPONENT = ('Core', 'DOM: CSS Object Model')
+
+with Files('nsDOM*'):
+    BUG_COMPONENT = ('Core', 'DOM: CSS Object Model')
+
 DIRS += ['xbl-marquee']
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsICSSUnprefixingService.idl',
 ]
 
 XPIDL_MODULE = 'layout_base'
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1203,16 +1203,27 @@ protected:
   bool mSuppressErrors : 1;
 
   // True if we've parsed "display: -webkit-box" as "display: flex" in an
   // earlier declaration within the current block of declarations, as part of
   // emulating support for certain -webkit-prefixed properties on certain
   // sites.
   bool mDidUnprefixWebkitBoxInEarlierDecl; // not :1 so we can use AutoRestore
 
+#ifdef DEBUG
+  // True if any parsing of URL values requires a sheet principal to have
+  // been passed in the nsCSSScanner constructor.  This is usually the case.
+  // It can be set to false, for example, when we create an nsCSSParser solely
+  // to parse a property value to test it for syntactic correctness.  When
+  // false, an assertion that mSheetPrincipal is non-null is skipped.  Should
+  // not be set to false if any nsCSSValues created during parsing can escape
+  // out of the parser.
+  bool mSheetPrincipalRequired;
+#endif
+
   // Stack of rule groups; used for @media and such.
   InfallibleTArray<nsRefPtr<css::GroupRule> > mGroupStack;
 
   // During the parsing of a property (which may be a shorthand), the data
   // are stored in |mTempData|.  (It is needed to ensure that parser
   // errors cause the data to be ignored, and to ensure that a
   // non-'!important' declaration does not override an '!important'
   // one.)
@@ -1280,16 +1291,19 @@ CSSParserImpl::CSSParserImpl()
     mIsChromeOrCertifiedApp(false),
     mViewportUnitsEnabled(true),
     mHTMLMediaMode(false),
     mParsingCompoundProperty(false),
     mInSupportsCondition(false),
     mInFailingSupportsRule(false),
     mSuppressErrors(false),
     mDidUnprefixWebkitBoxInEarlierDecl(false),
+#ifdef DEBUG
+    mSheetPrincipalRequired(true),
+#endif
     mNextFree(nullptr)
 {
 }
 
 CSSParserImpl::~CSSParserImpl()
 {
   mData.AssertInitialState();
   mTempData.AssertInitialState();
@@ -7603,18 +7617,19 @@ CSSParserImpl::ParseSymbols(nsCSSValue& 
   SkipUntil(')');
   return false;
 }
 
 bool
 CSSParserImpl::SetValueToURL(nsCSSValue& aValue, const nsString& aURL)
 {
   if (!mSheetPrincipal) {
-    NS_NOTREACHED("Codepaths that expect to parse URLs MUST pass in an "
-                  "origin principal");
+    NS_ASSERTION(!mSheetPrincipalRequired,
+                 "Codepaths that expect to parse URLs MUST pass in an "
+                 "origin principal");
     return false;
   }
 
   nsRefPtr<nsStringBuffer> buffer(nsCSSValue::BufferFromString(aURL));
 
   // Note: urlVal retains its own reference to |buffer|.
   mozilla::css::URLValue *urlVal =
     new mozilla::css::URLValue(buffer, mBaseURI, mSheetURI, mSheetPrincipal);
@@ -15271,16 +15286,27 @@ CSSParserImpl::IsValueValidForProperty(c
 {
   mData.AssertInitialState();
   mTempData.AssertInitialState();
 
   nsCSSScanner scanner(aPropValue, 0);
   css::ErrorReporter reporter(scanner, mSheet, mChildLoader, nullptr);
   InitScanner(scanner, reporter, nullptr, nullptr, nullptr);
 
+#ifdef DEBUG
+  // We normally would need to pass in a sheet principal to InitScanner,
+  // because we might parse a URL value.  However, we will never use the
+  // parsed nsCSSValue (and so whether we have a sheet principal or not
+  // doesn't really matter), so to avoid failing the assertion in
+  // SetValueToURL, we set mSheetPrincipalRequired to false to declare
+  // that it's safe to skip the assertion.
+  AutoRestore<bool> autoRestore(mSheetPrincipalRequired);
+  mSheetPrincipalRequired = false;
+#endif
+
   nsAutoSuppressErrors suppressErrors(this);
 
   mSection = eCSSSection_General;
   scanner.SetSVGMode(false);
 
   // Check for unknown properties
   if (eCSSProperty_UNKNOWN == aPropID) {
     ReleaseScanner();
--- a/layout/svg/moz.build
+++ b/layout/svg/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'SVG')
+
 EXPORTS += [
     'nsFilterInstance.h',
     'nsSVGEffects.h',
     'nsSVGFilterInstance.h',
     'nsSVGForeignObjectFrame.h',
     'nsSVGIntegrationUtils.h',
     'nsSVGUtils.h',
     'SVGImageContext.h',
--- a/layout/tables/moz.build
+++ b/layout/tables/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Layout: Tables')
+
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 EXPORTS += [
     'nsITableCellLayout.h',
 ]
 
 UNIFIED_SOURCES += [
     'BasicTableLayoutStrategy.cpp',
--- a/layout/tools/reftest/moz.build
+++ b/layout/tools/reftest/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Testing', 'Reftest')
+
 if CONFIG['MOZ_BUILD_APP'] in ('b2g', 'b2g/dev', 'mobile/android'):
     DEFINES['BOOTSTRAP'] = True
     if CONFIG['MOZ_BUILD_APP'] in ('b2g', 'b2g/dev'):
         DEFINES['REFTEST_B2G'] = True
 else:
     EXTRA_PP_COMPONENTS += [
         'reftest-cmdline.js',
         'reftest-cmdline.manifest',
--- a/layout/xul/grid/moz.build
+++ b/layout/xul/grid/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: XUL')
+
 EXPORTS += [
     'nsGrid.h',
     'nsGridCell.h',
     'nsGridLayout2.h',
     'nsGridRow.h',
     'nsGridRowGroupLayout.h',
     'nsGridRowLayout.h',
     'nsGridRowLeafFrame.h',
--- a/layout/xul/moz.build
+++ b/layout/xul/moz.build
@@ -1,14 +1,20 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: XUL')
+
+with Files('*Menu*'):
+    BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: Menus')
+
 if CONFIG['ENABLE_TESTS']:
     MOCHITEST_MANIFESTS += ['test/mochitest.ini']
     MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
     BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 XPIDL_SOURCES += [
     'nsIBoxObject.idl',
     'nsIBrowserBoxObject.idl',
--- a/layout/xul/tree/moz.build
+++ b/layout/xul/tree/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'XP Toolkit/Widgets: XUL')
+
 XPIDL_SOURCES += [
     'nsITreeBoxObject.idl',
     'nsITreeColumns.idl',
     'nsITreeContentView.idl',
     'nsITreeSelection.idl',
     'nsITreeView.idl',
 ]
 
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 6de5d3e488d808dd925ae0885a7552fc0a25b449.
+The git commit ID used was 588c82be50ffee59b7fab71b56e6081a5a89301c.
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -1186,59 +1186,83 @@ void wasapi_stream_destroy(cubeb_stream 
 }
 
 int wasapi_stream_start(cubeb_stream * stm)
 {
   auto_lock lock(stm->stream_reset_lock);
 
   XASSERT(stm && !stm->thread && !stm->shutdown_event);
 
+  HRESULT hr = stm->client->Start();
+  if (hr == AUDCLNT_E_DEVICE_INVALIDATED) {
+    LOG("audioclient invalid device, reconfiguring\n", hr);
+
+    BOOL ok = ResetEvent(stm->reconfigure_event);
+    if (!ok) {
+      LOG("resetting reconfig event failed: %x\n", GetLastError());
+    }
+
+    close_wasapi_stream(stm);
+    int r = setup_wasapi_stream(stm);
+    if (r != CUBEB_OK) {
+      LOG("reconfigure failed\n");
+      return r;
+    }
+
+    HRESULT hr = stm->client->Start();
+    if (FAILED(hr)) {
+      LOG("could not start the stream after reconfig: %x\n", hr);
+      return CUBEB_ERROR;
+    }
+ } else if (FAILED(hr)) {
+    LOG("could not start the stream.\n");
+    return CUBEB_ERROR;
+  }
+
   stm->shutdown_event = CreateEvent(NULL, 0, 0, NULL);
   if (!stm->shutdown_event) {
     LOG("Can't create the shutdown event, error: %x\n", GetLastError());
     return CUBEB_ERROR;
   }
 
   stm->thread = (HANDLE) _beginthreadex(NULL, 256 * 1024, wasapi_stream_render_loop, stm, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
   if (stm->thread == NULL) {
     LOG("could not create WASAPI render thread.\n");
     return CUBEB_ERROR;
   }
 
-  HRESULT hr = stm->client->Start();
-  if (FAILED(hr)) {
-    LOG("could not start the stream.\n");
-    return CUBEB_ERROR;
-  } else {
-    stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
-  }
+  stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
 
-  return FAILED(hr) ? CUBEB_ERROR : CUBEB_OK;
+  return CUBEB_OK;
 }
 
 int wasapi_stream_stop(cubeb_stream * stm)
 {
   XASSERT(stm);
 
-  auto_lock lock(stm->stream_reset_lock);
+  {
+    auto_lock lock(stm->stream_reset_lock);
 
-  HRESULT hr = stm->client->Stop();
-  if (FAILED(hr)) {
-    LOG("could not stop AudioClient\n");
-  }
+    if (!stm->client) {
+      XASSERT(!stm->thread);
+      LOG("stream already stopped\n");
+    } else {
+      HRESULT hr = stm->client->Stop();
+      if (FAILED(hr)) {
+        LOG("could not stop AudioClient\n");
+        return CUBEB_ERROR;
+      }
+    }
 
-  stm->stream_reset_lock->leave();
-  stop_and_join_render_thread(stm);
-  stm->stream_reset_lock->enter();
-
-  if (SUCCEEDED(hr)) {
     stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
   }
 
-  return FAILED(hr) ? CUBEB_ERROR : CUBEB_OK;
+  stop_and_join_render_thread(stm);
+
+  return CUBEB_OK;
 }
 
 int wasapi_stream_get_position(cubeb_stream * stm, uint64_t * position)
 {
   XASSERT(stm && position);
 
   *position = clock_get(stm);
 
--- a/media/webrtc/signaling/test/sdp_unittests.cpp
+++ b/media/webrtc/signaling/test/sdp_unittests.cpp
@@ -1156,25 +1156,30 @@ const std::string kBasicAudioVideoOffer 
 "a=candidate:3 1 UDP 100401151 162.222.183.171 49761 typ relay raddr 162.222.183.171 rport 49761" CRLF
 "a=candidate:6 1 UDP 16515071 162.222.183.171 51858 typ relay raddr 162.222.183.171 rport 51858" CRLF
 "a=candidate:3 2 UDP 100401150 162.222.183.171 62454 typ relay raddr 162.222.183.171 rport 62454" CRLF
 "a=candidate:2 2 UDP 1694236670 24.6.134.204 55428 typ srflx raddr 10.0.0.36 rport 55428" CRLF
 "a=candidate:6 2 UDP 16515070 162.222.183.171 50340 typ relay raddr 162.222.183.171 rport 50340" CRLF
 "a=candidate:0 2 UDP 2130379006 10.0.0.36 55428 typ host" CRLF
 "a=end-of-candidates" CRLF
 "a=ssrc:5150" CRLF
-"m=video 9 RTP/SAVPF 120" CRLF
+"m=video 9 RTP/SAVPF 120 121" CRLF
 "c=IN IP6 ::1" CRLF
 "a=mid:second" CRLF
 "a=rtpmap:120 VP8/90000" CRLF
 "a=fmtp:120 max-fs=3600;max-fr=30" CRLF
+"a=rtpmap:121 VP9/90000" CRLF
+"a=fmtp:121 max-fs=3600;max-fr=30" CRLF
 "a=recvonly" CRLF
 "a=rtcp-fb:120 nack" CRLF
 "a=rtcp-fb:120 nack pli" CRLF
 "a=rtcp-fb:120 ccm fir" CRLF
+"a=rtcp-fb:121 nack" CRLF
+"a=rtcp-fb:121 nack pli" CRLF
+"a=rtcp-fb:121 ccm fir" CRLF
 "a=setup:active" CRLF
 "a=rtcp-mux" CRLF
 "a=msid:streama tracka" CRLF
 "a=msid:streamb trackb" CRLF
 "a=candidate:0 1 UDP 2130379007 10.0.0.36 59530 typ host" CRLF
 "a=candidate:0 2 UDP 2130379006 10.0.0.36 64378 typ host" CRLF
 "a=candidate:2 2 UDP 1694236670 24.6.134.204 64378 typ srflx raddr 10.0.0.36 rport 64378" CRLF
 "a=candidate:6 2 UDP 16515070 162.222.183.171 64941 typ relay raddr 162.222.183.171 rport 64941" CRLF
@@ -1304,18 +1309,19 @@ TEST_P(NewSdpTest, CheckMlines) {
   ASSERT_EQ("101", audio_formats[4]);
 
   ASSERT_EQ(SdpMediaSection::kVideo, mSdp->GetMediaSection(1).GetMediaType())
     << "Wrong type for second media section";
   ASSERT_EQ(SdpMediaSection::kRtpSavpf,
             mSdp->GetMediaSection(1).GetProtocol())
     << "Wrong protocol for video";
   auto video_formats = mSdp->GetMediaSection(1).GetFormats();
-  ASSERT_EQ(1U, video_formats.size()) << "Wrong number of formats for video";
+  ASSERT_EQ(2U, video_formats.size()) << "Wrong number of formats for video";
   ASSERT_EQ("120", video_formats[0]);
+  ASSERT_EQ("121", video_formats[1]);
 
   ASSERT_EQ(SdpMediaSection::kAudio, mSdp->GetMediaSection(2).GetMediaType())
     << "Wrong type for third media section";
 }
 
 TEST_P(NewSdpTest, CheckSetup) {
   ParseSdp(kBasicAudioVideoOffer);
   ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
@@ -1403,24 +1409,33 @@ TEST_P(NewSdpTest, CheckRtpmap) {
   CheckRtpmap("101",
               SdpRtpmapAttributeList::kOtherCodec,
               "telephone-event",
               8000,
               1,
               audiosec.GetFormats()[4],
               rtpmap);
 
-  const SdpMediaSection& videosec = mSdp->GetMediaSection(1);
+  const SdpMediaSection& videosec1 = mSdp->GetMediaSection(1);
   CheckRtpmap("120",
               SdpRtpmapAttributeList::kVP8,
               "VP8",
               90000,
               0,
-              videosec.GetFormats()[0],
-              videosec.GetAttributeList().GetRtpmap());
+              videosec1.GetFormats()[0],
+              videosec1.GetAttributeList().GetRtpmap());
+
+  const SdpMediaSection& videosec2 = mSdp->GetMediaSection(1);
+  CheckRtpmap("121",
+              SdpRtpmapAttributeList::kVP9,
+              "VP9",
+              90000,
+              0,
+              videosec2.GetFormats()[1],
+              videosec2.GetAttributeList().GetRtpmap());
 }
 
 const std::string kH264AudioVideoOffer =
 "v=0" CRLF
 "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
 "s=SIP Call" CRLF
 "c=IN IP4 224.0.0.1/100/12" CRLF
 "t=0 0" CRLF
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/0007-Preserve-LastError-when-calling-TlsGetValue.patch
@@ -0,0 +1,45 @@
+From f44c19741e98f4a87cf20e59e31634bb8a29c657 Mon Sep 17 00:00:00 2001
+From: Mike Hommey <mh@glandium.org>
+Date: Wed, 4 Mar 2015 10:54:10 +0900
+Subject: [PATCH] Preserve LastError when calling TlsGetValue
+
+TlsGetValue has a semantic difference with pthread_getspecific, in that it
+can return a non-error NULL value, so it always sets the LastError.
+But allocator callers may not be expecting calling e.g. free() to change
+the value of the last error, so preserve it.
+---
+ include/jemalloc/internal/tsd.h | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/include/jemalloc/internal/tsd.h b/include/jemalloc/internal/tsd.h
+index dbb91a2..62a887e 100644
+--- a/include/jemalloc/internal/tsd.h
++++ b/include/jemalloc/internal/tsd.h
+@@ -277,9 +277,11 @@ a_name##tsd_set(a_type *val)						\
+ a_attr bool								\
+ a_name##tsd_cleanup_wrapper(void)					\
+ {									\
+-	a_name##tsd_wrapper_t *wrapper;					\
++	DWORD error = GetLastError();					\
++	a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)	\
++	    TlsGetValue(a_name##tsd_tsd);				\
++	SetLastError(error);						\
+ 									\
+-	wrapper = (a_name##tsd_wrapper_t *)TlsGetValue(a_name##tsd_tsd);\
+ 	if (wrapper == NULL)						\
+ 		return (false);						\
+ 	if (a_cleanup != malloc_tsd_no_cleanup &&			\
+@@ -307,8 +309,10 @@ a_name##tsd_wrapper_set(a_name##tsd_wrapper_t *wrapper)			\
+ a_attr a_name##tsd_wrapper_t *						\
+ a_name##tsd_wrapper_get(void)						\
+ {									\
++	DWORD error = GetLastError();					\
+ 	a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)	\
+ 	    TlsGetValue(a_name##tsd_tsd);				\
++	SetLastError(error);						\
+ 									\
+ 	if (unlikely(wrapper == NULL)) {				\
+ 		wrapper = (a_name##tsd_wrapper_t *)			\
+-- 
+2.3.0.3.g98027e3
+
--- a/memory/jemalloc/src/include/jemalloc/internal/tsd.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/tsd.h
@@ -272,19 +272,21 @@ a_name##tsd_set(a_type *val)						\
 }
 #elif (defined(_WIN32))
 #define	malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer,		\
     a_cleanup)								\
 /* Initialization/cleanup. */						\
 a_attr bool								\
 a_name##tsd_cleanup_wrapper(void)					\
 {									\
-	a_name##tsd_wrapper_t *wrapper;					\
+	DWORD error = GetLastError();					\
+	a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)	\
+	    TlsGetValue(a_name##tsd_tsd);				\
+	SetLastError(error);						\
 									\
-	wrapper = (a_name##tsd_wrapper_t *)TlsGetValue(a_name##tsd_tsd);\
 	if (wrapper == NULL)						\
 		return (false);						\
 	if (a_cleanup != malloc_tsd_no_cleanup &&			\
 	    wrapper->initialized) {					\
 		wrapper->initialized = false;				\
 		a_cleanup(&wrapper->val);				\
 		if (wrapper->initialized) {				\
 			/* Trigger another cleanup round. */		\
@@ -302,18 +304,20 @@ a_name##tsd_wrapper_set(a_name##tsd_wrap
 		malloc_write("<jemalloc>: Error setting"		\
 		    " TSD for "#a_name"\n");				\
 		abort();						\
 	}								\
 }									\
 a_attr a_name##tsd_wrapper_t *						\
 a_name##tsd_wrapper_get(void)						\
 {									\
+	DWORD error = GetLastError();					\
 	a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)	\
 	    TlsGetValue(a_name##tsd_tsd);				\
+	SetLastError(error);						\
 									\
 	if (unlikely(wrapper == NULL)) {				\
 		wrapper = (a_name##tsd_wrapper_t *)			\
 		    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));	\
 		if (wrapper == NULL) {					\
 			malloc_write("<jemalloc>: Error allocating"	\
 			    " TSD for "#a_name"\n");			\
 			abort();					\
--- a/memory/jemalloc/update.sh
+++ b/memory/jemalloc/update.sh
@@ -15,13 +15,14 @@ git describe --long --abbrev=40 > VERSIO
 rm -rf .git .gitignore .gitattributes autom4te.cache .autom4te.cfg
 
 patch -p1 < ../0001-Dont-overwrite-VERSION-on-a-git-repository.patch
 patch -p1 < ../0002-Move-variable-declaration-to-the-top-its-block-for-M.patch
 patch -p1 < ../0003-Add-a-isblank-definition-for-MSVC-2013.patch
 patch -p1 < ../0004-Implement-stats.bookkeeping.patch
 patch -p1 < ../0005-Bug-1121314-Avoid-needing-the-arena-in-chunk_alloc_d.patch
 patch -p1 < ../0006-Make-opt.lg_dirty_mult-work-as-documented.patch
+patch -p1 < ../0007-Preserve-LastError-when-calling-TlsGetValue.patch
 
 cd ..
 hg addremove -q src
 
 echo "jemalloc has now been updated.  Don't forget to run hg commit!"
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -1,108 +1,98 @@
 [testGeckoProfile]
 # [test_bug720538] # disabled on fig - bug 897072
 [testAboutPage]
 # disabled on Android 2.3; bug 975187
 skip-if = android_version == "10"
 [testAboutPasswords]
 [testAddonManager]
-# disabled on x86; bug 936216
 # disabled on 2.3; bug 941624, bug 1063509, bug 1073374, bug 1087221, bug 1088023, bug 1088027, bug 1090206
-skip-if = android_version == "10" || processor == "x86"
+skip-if = android_version == "10"
 [testAddSearchEngine]
 # disabled on Android 2.3; bug 979552
 skip-if = android_version == "10"
 [testAdobeFlash]
-skip-if = processor == "x86"
 [testANRReporter]
 [testAppConstants]
 [testAwesomebar]
 [testAxisLocking]
-# disabled on x86 only; bug 927476
-skip-if = processor == "x86"
 # [testBookmark] # see bug 915350
 [testBookmarksPanel]
 # disabled on 2.3; bug 979615
 skip-if = android_version == "10"
 [testBookmarkFolders]
 # disabled on Android 2.3; bug 979552
 skip-if = android_version == "10"
 # [testBookmarklets] # see bug 915350
 # [testBookmarkKeyword] # see bug 915350
 [testBrowserProvider]
 [testBrowserSearchVisibility]
 [testClearPrivateData]
-# disabled on x86 and 2.3; bug 948591
-skip-if = android_version == "10" || processor == "x86"
+# disabled on 2.3; bug 948591
+skip-if = android_version == "10"
 [testDBUtils]
 [testDistribution]
 [testDoorHanger]
 # disabled on 2.3; bug 1085609
 skip-if = android_version == "10"
 [testFilterOpenTab]
 [testFindInPage]
 # disabled on 2.3
 skip-if = android_version == "10"
 [testFlingCorrectness]
-# disabled on x86 only; bug 927476
-skip-if = processor == "x86"
 [testFormHistory]
 [testGetUserMedia]
 # [testHistory] # see bug 915350
 [testHomeBanner]
-# disabled on x86 only; bug 957185
-skip-if = processor == "x86"
 [testImportFromAndroid]
-# disabled on x86 and 2.3; bug 900664, 979552
-skip-if = android_version == "10" || processor == "x86"
+# disabled on 2.3; bug 979552
+skip-if = android_version == "10"
 [testInputUrlBar]
 [testJarReader]
 [testLinkContextMenu]
 # [testHomeListsProvider] # see bug 952310
 [testHomeProvider]
 [testLoad]
 [testMailToContextMenu]
 # [testMasterPassword] disabled for being finicky, see bug 1033013
 # disabled on 2.3; bug 979603
 # disabled on 4.0; bug 1006242
 # skip-if = android_version == "10" || android_version == "15"
 [testNewTab]
 [testPanCorrectness]
-# disabled on x86 only; bug 927476
-skip-if = processor == "x86"
 # [testPasswordEncrypt] # see bug 824067
 [testPasswordProvider]
 # [testPermissions] # see bug 757475
 [testPictureLinkContextMenu]
 [testPrefsObserver]
 [testPrivateBrowsing]
 [testPromptGridInput]
-# bug 957185 for x86, bug 1001657 for 2.3
-skip-if = android_version == "10" || processor == "x86"
+# bug 1001657 for 2.3
+skip-if = android_version == "10"
 # [testReaderMode] # see bug 913254, 936224
 [testReadingListCache]
 [testReadingListProvider]
 [testSearchHistoryProvider]
 [testSearchSuggestions]
 # disabled on 2.3; bug 907768
 skip-if = android_version == "10"
 [testSessionOOMSave]
-# disabled on x86 and 2.3; bug 945395
-skip-if = android_version == "10" || processor == "x86"
+# disabled on 2.3; bug 945395
+skip-if = android_version == "10"
 [testSessionOOMRestore]
 # disabled on Android 2.3; bug 979600
 skip-if = android_version == "10"
 [testSettingsMenuItems]
 # disabled on Android 2.3; bug 979552
 skip-if = android_version == "10"
 # [testShareLink] # see bug 915897
 [testSystemPages]
-# disabled on x86 and 2.3; bug 907383, 979603
-skip-if = android_version == "10" || processor == "x86"
+# disabled on 2.3; bug 979603
+skip-if = android_version == "10"
 # [testThumbnails] # see bug 813107
 [testTitleBar]
 # disabled on Android 2.3; bug 979552
 skip-if = android_version == "10"
 # [testVkbOverlap] # see bug 907274
 
 # Using JavascriptTest
 [testAccounts]
@@ -113,17 +103,17 @@ skip-if = android_version == "10"
 [testFilePicker]
 [testHistoryService]
 [testJNI]
 # [testMozPay] # see bug 945675
 [testNetworkManager]
 [testOfflinePage]
 [testOrderedBroadcast]
 [testOSLocale]
-skip-if = processor == "x86" || android_version == "10" # x86: Bug 1088708, 2.3: Bug 1124494
+skip-if = android_version == "10" # 2.3: Bug 1124494
 [testResourceSubstitutions]
 [testRestrictedProfiles]
 [testSessionFormData]
 [testSharedPreferences]
 [testSimpleDiscovery]
 [testTrackingProtection]
 [testUITelemetry]
 [testVideoControls]
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -422,20 +422,20 @@ pref("media.getusermedia.playout_delay",
 #endif
 #endif
 
 #if !defined(ANDROID)
 pref("media.getusermedia.screensharing.enabled", true);
 #endif
 
 #ifdef RELEASE_BUILD
-pref("media.getusermedia.screensharing.allowed_domains", "webex.com,*.webex.com,collaborate.com,*.collaborate.com,projectsquared.com,*.projectsquared.com,*.room.co,room.co,beta.talky.io,talky.io,*.clearslide.com,appear.in,*.appear.in,tokbox.com,*.tokbox.com,example.com");
+pref("media.getusermedia.screensharing.allowed_domains", "webex.com,*.webex.com,collaborate.com,*.collaborate.com,projectsquared.com,*.projectsquared.com,*.room.co,room.co,beta.talky.io,talky.io,*.clearslide.com,appear.in,*.appear.in,tokbox.com,*.tokbox.com,*.sso.francetelecom.fr,*.si.francetelecom.fr,*.sso.infra.ftgroup,*.multimedia-conference.orange-business.com,*.espacecollaboration.orange-business.com,example.com");
 #else
  // temporary value, not intended for release - bug 1049087
-pref("media.getusermedia.screensharing.allowed_domains", "mozilla.github.io,webex.com,*.webex.com,collaborate.com,*.collaborate.com,projectsquared.com,*.projectsquared.com,*.room.co,room.co,beta.talky.io,talky.io,*.clearslide.com,appear.in,*.appear.in,tokbox.com,*.tokbox.com,example.com");
+pref("media.getusermedia.screensharing.allowed_domains", "mozilla.github.io,webex.com,*.webex.com,collaborate.com,*.collaborate.com,projectsquared.com,*.projectsquared.com,*.room.co,room.co,beta.talky.io,talky.io,*.clearslide.com,appear.in,*.appear.in,tokbox.com,*.tokbox.com,*.sso.francetelecom.fr,*.si.francetelecom.fr,*.sso.infra.ftgroup,*.multimedia-conference.orange-business.com,*.espacecollaboration.orange-business.com,example.com");
 #endif
 // OS/X 10.6 and XP have screen/window sharing off by default due to various issues - Caveat emptor
 pref("media.getusermedia.screensharing.allow_on_old_platforms", false);
 
 // TextTrack support
 pref("media.webvtt.enabled", true);
 pref("media.webvtt.regions.enabled", false);
 
--- a/python/mozbuild/mozbuild/sphinx.py
+++ b/python/mozbuild/mozbuild/sphinx.py
@@ -104,19 +104,20 @@ def format_module(m):
 
     for subcontext, cls in sorted(m.SUBCONTEXTS.items()):
         lines.extend([
             '.. _mozbuild_subcontext_%s:' % subcontext,
             '',
             'Sub-Context: %s' % subcontext,
             '=============' + '=' * len(subcontext),
             '',
-            prepare_docstring(cls.__doc__)[0],
-            '',
         ])
+        lines.extend(prepare_docstring(cls.__doc__))
+        if lines[-1]:
+            lines.append('')
 
         for k, v in sorted(cls.VARIABLES.items()):
             lines.extend(variable_reference(k, *v))
 
     lines.extend([
         'Variables',
         '=========',
         '',
rename from testing/config/mozharness/android_arm_4_4_config.py
rename to testing/config/mozharness/android_arm_4_3_config.py
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -14,17 +14,19 @@ var Cu = Components.utils;
 Cu.import("resource://specialpowers/MockFilePicker.jsm");
 Cu.import("resource://specialpowers/MockColorPicker.jsm");
 Cu.import("resource://specialpowers/MockPermissionPrompt.jsm");
 Cu.import("resource://specialpowers/MockPaymentsUIGlue.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-Cu.importGlobalProperties(["File"]);
+if (!this.File) {
+    Cu.importGlobalProperties(["File"]);
+}
 
 // Allow stuff from this scope to be accessed from non-privileged scopes. This
 // would crash if used outside of automation.
 Cu.forcePermissiveCOWs();
 
 function SpecialPowersAPI() {
   this._consoleListeners = [];
   this._encounteredCrashDumpFiles = [];
--- a/toolkit/devtools/server/tests/mochitest/test_css-logic.html
+++ b/toolkit/devtools/server/tests/mochitest/test_css-logic.html
@@ -10,17 +10,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
   <script type="application/javascript;version=1.8">
 Cu.import("resource://gre/modules/devtools/Loader.jsm");
 const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
 
 const {CssLogic} = devtools.require("devtools/styleinspector/css-logic");
-Cu.importGlobalProperties(['CSS']);
 
 window.onload = function() {
   SimpleTest.waitForExplicitFinish();
   runNextTest();
 }
 
 addTest(function findAllCssSelectors() {
   var nodes = document.querySelectorAll('*');
--- a/toolkit/xre/WindowsCrtPatch.h
+++ b/toolkit/xre/WindowsCrtPatch.h
@@ -100,17 +100,17 @@ PatchModuleImports(HMODULE module, PIMAG
   }
 }
 
 PIMAGE_NT_HEADERS NTAPI
 patched_RtlImageNtHeader(HMODULE module)
 {
   PIMAGE_NT_HEADERS headers = stub_RtlImageNtHeader(module);
 
-  if (module == GetModuleHandleA("msvcr120.dll")) {
+  if (module == GetModuleHandleW(L"msvcr120.dll")) {
     PatchModuleImports(module, headers);
   }
 
   return headers;
 }
 
 // Non-inline to make the asserts stand out
 MOZ_NEVER_INLINE void
--- a/toolkit/xre/nsNativeAppSupportUnix.cpp
+++ b/toolkit/xre/nsNativeAppSupportUnix.cpp
@@ -62,25 +62,27 @@ typedef enum {
   GNOME_INTERACT_ANY
 } GnomeInteractStyle;
 
 typedef enum {
   GNOME_DIALOG_ERROR,
   GNOME_DIALOG_NORMAL
 } GnomeDialogType;
 
+#if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
 typedef GnomeProgram * (*_gnome_program_init_fn)(const char *, const char *,
                                                  const GnomeModuleInfo *, int,
                                                  char **, const char *, ...);
 typedef GnomeProgram * (*_gnome_program_get_fn)(void);
 typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)();
 typedef GnomeClient * (*_gnome_master_client_fn)(void);
 typedef void (*_gnome_client_set_restart_command_fn)(GnomeClient*, gint, gchar*[]);
 
 static _gnome_client_set_restart_command_fn gnome_client_set_restart_command;
+#endif
 
 gboolean save_yourself_cb(GnomeClient *client, gint phase,
                           GnomeSaveStyle style, gboolean shutdown,
                           GnomeInteractStyle interact, gboolean fast,
                           gpointer user_data)
 {
   nsCOMPtr<nsIObserverService> obsServ =
     mozilla::services::GetObserverService();
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -614,20 +614,24 @@ CycleCollectedJSRuntime::NoteGCThingXPCO
   else if (aClasp->flags & JSCLASS_HAS_PRIVATE &&
            aClasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "js::GetObjectPrivate(obj)");
     aCb.NoteXPCOMChild(static_cast<nsISupports*>(js::GetObjectPrivate(aObj)));
   } else {
     const DOMJSClass* domClass = GetDOMClass(aObj);
     if (domClass) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "UnwrapDOMObject(obj)");
+      // It's possible that our object is an unforgeable holder object, in
+      // which case it doesn't actually have a C++ DOM object associated with
+      // it.  Use UnwrapPossiblyNotInitializedDOMObject, which produces null in
+      // that case, since NoteXPCOMChild/NoteNativeChild are null-safe.
       if (domClass->mDOMObjectIsISupports) {
-        aCb.NoteXPCOMChild(UnwrapDOMObject<nsISupports>(aObj));
+        aCb.NoteXPCOMChild(UnwrapPossiblyNotInitializedDOMObject<nsISupports>(aObj));
       } else if (domClass->mParticipant) {
-        aCb.NoteNativeChild(UnwrapDOMObject<void>(aObj),
+        aCb.NoteNativeChild(UnwrapPossiblyNotInitializedDOMObject<void>(aObj),
                             domClass->mParticipant);
       }
     }
   }
 }
 
 void
 CycleCollectedJSRuntime::TraverseGCThing(TraverseSelect aTs, JS::GCCellPtr aThing,