Merge latest green birch changeset and mozilla-central
authorEd Morley <emorley@mozilla.com>
Mon, 15 Jul 2013 13:01:56 +0100
changeset 150740 5e191a26d909f97239e4773529ba3ef8aaba6d8e
parent 150739 e86f02d4738ebf2033fded33c9f0529794fb774e (current diff)
parent 150732 ff0a372e3170025796ab97ce7c89073af7a0573f (diff)
child 150741 79439df5bf5d7ba2a6a7b2b8ee991698a39c1df6
child 150752 a65dec53121c5a25f8599b2a9461916c061eeda8
child 150788 1e847cab869ec7dda7e289c8c00ff07968dc8594
child 150901 4e0a9e8a698c760a5cc1de3a711d695e497508f1
child 170117 1ba44a63743dfdd90d13f438252633776dbd966e
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.0a1
first release with
nightly linux32
5e191a26d909 / 25.0a1 / 20130715100109 / files
nightly linux64
5e191a26d909 / 25.0a1 / 20130715100109 / files
nightly mac
5e191a26d909 / 25.0a1 / 20130715100109 / files
nightly win32
5e191a26d909 / 25.0a1 / 20130715100109 / files
nightly win64
5e191a26d909 / 25.0a1 / 20130715100109 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge latest green birch changeset and mozilla-central
dom/telephony/TelephonyFactory.h
js/src/frontend/SharedContext-inl.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -12,9 +12,9 @@
 #          O               O
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
-Bug 887463 - Remove webvtt parser.
+Bug 870407 - move CMMSRCS to mozbuild
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1030,35 +1030,59 @@ HyperTextAccessible::GetTextBeforeOffset
     }
 
     case BOUNDARY_LINE_START: {
       if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
         offset = AdjustCaretOffset(offset);
 
       // If we are at last empty then home key and get the text (last empty line
       // doesn't have own frame).
-      if (offset == CharacterCount()) {
-        nsAutoString lastChar;
-        GetText(offset -1, -1, lastChar);
-        if (lastChar.EqualsLiteral("\n")) {
-          *aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
-          *aEndOffset = offset;
-          return GetText(*aStartOffset, *aEndOffset, aText);
-        }
+      if (IsEmptyLastLineOffset(offset)) {
+        *aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
+        *aEndOffset = offset;
+        return GetText(*aStartOffset, *aEndOffset, aText);
       }
 
       // Home key, up arrow, home key.
       *aEndOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
       *aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
       *aStartOffset = FindLineBoundary(*aStartOffset, eDirPrevious, eSelectBeginLine);
 
       return GetText(*aStartOffset, *aEndOffset, aText);
     }
 
-    case BOUNDARY_LINE_END:
+    case BOUNDARY_LINE_END: {
+      if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
+        offset = AdjustCaretOffset(offset);
+
+      // Nothing if we are at first line.
+      int32_t tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
+      if (tmpOffset == 0) {
+        *aStartOffset = *aEndOffset = 0;
+        return NS_OK;
+      }
+
+      // Up arrow, end key to find previous line endings.
+      if (IsEmptyLastLineOffset(offset)) { // no own frame for a last line
+        tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
+        *aStartOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
+        *aEndOffset = offset - 1;
+        return GetText(*aStartOffset, *aEndOffset, aText);
+      }
+
+      tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
+      *aEndOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
+      tmpOffset = FindLineBoundary(*aEndOffset, eDirPrevious, eSelectLine);
+      *aStartOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
+      if (*aStartOffset == *aEndOffset) // we are at second line
+        *aStartOffset = 0;
+
+      return GetText(*aStartOffset, *aEndOffset, aText);
+    }
+
     case BOUNDARY_ATTRIBUTE_RANGE:
       return GetTextHelper(eGetBefore, aBoundaryType, aOffset,
                            aStartOffset, aEndOffset, aText);
 
     default:
       return NS_ERROR_INVALID_ARG;
   }
 }
@@ -1093,23 +1117,19 @@ HyperTextAccessible::GetTextAtOffset(int
       *aEndOffset = FindWordBoundary(offset, eDirNext, eEndWord);
       *aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eEndWord);
       return GetText(*aStartOffset, *aEndOffset, aText);
 
     case BOUNDARY_LINE_START: {
       // Empty last line doesn't have own frame (a previous line contains '\n'
       // character instead) thus we can't operate on last line separately
       // from previous line.
-      if (offset == CharacterCount()) {
-        nsAutoString lastChar;
-        GetText(offset -1, -1, lastChar);
-        if (lastChar.EqualsLiteral("\n")) {
-          *aStartOffset = *aEndOffset = offset;
-          return NS_OK;
-        }
+      if (IsEmptyLastLineOffset(offset)) {
+        *aStartOffset = *aEndOffset = offset;
+        return NS_OK;
       }
 
       if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
         offset = AdjustCaretOffset(offset);
 
       // Home key, arrow down and if not on last line then home key.
       *aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
       *aEndOffset = FindLineBoundary(offset, eDirNext, eSelectLine);
@@ -1119,25 +1139,21 @@ HyperTextAccessible::GetTextAtOffset(int
 
       return GetText(*aStartOffset, *aEndOffset, aText);
     }
 
     case BOUNDARY_LINE_END: {
       // Empty last line doesn't have own frame (a previous line contains '\n'
       // character instead) thus we can't operate on last line separately
       // from the previous line.
-      if (offset == CharacterCount()) {
-        nsAutoString lastChar;
-        GetText(offset -1, -1, lastChar);
-        if (lastChar.EqualsLiteral("\n")) {
-          *aStartOffset = offset - 1;
-          *aEndOffset = offset;
-          aText = lastChar;
-          return NS_OK;
-        }
+      if (IsEmptyLastLineOffset(offset)) {
+        *aStartOffset = offset - 1;
+        *aEndOffset = offset;
+        aText.AssignLiteral("\n");
+        return NS_OK;
       }
 
       if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
         offset = AdjustCaretOffset(offset);
 
       // In contrast to word end boundary we follow the spec here. End key,
       // then up arrow and if not on first line then end key.
       *aEndOffset = FindLineBoundary(offset, eDirNext, eSelectEndLine);
--- a/accessible/src/generic/HyperTextAccessible.h
+++ b/accessible/src/generic/HyperTextAccessible.h
@@ -279,16 +279,29 @@ protected:
           frameSelection->GetHint() == nsFrameSelection::HINTLEFT) {
         return aOffset - 1;
       }
     }
     return aOffset;
   }
 
   /**
+   * Return true if the given offset points to terminal empty line if any.
+   */
+  bool IsEmptyLastLineOffset(int32_t aOffset)
+  {
+    if (aOffset != static_cast<int32_t>(CharacterCount()))
+      return false;
+
+    nsAutoString lastChar;
+    GetText(aOffset -1, -1, lastChar);
+    return lastChar.EqualsLiteral("\n");
+  }
+
+  /**
    * Return an offset of the found word boundary.
    */
   int32_t FindWordBoundary(int32_t aOffset, nsDirection aDirection,
                            EWordMovementType aWordMovementType)
   {
     return FindBoundary(aOffset, aDirection, eSelectWord, aWordMovementType);
   }
 
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -357,50 +357,74 @@ this.AccessFu = {
   _processedMessageManagers: []
 };
 
 var Output = {
   brailleState: {
     startOffset: 0,
     endOffset: 0,
     text: '',
+    selectionStart: 0,
+    selectionEnd: 0,
 
     init: function init(aOutput) {
       if (aOutput && 'output' in aOutput) {
         this.startOffset = aOutput.startOffset;
         this.endOffset = aOutput.endOffset;
         // We need to append a space at the end so that the routing key corresponding
         // to the end of the output (i.e. the space) can be hit to move the caret there.
         this.text = aOutput.output + ' ';
-        return this.text;
+        this.selectionStart = typeof aOutput.selectionStart === 'number' ?
+                              aOutput.selectionStart : this.selectionStart;
+        this.selectionEnd = typeof aOutput.selectionEnd === 'number' ?
+                            aOutput.selectionEnd : this.selectionEnd;
+
+        return { text: this.text,
+                 selectionStart: this.selectionStart,
+                 selectionEnd: this.selectionEnd };
       }
+
+      return null;
     },
 
-    update: function update(aText) {
+    adjustText: function adjustText(aText) {
       let newBraille = [];
       let braille = {};
 
       let prefix = this.text.substring(0, this.startOffset).trim();
       if (prefix) {
         prefix += ' ';
         newBraille.push(prefix);
       }
 
-      let newText = aText;
-      newBraille.push(newText);
+      newBraille.push(aText);
 
       let suffix = this.text.substring(this.endOffset).trim();
       if (suffix) {
         suffix = ' ' + suffix;
         newBraille.push(suffix);
       }
 
-      braille.startOffset = prefix.length;
-      braille.output = newBraille.join('');
-      braille.endOffset = braille.output.length - suffix.length;
+      this.startOffset = braille.startOffset = prefix.length;
+      this.text = braille.text = newBraille.join('') + ' ';
+      this.endOffset = braille.endOffset = braille.text.length - suffix.length;
+      braille.selectionStart = this.selectionStart;
+      braille.selectionEnd = this.selectionEnd;
+
+      return braille;
+    },
+
+    adjustSelection: function adjustSelection(aSelection) {
+      let braille = {};
+
+      braille.startOffset = this.startOffset;
+      braille.endOffset = this.endOffset;
+      braille.text = this.text;
+      this.selectionStart = braille.selectionStart = aSelection.selectionStart + this.startOffset;
+      this.selectionEnd = braille.selectionEnd = aSelection.selectionEnd + this.startOffset;
 
       return braille;
     }
   },
 
   start: function start() {
     Cu.import('resource://gre/modules/Geometry.jsm');
   },
@@ -497,32 +521,37 @@ var Output = {
           announceBox.classList.remove('showing');
         break;
       }
     }
   },
 
   Android: function Android(aDetails, aBrowser) {
     const ANDROID_VIEW_TEXT_CHANGED = 0x10;
+    const ANDROID_VIEW_TEXT_SELECTION_CHANGED = 0x2000;
 
     if (!this._bridge)
       this._bridge = Cc['@mozilla.org/android/bridge;1'].getService(Ci.nsIAndroidBridge);
 
     for each (let androidEvent in aDetails) {
       androidEvent.type = 'Accessibility:Event';
       if (androidEvent.bounds)
         androidEvent.bounds = this._adjustBounds(androidEvent.bounds, aBrowser, true);
-      if (androidEvent.eventType === ANDROID_VIEW_TEXT_CHANGED) {
-        androidEvent.brailleText = this.brailleState.update(androidEvent.text);
+
+      switch(androidEvent.eventType) {
+        case ANDROID_VIEW_TEXT_CHANGED:
+          androidEvent.brailleOutput = this.brailleState.adjustText(androidEvent.text);
+          break;
+        case ANDROID_VIEW_TEXT_SELECTION_CHANGED:
+          androidEvent.brailleOutput = this.brailleState.adjustSelection(androidEvent.brailleOutput);
+          break;
+        default:
+          androidEvent.brailleOutput = this.brailleState.init(androidEvent.brailleOutput);
+          break;
       }
-      let (output = this.brailleState.init(androidEvent.brailleText)) {
-        if (typeof output === 'string') {
-          androidEvent.brailleText = output;
-        }
-      };
       this._bridge.handleGeckoMessage(JSON.stringify(androidEvent));
     }
   },
 
   Haptic: function Haptic(aDetails, aBrowser) {
     Utils.win.navigator.vibrate(aDetails.pattern);
   },
 
--- a/accessible/src/jsat/EventManager.jsm
+++ b/accessible/src/jsat/EventManager.jsm
@@ -207,16 +207,19 @@ this.EventManager.prototype = {
           this.present(Presentation.editingModeChanged(editState.editing));
 
         if (editState.editing != this.editState.editing ||
             editState.multiline != this.editState.multiline ||
             editState.atEnd != this.editState.atEnd ||
             editState.atStart != this.editState.atStart)
           this.sendMsgFunc("AccessFu:Input", editState);
 
+        this.present(Presentation.textSelectionChanged(acc.getText(0,-1),
+                     caretOffset, caretOffset, 0, 0, aEvent.isFromUserInput));
+
         this.editState = editState;
         break;
       }
       case EVENT_TEXT_INSERTED:
       case EVENT_TEXT_REMOVED:
       {
         if (aEvent.isFromUserInput) {
           // XXX support live regions as well.
--- a/accessible/src/jsat/Presentation.jsm
+++ b/accessible/src/jsat/Presentation.jsm
@@ -56,17 +56,17 @@ Presenter.prototype = {
    */
   textChanged: function textChanged(aIsInserted, aStartOffset,
                                     aLength, aText,
                                     aModifiedText) {},
 
   /**
    * Text selection has changed. TODO.
    */
-  textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd) {},
+  textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd, aIsFromUser) {},
 
   /**
    * Selection has changed. TODO.
    * @param {nsIAccessible} aObject the object that has been selected.
    */
   selectionChanged: function selectionChanged(aObject) {},
 
   /**
@@ -229,35 +229,35 @@ AndroidPresenter.prototype = {
     if (isExploreByTouch) {
       // This isn't really used by TalkBack so this is a half-hearted attempt
       // for now.
       androidEvents.push({eventType: this.ANDROID_VIEW_HOVER_EXIT, text: []});
     }
 
     let state = Utils.getStates(aContext.accessible)[0];
 
-    let brailleText = '';
+    let brailleOutput = {};
     if (Utils.AndroidSdkVersion >= 16) {
       if (!this._braillePresenter) {
         this._braillePresenter = new BraillePresenter();
       }
-      brailleText = this._braillePresenter.pivotChanged(aContext, aReason).
+      brailleOutput = this._braillePresenter.pivotChanged(aContext, aReason).
                          details;
     }
 
     androidEvents.push({eventType: (isExploreByTouch) ?
                           this.ANDROID_VIEW_HOVER_ENTER : focusEventType,
                         text: UtteranceGenerator.genForContext(aContext).output,
                         bounds: aContext.bounds,
                         clickable: aContext.accessible.actionCount > 0,
                         checkable: !!(state &
                                       Ci.nsIAccessibleStates.STATE_CHECKABLE),
                         checked: !!(state &
                                     Ci.nsIAccessibleStates.STATE_CHECKED),
-                        brailleText: brailleText});
+                        brailleOutput: brailleOutput});
 
 
     return {
       type: this.type,
       details: androidEvents
     };
   },
 
@@ -305,30 +305,38 @@ AndroidPresenter.prototype = {
         aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
     }
 
     return {type: this.type, details: [eventDetails]};
   },
 
   textSelectionChanged: function AndroidPresenter_textSelectionChanged(aText, aStart,
                                                                        aEnd, aOldStart,
-                                                                       aOldEnd) {
+                                                                       aOldEnd, aIsFromUser) {
     let androidEvents = [];
 
-    if (Utils.AndroidSdkVersion >= 14) {
+    if (Utils.AndroidSdkVersion >= 14 && !aIsFromUser) {
+      if (!this._braillePresenter) {
+        this._braillePresenter = new BraillePresenter();
+      }
+      let brailleOutput = this._braillePresenter.textSelectionChanged(aText, aStart, aEnd,
+                                                                      aOldStart, aOldEnd,
+                                                                      aIsFromUser).details;
+
       androidEvents.push({
         eventType: this.ANDROID_VIEW_TEXT_SELECTION_CHANGED,
         text: [aText],
         fromIndex: aStart,
         toIndex: aEnd,
-        itemCount: aText.length
+        itemCount: aText.length,
+        brailleOutput: brailleOutput
       });
     }
 
-    if (Utils.AndroidSdkVersion >= 16) {
+    if (Utils.AndroidSdkVersion >= 16 && aIsFromUser) {
       let [from, to] = aOldStart < aStart ? [aOldStart, aStart] : [aStart, aOldStart];
       androidEvents.push({
         eventType: this.ANDROID_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
         text: [aText],
         fromIndex: from,
         toIndex: to
       });
     }
@@ -449,19 +457,30 @@ BraillePresenter.prototype = {
 
   pivotChanged: function BraillePresenter_pivotChanged(aContext, aReason) {
     if (!aContext.accessible) {
       return null;
     }
 
     let brailleOutput = BrailleGenerator.genForContext(aContext);
     brailleOutput.output = brailleOutput.output.join(' ');
+    brailleOutput.selectionStart = 0;
+    brailleOutput.selectionEnd = 0;
 
     return { type: this.type, details: brailleOutput };
-  }
+  },
+
+  textSelectionChanged: function BraillePresenter_textSelectionChanged(aText, aStart,
+                                                                       aEnd, aOldStart,
+                                                                       aOldEnd, aIsFromUser) {
+    return { type: this.type,
+             details: { selectionStart: aStart,
+                        selectionEnd: aEnd } };
+  },
+
 
 };
 
 this.Presentation = {
   get presenters() {
     delete this.presenters;
     this.presenters = [new VisualPresenter()];
 
@@ -491,18 +510,21 @@ this.Presentation = {
   textChanged: function Presentation_textChanged(aIsInserted, aStartOffset,
                                     aLength, aText,
                                     aModifiedText) {
     return [p.textChanged(aIsInserted, aStartOffset, aLength,
                           aText, aModifiedText)
               for each (p in this.presenters)];
   },
 
-  textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd) {
-    return [p.textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd)
+  textSelectionChanged: function textSelectionChanged(aText, aStart, aEnd,
+                                                      aOldStart, aOldEnd,
+                                                      aIsFromUser) {
+    return [p.textSelectionChanged(aText, aStart, aEnd,
+                                   aOldStart, aOldEnd, aIsFromUser)
               for each (p in this.presenters)];
   },
 
   tabStateChanged: function Presentation_tabStateChanged(aDocObj, aPageState) {
     return [p.tabStateChanged(aDocObj, aPageState)
               for each (p in this.presenters)];
   },
 
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -238,17 +238,17 @@ function moveCaret(aMessage) {
   }
 
   presentCaretChange(text, oldOffset, accText.caretOffset);
 }
 
 function presentCaretChange(aText, aOldOffset, aNewOffset) {
   if (aOldOffset !== aNewOffset) {
     let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
-                                                aOldOffset, aOldOffset);
+                                                aOldOffset, aOldOffset, true);
     sendAsyncMessage('AccessFu:Present', msg);
   }
 }
 
 function scroll(aMessage) {
   let vc = Utils.getVirtualCursor(content.document);
 
   function tryToScroll() {
--- a/accessible/tests/mochitest/text/test_atcaretoffset.html
+++ b/accessible/tests/mochitest/text/test_atcaretoffset.html
@@ -51,17 +51,17 @@
 
         testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "words", 10, 15,
                          [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "two ", 6, 10,
                              [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10,
-                             "textarea", kTodo, kTodo, kTodo);
+                             "textarea", kTodo, kTodo, kOk);
       }
 
       this.getID = function moveToLastLineEnd_getID()
       {
         return "move to last line end";
       }
     }
 
@@ -114,17 +114,17 @@
 
         testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10,
                          [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "aword\n", 0, 6,
                              [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_END, "aword", 0, 5,
-                             "textarea", kTodo, kTodo, kTodo);
+                             [ "textarea" ]);
       }
 
       this.getID = function moveToMiddleLineStart_getID()
       {
         return "move to middle line start";
       }
     }
 
@@ -145,17 +145,17 @@
 
         testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10,
                          [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "aword\n", 0, 6,
                              [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_END, "aword", 0, 5,
-                             "textarea", kTodo, kTodo, kTodo);
+                             [ "textarea" ]);
       }
 
       this.getID = function moveToMiddleLineEnd_getID()
       {
         return "move to middle line end";
       }
     }
 
@@ -207,29 +207,29 @@
 
         testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "aword", 0, 5,
                          [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "", 0, 0,
                              [ "textarea" ]);
 
         testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_END, "", 0, 0,
-                             "textarea", kTodo, kOk, kTodo);
+                             [ "textarea" ]);
       }
 
       this.getID = function moveToFirstLineEnd_getID()
       {
         return "move to first line end";
       }
     }
 
     var gQueue = null;
     function doTest()
     {
-      SimpleTest.expectAssertions(3);
+      SimpleTest.expectAssertions(1);
 
       gQueue = new eventQueue();
       gQueue.push(new moveToLastLineEnd());
       gQueue.push(new moveToLastLineStart());
       gQueue.push(new moveToMiddleLineStart());
       gQueue.push(new moveToMiddleLineEnd());
       gQueue.push(new moveToFirstLineStart());
       gQueue.push(new moveToFirstLineEnd());
--- a/accessible/tests/mochitest/text/test_multiline.html
+++ b/accessible/tests/mochitest/text/test_multiline.html
@@ -11,17 +11,17 @@
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../text.js"></script>
   <script type="application/javascript">
 
     function doTest()
     {
-      SimpleTest.expectAssertions(20);
+      SimpleTest.expectAssertions(5);
 
       // __o__n__e__w__o__r__d__\n
       //  0  1  2  3  4  5  6  7
       // __\n
       //  8
       // __t__w__o__ __w__o__r__d__s__\n
       //  9 10 11 12 13 14 15 16 17 18
 
@@ -109,52 +109,22 @@
       // BOUNDARY_LINE_START
       testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0, IDs);
       testTextBeforeOffset(8, BOUNDARY_LINE_START, "oneword\n", 0, 8, IDs);
       testTextBeforeOffset(9, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
       testTextBeforeOffset(18, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
       testTextBeforeOffset(19, BOUNDARY_LINE_START, "two words\n", 9, 19, IDs);
 
       // BOUNDARY_LINE_END
-      testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0,
-                           "div", kOk, kOk, kOk,
-                           "divbr", kOk, kOk, kOk,
-                           "editable", kOk, kOk, kOk,
-                           "editablebr", kOk, kOk, kOk,
-                           "textarea", kOk, kOk, kOk);
-      testTextBeforeOffset(7, BOUNDARY_LINE_END, "", 0, 0,
-                           "div", kOk, kTodo, kTodo,
-                           "divbr", kOk, kTodo, kTodo,
-                           "editable", kOk, kTodo, kTodo,
-                           "editablebr", kOk, kTodo, kTodo,
-                           "textarea", kOk, kTodo, kTodo);
-      testTextBeforeOffset(8, BOUNDARY_LINE_END, "oneword", 0, 7,
-                           "div", kTodo, kTodo, kTodo,
-                           "divbr", kTodo, kTodo, kTodo,
-                           "editable", kTodo, kTodo, kTodo,
-                           "editablebr", kTodo, kTodo, kTodo,
-                           "textarea", kTodo, kTodo, kTodo);
-      testTextBeforeOffset(9, BOUNDARY_LINE_END, "\n", 7, 8,
-                           "div", kOk, kTodo, kTodo,
-                           "divbr", kOk, kTodo, kTodo,
-                           "editable", kOk, kTodo, kTodo,
-                           "editablebr", kOk, kTodo, kTodo,
-                           "textarea", kOk, kTodo, kTodo);
-      testTextBeforeOffset(18, BOUNDARY_LINE_END, "\n", 7, 8,
-                           "div", kTodo, kTodo, kTodo,
-                           "divbr", kTodo, kTodo, kTodo,
-                           "editable", kTodo, kTodo, kTodo,
-                           "editablebr", kTodo, kTodo, kTodo,
-                           "textarea", kTodo, kTodo, kTodo);
-      testTextBeforeOffset(19, BOUNDARY_LINE_END, "\ntwo words", 8, 18,
-                           "div", kTodo, kTodo, kTodo,
-                           "divbr", kTodo, kTodo, kTodo,
-                           "editable", kTodo, kTodo, kTodo,
-                           "editablebr", kTodo, kTodo, kTodo,
-                           "textarea", kTodo, kTodo, kTodo);
+      testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0, IDs);
+      testTextBeforeOffset(7, BOUNDARY_LINE_END, "", 0, 0, IDs);
+      testTextBeforeOffset(8, BOUNDARY_LINE_END, "oneword", 0, 7, IDs);
+      testTextBeforeOffset(9, BOUNDARY_LINE_END, "\n", 7, 8, IDs);
+      testTextBeforeOffset(18, BOUNDARY_LINE_END, "\n", 7, 8, IDs);
+      testTextBeforeOffset(19, BOUNDARY_LINE_END, "\ntwo words", 8, 18, IDs);
 
       ////////////////////////////////////////////////////////////////////////
       // getTextAtOffset
 
       // BOUNDARY_LINE_START
       testTextAtOffset(0, BOUNDARY_LINE_START, "oneword\n", 0, 8, IDs);
       testTextAtOffset(7, BOUNDARY_LINE_START, "oneword\n", 0, 8, IDs);
       testTextAtOffset(8, BOUNDARY_LINE_START, "\n", 8, 9, IDs);
--- a/accessible/tests/mochitest/text/test_singleline.html
+++ b/accessible/tests/mochitest/text/test_singleline.html
@@ -7,19 +7,19 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="../common.js"></script>
   <script type="application/javascript"
           src="../text.js"></script>
   <script type="application/javascript">
     if (navigator.platform.startsWith("Mac")) {
-      SimpleTest.expectAssertions(0, 8);
+      SimpleTest.expectAssertions(0, 4);
     } else {
-      SimpleTest.expectAssertions(8);
+      SimpleTest.expectAssertions(4);
     }
 
     function doTest()
     {
       // __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
       //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 
       ////////////////////////////////////////////////////////////////////////
@@ -79,31 +79,19 @@
 
       // BOUNDARY_LINE_START
       testTextBeforeOffset(0, BOUNDARY_LINE_START, "", 0, 0, IDs);
       testTextBeforeOffset(1, BOUNDARY_LINE_START, "", 0, 0, IDs);
       testTextBeforeOffset(14, BOUNDARY_LINE_START, "", 0, 0, IDs);
       testTextBeforeOffset(15, BOUNDARY_LINE_START, "", 0, 0, IDs);
 
       // BOUNDARY_LINE_END
-      testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0,
-                           "input", kOk, kOk, kOk,
-                           "div", kOk, kOk, kOk,
-                           "editable", kOk, kOk, kOk,
-                           "textarea", kOk, kOk, kOk);
-      testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0,
-                           "input", kTodo, kOk, kTodo,
-                           "div", kTodo, kOk, kTodo,
-                           "editable", kTodo, kOk, kTodo,
-                           "textarea", kTodo, kOk, kTodo);
-      testTextBeforeOffset(14, BOUNDARY_LINE_END, "", 0, 0,
-                           "input", kTodo, kOk, kTodo,
-                           "div", kTodo, kOk, kTodo,
-                           "editable", kTodo, kOk, kTodo,
-                           "textarea", kTodo, kOk, kTodo);
+      testTextBeforeOffset(0, BOUNDARY_LINE_END, "", 0, 0, IDs);
+      testTextBeforeOffset(1, BOUNDARY_LINE_END, "", 0, 0, IDs);
+      testTextBeforeOffset(14, BOUNDARY_LINE_END, "", 0, 0, IDs);
       testTextBeforeOffset(15, BOUNDARY_LINE_END, "", 0, 0, IDs);
 
       ////////////////////////////////////////////////////////////////////////
       // getTextAtOffset
 
       IDs = [ "input", "div", "editable", "textarea" ];
       regularIDs = [ "input", "div", "editable" ];
 
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1372700880000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1373408730000">
   <emItems>
       <emItem  blockID="i350" id="sqlmoz@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
@@ -214,20 +214,16 @@
       <emItem  blockID="i18" id="msntoolbar@msn.com">
                         <versionRange  minVersion=" " maxVersion="6.*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i228" id="crossriderapp5060@crossrider.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i386" id="7lffxtbr@CursorMania_7l.com">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
                         <versionRange  minVersion="1.2" maxVersion="1.2">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="3.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
       <emItem  blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com">
@@ -280,20 +276,16 @@
       <emItem  blockID="i256" id="/^[0-9a-f]+@[0-9a-f]+\.info/">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i370" id="happylyrics@hpyproductions.net">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i388" id="5mffxtbr@MyFunCards_5m.com">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i396" id="/@(ft|putlocker|clickmovie|m2k|sharerepo|smarter-?)downloader\.com$/">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i22" id="ShopperReports@ShopperReports.com">
                         <versionRange  minVersion="3.1.22.0" maxVersion="3.1.22.0">
                     </versionRange>
                   </emItem>
@@ -386,16 +378,20 @@
       <emItem  blockID="i394" id="{7D4F1959-3F72-49d5-8E59-F02F8AA6815D}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i344" id="lrcsTube@hansanddeta.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i426" id="addlyrics@addlyrics.net">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i404" id="{a9bb9fa0-4122-4c75-bd9a-bc27db3f9155}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i83" id="flash@adobee.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
@@ -571,20 +567,16 @@
       <emItem  blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i306" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE10}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i384" id="7lffxtbr@PopularScreensavers_7l.com">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i165" id="{EEF73632-A085-4fd3-A778-ECD82C8CB297}">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i60" id="youtb3@youtb3.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
--- a/browser/config/tooltool-manifests/linux32/clang.manifest
+++ b/browser/config/tooltool-manifests/linux32/clang.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r170890"
+"clang_version": "r183744"
 }, 
 {
-"filename": "setup.sh", 
+"size": 47, 
+"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", 
 "algorithm": "sha512", 
-"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", 
-"size": 47
+"filename": "setup.sh"
 }, 
 {
-"filename": "clang.tar.bz2", 
+"size": 70206124, 
+"digest": "a6b8046bd9485f9387dcb1c14b8d442822f02b1caa61b653e8b6cfd96906deadfb4b29809f2cd2b71f919b321d97dd2ebec6020c15f6d485f1641c0f710a762f", 
 "algorithm": "sha512", 
-"digest": "0bcfc19f05cc0f042befb3823c7ecce9ba411b152921aa29e97e7adc846e0258fd7da521b1620cb1e61a19d2fcac9b60e6d613c922b6c153e01b9b0766651d09", 
-"size": 62708281
+"filename": "clang.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/linux64/clang.manifest
+++ b/browser/config/tooltool-manifests/linux64/clang.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r170890"
-},
+"clang_version": "r183744"
+}, 
 {
-"filename": "setup.sh",
-"algorithm": "sha512",
-"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
-"size": 47
-},
+"size": 47, 
+"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", 
+"algorithm": "sha512", 
+"filename": "setup.sh"
+}, 
 {
-"filename": "clang.tar.bz2",
-"algorithm": "sha512",
-"digest": "e14ccefd965372a57c540647b2b99e21a4aa82f81a8b9a9e18dac7cba4c3436181bef0dfab8c51bcb5c343f504a693fdcfbe7d609f10291b5dd65ab059979d29",
-"size": 63034761
+"size": 70350828, 
+"digest": "6cd04e8ec44c6fef159349c22bd0476891e4a2d46479f9586283eaf3305e42f79c720d40dfec0e78d8899c1651189b12e285de60862ffd0612b0dac7a0c336c6", 
+"algorithm": "sha512", 
+"filename": "clang.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/macosx64/releng.manifest
+++ b/browser/config/tooltool-manifests/macosx64/releng.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r170890"
-},
+"clang_version": "r183744"
+}, 
 {
-"size": 47,
-"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
-"algorithm": "sha512",
+"size": 47, 
+"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", 
+"algorithm": "sha512", 
 "filename": "setup.sh"
-},
+}, 
 {
-"size": 56126352,
-"digest": "e156e2a39abd5bf272ee30748a6825f22ddd27565b097c66662a2a6f2e9892bc5b4bf30a3552dffbe867dbfc39e7ee086e0b2cd7935f6ea216c0cf936178a88f",
-"algorithm": "sha512",
+"size": 59602619, 
+"digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b", 
+"algorithm": "sha512", 
 "filename": "clang.tar.bz2"
 }
 ]
--- a/browser/metro/base/content/ContentAreaObserver.js
+++ b/browser/metro/base/content/ContentAreaObserver.js
@@ -1,16 +1,16 @@
 /* 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/. */
 
  /*
   * ContentAreaObserver manages tracking the viewable area within the browser.
   * It also handles certain tasks like positioning of input elements within
-  * content when the viewable area changes. 
+  * content when the viewable area changes.
   *
   * ContentAreaObserver creates styles that content can apply and also fires
   * events when things change. The 'width' and 'height' properties of the
   * styles are updated whenever various parts of the UI are resized.
   *
   *  styles: window-width, window-height
   *  events: SizeChanged
   *
@@ -166,23 +166,20 @@ var ContentAreaObserver = {
     // these are hidden.
     BrowserUI._updateButtons();
 
     this._disatchBrowserEvent("ViewableSizeChanged");
   },
 
   updateAppBarPosition: function updateAppBarPosition(aForceDown) {
     // Adjust the app and find bar position above the soft keyboard
-    let navBar = document.getElementById("navbar");
-    let contextAppBar = document.getElementById("contextappbar");
-    let findBar = document.getElementById("content-navigator");
     let keyboardHeight = aForceDown ? 0 : MetroUtils.keyboardHeight;
-    navBar.style.bottom = keyboardHeight + "px";
-    contextAppBar.style.bottom = keyboardHeight + "px";
-    findBar.style.bottom = keyboardHeight + "px";
+    Elements.navbar.style.bottom = keyboardHeight + "px";
+    Elements.contextappbar.style.bottom = keyboardHeight + "px";
+    Elements.findbar.style.bottom = keyboardHeight + "px";
   },
 
   /*
    * Called by BrowserUI right before we blur the nav bar edit. We use
    * this to get a head start on shuffling app bars around before the
    * soft keyboard transitions down.
    */
   navBarWillBlur: function navBarWillBlur() {
--- a/browser/metro/base/content/TopSites.js
+++ b/browser/metro/base/content/TopSites.js
@@ -288,23 +288,25 @@ TopSitesView.prototype = {
   updateTile: function(aTileNode, aSite, aArrangeGrid) {
     PlacesUtils.favicons.getFaviconURLForPage(Util.makeURI(aSite.url), function(iconURLfromSiteURL) {
       if (!iconURLfromSiteURL) {
         return;
       }
       aTileNode.iconSrc = iconURLfromSiteURL.spec;
       let faviconURL = (PlacesUtils.favicons.getFaviconLinkForIcon(iconURLfromSiteURL)).spec;
       let xpFaviconURI = Util.makeURI(faviconURL.replace("moz-anno:favicon:",""));
-      ColorUtils.getForegroundAndBackgroundIconColors(xpFaviconURI, function(foreground, background) {
-        aTileNode.style.color = foreground; //color text
+      let successAction = function(foreground, background) {
+	      aTileNode.style.color = foreground; //color text
         aTileNode.setAttribute("customColor", background);
         if (aTileNode.refresh) {
           aTileNode.refresh();
         }
-      });
+      };
+      let failureAction = function() {};
+      ColorUtils.getForegroundAndBackgroundIconColors(xpFaviconURI, successAction, failureAction);
     });
 
     if (this._useThumbs) {
       aSite.backgroundImage = 'url("'+PageThumbs.getThumbnailURL(aSite.url)+'")';
     } else {
       delete aSite.backgroundImage;
     }
     aSite.applyToTileNode(aTileNode);
--- a/browser/metro/base/content/bindings/browser.xml
+++ b/browser/metro/base/content/bindings/browser.xml
@@ -752,16 +752,17 @@
          ]]></body>
       </method>
 
       <field name="_active">false</field>
       <property name="active" onget="return this._active;">
         <setter><![CDATA[
           // Do not change displayport on local tabs!
           this._active = val;
+          this.docShellIsActive = this._active;
         ]]></setter>
       </property>
 
       <!-- Transform the viewport without updating the displayport. -->
       <method name="fuzzyZoom">
         <parameter name="scale"/>
         <parameter name="x"/>
         <parameter name="y"/>
--- a/browser/metro/base/content/bookmarks.js
+++ b/browser/metro/base/content/bookmarks.js
@@ -229,23 +229,25 @@ BookmarksView.prototype = {
     PlacesUtils.favicons.getFaviconURLForPage(aUri, this._gotIcon.bind(this, aBookmarkId, aItem));
   },
 
   _gotIcon: function bv__gotIcon(aBookmarkId, aItem, aIconUri) {
     aItem.setAttribute("iconURI", aIconUri ? aIconUri.spec : "");
     if (!aIconUri) {
       return;
     }
-    ColorUtils.getForegroundAndBackgroundIconColors(aIconUri, function(foregroundColor, backgroundColor) {
+    let successAction = function(foregroundColor, backgroundColor) {
       aItem.style.color = foregroundColor; //color text
       aItem.setAttribute("customColor", backgroundColor); //set background
       if (aItem.refresh) {
         aItem.refresh();
       }
-    });
+    };
+    let failureAction = function() {};
+    ColorUtils.getForegroundAndBackgroundIconColors(aIconUri, successAction, failureAction);
   },
 
   _sendNeedsRefresh: function bv__sendNeedsRefresh(){
     // Event sent when all view instances need to refresh.
     let event = document.createEvent("Events");
     event.initEvent("BookmarksNeedsRefresh", true, false);
     window.dispatchEvent(event);
   },
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -38,20 +38,20 @@ let Elements = {};
   ["controls",           "browser-controls"],
   ["panelUI",            "panel-container"],
   ["startUI",            "start-container"],
   ["tray",               "tray"],
   ["toolbar",            "toolbar"],
   ["browsers",           "browsers"],
   ["navbar",             "navbar"],
   ["contextappbar",      "contextappbar"],
+  ["findbar",            "findbar"],
   ["contentViewport",    "content-viewport"],
   ["progress",           "progress-control"],
   ["progressContainer",  "progress-container"],
-  ["contentNavigator",   "content-navigator"],
 ].forEach(function (aElementGlobal) {
   let [name, id] = aElementGlobal;
   XPCOMUtils.defineLazyGetter(Elements, name, function() {
     return document.getElementById(id);
   });
 });
 
 /**
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -245,25 +245,16 @@
       </stack>
     </vbox>
 
     <html:div id="overlay-back" class="overlay-button"
               observes="cmd_back"></html:div>
     <html:div id="overlay-plus" class="overlay-button"
               observes="cmd_back"></html:div>
 
-    <!-- popup for content navigator helper -->
-    <appbar id="content-navigator" class="window-width content-navigator-box" orient="horizontal" pack="start">
-      <textbox id="find-helper-textbox" class="search-bar content-navigator-item" oncommand="FindHelperUI.search(this.value)" oninput="FindHelperUI.updateCommands(this.value);" type="search"/>
-      <button class="content-navigator-item previous-button" command="cmd_findPrevious"/>
-      <button class="content-navigator-item next-button" command="cmd_findNext"/>
-      <spacer flex="1"/>
-      <button class="content-navigator-item close-button" command="cmd_findClose"/>
-    </appbar>
-
     <!-- Navbar -->
     <appbar id="navbar" mousethrough="never" observes="bcast_windowState">
       <hbox id="progress-container" layer="true">
         <hbox id="progress-control" />
       </hbox>
 
       <!-- Main Toolbar -->
       <toolbar id="toolbar" observes="bcast_windowState" flex="1">
@@ -351,16 +342,25 @@
             </hbox>
           </vbox>
 
           <richlistbox id="console-box" class="panel-list console-box" flex="1" onkeypress="ConsolePanelView.onConsoleBoxKeyPress(event)" oncontextmenu="ConsolePanelView.onContextMenu(event);"/>
         </vbox>
       </deck>
     </vbox>
 
+    <!-- Find bar -->
+    <appbar id="findbar" class="window-width findbar-box" orient="horizontal" pack="start">
+      <textbox id="findbar-textbox" class="search-bar findbar-item" oncommand="FindHelperUI.search(this.value)" oninput="FindHelperUI.updateCommands(this.value);" type="search"/>
+      <button class="findbar-item previous-button" command="cmd_findPrevious"/>
+      <button class="findbar-item next-button" command="cmd_findNext"/>
+      <spacer flex="1"/>
+      <button class="findbar-item close-button" command="cmd_findClose"/>
+    </appbar>
+
     <!-- Context button bar -->
     <appbar id="contextappbar">
       <toolbar id="contextualactions-tray" flex="1">
         <toolbarbutton id="delete-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('delete')"/>
         <toolbarbutton id="restore-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('restore')"/>
         <toolbarbutton id="pin-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('pin')"/>
         <toolbarbutton id="unpin-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('unpin')"/>
         <toolbarbutton id="clear-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('clear')"/>
--- a/browser/metro/base/content/helperui/FindHelperUI.js
+++ b/browser/metro/base/content/helperui/FindHelperUI.js
@@ -37,18 +37,18 @@ var FindHelperUI = {
         this._textbox.removeAttribute("status");
       else
         this._textbox.setAttribute("status", val);
       this.updateCommands(this._textbox.value);
     }
   },
 
   init: function findHelperInit() {
-    this._textbox = document.getElementById("find-helper-textbox");
-    this._container = Elements.contentNavigator;
+    this._textbox = document.getElementById("findbar-textbox");
+    this._container = Elements.findbar;
 
     this._cmdPrevious = document.getElementById(this.commands.previous);
     this._cmdNext = document.getElementById(this.commands.next);
 
     this._textbox.addEventListener('keydown', this);
 
     // Listen for find assistant messages from content
     messageManager.addMessageListener("FindAssist:Show", this);
--- a/browser/metro/modules/colorUtils.jsm
+++ b/browser/metro/modules/colorUtils.jsm
@@ -9,28 +9,30 @@ const ColorAnalyzer = Components.classes
 
 this.EXPORTED_SYMBOLS = ["ColorUtils"];
 
 let ColorUtils = {
   /** Takes an icon and a success callback (who is expected to handle foreground color
    *  & background color as is desired) The first argument to the callback is
    * the foreground/contrast color, the second is the background/primary/dominant one
    */
-  getForegroundAndBackgroundIconColors: function getForegroundAndBackgroundIconColors(aIconURI, aSuccessCallback) {
+  getForegroundAndBackgroundIconColors: function getForegroundAndBackgroundIconColors(aIconURI, aSuccessCallback, aErrorCallback) {
     if (!aIconURI) {
       return;
     }
-
     let that = this;
     let wrappedIcon = aIconURI;
     ColorAnalyzer.findRepresentativeColor(wrappedIcon, function (success, color) {
-      let foregroundColor = that.bestTextColorForContrast(color);
-      let backgroundColor = that.convertDecimalToRgbColor(color);
-      // let the caller do whatever it is they need through the callback
-      aSuccessCallback(foregroundColor, backgroundColor);
+      if (!success) {
+        aErrorCallback();
+      } else {
+        let foregroundColor = that.bestTextColorForContrast(color);
+        let backgroundColor = that.convertDecimalToRgbColor(color);
+        aSuccessCallback(foregroundColor, backgroundColor);
+      }
     }, this);
   },
   /** returns the best color for text readability on top of aColor
    * return color is in rgb(r,g,b) format, suitable to csss
    * The color bightness algorithm is currently: http://www.w3.org/TR/AERT#color-contrast
    */
   bestTextColorForContrast: function bestTextColorForContrast(aColor) {
     let r = (aColor & 0xff0000) >> 16;
--- a/browser/metro/theme/platform.css
+++ b/browser/metro/theme/platform.css
@@ -660,100 +660,100 @@ arrowbox {
 
 .meta-section-title {
   font-size: @metro_font_large@;
   font-weight: 100;
 }
 
 /* Find bar ------------------------------------------------------------- */
 
-#content-navigator {
+#findbar {
   background-color: @metro_orange@;
   padding: 0;
   pointer-events: none;
 }
 
-#content-navigator > toolbar {
+#findbar > toolbar {
   min-height: @findbar_height@ !important;
 }
 
-#content-navigator > .previous-button,
-#content-navigator > .next-button,
-#content-navigator > .close-button {
+#findbar > .previous-button,
+#findbar > .next-button,
+#findbar > .close-button {
   list-style-image: url(chrome://browser/skin/images/appbar-icons.png);
   min-width: @touch_button_small@ !important; /* button size */
   min-height: @touch_button_small@ !important; /* button size */
   border: none !important;
   background-image: none !important;
   background-color: inherit !important;
   pointer-events: auto;
   -moz-user-focus: ignore !important;
   margin: 0 @margin_normal@ !important;
 }
 
-#content-navigator > .close-button {
+#findbar > .close-button {
   -moz-margin-start: 0;
   -moz-image-region: rect(0px, 480px, 40px, 440px);
 }
 
-#content-navigator > .close-button:hover {
+#findbar > .close-button:hover {
   -moz-image-region: rect(40px, 480px, 80px, 440px);
 }
 
-#content-navigator > .close-button:active {
+#findbar > .close-button:active {
   -moz-image-region: rect(80px, 480px, 120px, 440px);
 }
 
-#content-navigator > .previous-button {
+#findbar > .previous-button {
   -moz-margin-end: 0;
   -moz-image-region: rect(0px, 400px, 40px, 360px);
 }
 
-#content-navigator > .previous-button:hover {
+#findbar > .previous-button:hover {
   -moz-image-region: rect(40px, 400px, 80px, 360px);
 }
 
-#content-navigator > .previous-button:active{
+#findbar > .previous-button:active{
   -moz-image-region: rect(80px, 400px, 120px, 360px);
 }
 
-#content-navigator > .next-button {
+#findbar > .next-button {
   -moz-margin-start: 0;
   -moz-image-region: rect(0px, 440px, 40px, 400px);
 }
 
-#content-navigator > .next-button:hover {
+#findbar > .next-button:hover {
   -moz-image-region: rect(40px, 440px, 80px, 400px);
 }
 
-#content-navigator > .next-button:active {
+#findbar > .next-button:active {
   -moz-image-region: rect(80px, 440px, 120px, 400px);
 }
 
-#find-helper-textbox {
+#findbar-textbox {
   pointer-events: auto;
   -moz-margin-end: 0;
   border: none !important;
   width: 20em;
 }
 
 .textbox-search-icon {
   list-style-image: url("chrome://browser/skin/images/search-glass-30.png");
   -moz-image-region: auto;
 }
 
 /* Override the default box ordering and make the find textbox appear to the
    right of the icon */
-#find-helper-textbox input {
+#findbar-textbox input {
   -moz-box-ordinal-group: 2
 }
 
-#find-helper-textbox deck {
+#findbar-textbox deck {
   margin-right: @margin_normal@;
 }
 
-#find-helper-textbox[status="1"] { /* Ci.nsITypeAheadFind.FIND_NOTFOUND */
+#findbar-textbox[status="1"] { /* Ci.nsITypeAheadFind.FIND_NOTFOUND */
   background: rgb(255,200,200);
 }
 
-#find-helper-textbox:hover:active {
+#findbar-textbox:hover:active {
   background: #8db8d8;
 }
--- a/build/mobile/robocop/RobocopUtils.java.in
+++ b/build/mobile/robocop/RobocopUtils.java.in
@@ -7,17 +7,17 @@
 package @ANDROID_PACKAGE_NAME@;
 
 import android.app.Activity;
 
 import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 
 public final class RobocopUtils {
-    private static final int MAX_WAIT_MS = 3000;
+    private static final int MAX_WAIT_MS = 20000;
 
     private RobocopUtils() {}
 
     public static void runOnUiThreadSync(Activity activity, final Runnable runnable) {
         final SynchronousQueue syncQueue = new SynchronousQueue();
         activity.runOnUiThread(
             new Runnable() {
                 public void run() {
--- a/configure.in
+++ b/configure.in
@@ -4284,17 +4284,16 @@ LIBJPEG_TURBO_X86_ASM=
 LIBJPEG_TURBO_X64_ASM=
 LIBJPEG_TURBO_ARM_ASM=
 MOZ_PANGO=1
 MOZ_PERMISSIONS=1
 MOZ_PLACES=1
 MOZ_SOCIAL=1
 MOZ_PREF_EXTENSIONS=1
 MOZ_PROFILELOCKING=1
-MOZ_PSM=1
 MOZ_REFLOW_PERF=
 MOZ_SAFE_BROWSING=
 MOZ_HELP_VIEWER=
 MOZ_SPELLCHECK=1
 MOZ_ANDROID_OMTC=
 MOZ_ONLY_TOUCH_EVENTS=
 MOZ_TOOLKIT_SEARCH=1
 MOZ_UI_LOCALE=en-US
@@ -5280,24 +5279,16 @@ fi
 dnl ========================================================
 dnl = Enable NFC permission on Android
 dnl ========================================================
 if test -n "$MOZ_ANDROID_BEAM"; then
     AC_DEFINE(MOZ_ANDROID_BEAM)
 fi
 
 dnl ========================================================
-dnl = Build Personal Security Manager
-dnl ========================================================
-MOZ_ARG_DISABLE_BOOL(crypto,
-[  --disable-crypto        Disable crypto support (Personal Security Manager)],
-    MOZ_PSM=,
-    MOZ_PSM=1 )
-
-dnl ========================================================
 dnl = JS Debugger XPCOM component (js/jsd)
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(jsd,
 [  --disable-jsd           Disable JavaScript debug library],
     MOZ_JSDEBUGGER=,
     MOZ_JSDEBUGGER=1)
 
 
@@ -8141,17 +8132,24 @@ AC_SUBST(GLIB_CFLAGS)
 AC_SUBST(GLIB_LIBS)
 AC_SUBST(GLIB_GMODULE_LIBS)
 
 dnl ========================================================
 dnl Graphics checks.
 dnl ========================================================
 
 if test "${OS_TARGET}" = "WINNT" -o "${OS_ARCH}" = "Darwin" -o "${MOZ_WIDGET_TOOLKIT}" = "android" -o "${MOZ_WIDGET_TOOLKIT}" = "gtk2"; then
-MOZ_ENABLE_SKIA=1
+    case "${target_cpu}" in
+    i*86*|x86_64|arm)
+        MOZ_ENABLE_SKIA=1
+        ;;
+    *)
+        MOZ_ENABLE_SKIA=
+        ;;
+    esac
 else
 MOZ_ENABLE_SKIA=
 fi
 
 MOZ_ARG_ENABLE_BOOL(skia,
 [  --enable-skia   Enable use of Skia],
 MOZ_ENABLE_SKIA=1,
 MOZ_ENABLE_SKIA=)
@@ -8628,17 +8626,16 @@ AC_SUBST(FILTER)
 AC_SUBST(BIN_FLAGS)
 AC_SUBST(MOZ_WIDGET_TOOLKIT)
 AC_SUBST(MOZ_UPDATE_XTERM)
 AC_SUBST(MOZ_PLATFORM_MAEMO)
 AC_SUBST(MOZ_AUTH_EXTENSION)
 AC_SUBST(MOZ_PERMISSIONS)
 AC_SUBST(MOZ_PREF_EXTENSIONS)
 AC_SUBST(MOZ_JS_LIBS)
-AC_SUBST(MOZ_PSM)
 AC_SUBST(MOZ_DEBUG)
 AC_SUBST(MOZ_DEBUG_SYMBOLS)
 AC_SUBST(MOZ_DEBUG_ENABLE_DEFS)
 AC_SUBST(MOZ_DEBUG_DISABLE_DEFS)
 AC_SUBST(MOZ_DEBUG_FLAGS)
 AC_SUBST(MOZ_DEBUG_LDFLAGS)
 AC_SUBST(WARNINGS_AS_ERRORS)
 AC_SUBST(MOZ_EXTENSIONS)
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1569,19 +1569,19 @@ WebGLContext::DrawArrays(GLenum mode, We
 
     MakeContextCurrent();
 
     if (mBoundFramebuffer) {
         if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
             return ErrorInvalidFramebufferOperation("drawArrays: incomplete framebuffer");
     }
 
+    if (!DoFakeVertexAttrib0(checked_firstPlusCount.value()))
+        return;
     BindFakeBlackTextures();
-    if (!DoFakeVertexAttrib0(checked_firstPlusCount.value()))
-        return;
 
     SetupContextLossTimer();
     gl->fDrawArrays(mode, first, count);
 
     UndoFakeVertexAttrib0();
     UnbindFakeBlackTextures();
 
     if (!mBoundFramebuffer) {
@@ -1679,19 +1679,19 @@ WebGLContext::DrawElements(WebGLenum mod
 
     MakeContextCurrent();
 
     if (mBoundFramebuffer) {
         if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
             return ErrorInvalidFramebufferOperation("drawElements: incomplete framebuffer");
     }
 
+    if (!DoFakeVertexAttrib0(maxAllowedCount))
+        return;
     BindFakeBlackTextures();
-    if (!DoFakeVertexAttrib0(maxAllowedCount))
-        return;
 
     SetupContextLossTimer();
     gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
 
     UndoFakeVertexAttrib0();
     UnbindFakeBlackTextures();
 
     if (!mBoundFramebuffer) {
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -63,18 +63,16 @@ MOCHITEST_FILES = \
 		seek11.js \
 		seek12.js \
 		seek13.js \
 		seekLies.sjs \
 		test_access_control.html \
 		test_audio1.html \
 		test_audio2.html \
 		test_autoplay.html \
-		test_bug465498.html \
-		test_bug493187.html \
 		test_bug495145.html \
 		test_bug495300.html \
 		test_bug654550.html \
 		test_bug686942.html \
 		test_can_play_type.html \
 		test_can_play_type_mpeg.html \
 		test_closing_connections.html \
 		test_constants.html \
@@ -179,16 +177,22 @@ endif
 #   test_videoDocumentTitle.html
 # Bug 493692:
 #   test_preload_suspend.html
 # Bug 567954 and Bug 574586:
 #   test_mixed_principals.html
 # Disabled since we don't play Wave files standalone, for now
 #		test_audioDocumentTitle.html
 
+# The below tests are disabled due to frequent timeouts.
+# Bug 832768 and Bug 864682:
+#		test_bug465498.html
+# Bug 707777:
+#		test_bug493187.html
+
 # sample files
 MOCHITEST_FILES += \
 		320x240.ogv \
 		448636.ogv \
 		audio-overhang.ogg \
 		audio-gaps.ogg \
 		badtags.ogg \
 		beta-phrasebook.ogg \
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -349,17 +349,16 @@ public:
 
     uint32_t currentOutSampleRate, currentInSampleRate;
     if (ShouldResample(aStream->SampleRate())) {
       SpeexResamplerState* resampler = Resampler(aStream, aChannels);
       speex_resampler_get_rate(resampler, &currentInSampleRate, &currentOutSampleRate);
       uint32_t finalSampleRate = ComputeFinalOutSampleRate(aStream->SampleRate());
       if (currentOutSampleRate != finalSampleRate) {
         speex_resampler_set_rate(resampler, currentInSampleRate, finalSampleRate);
-        speex_resampler_skip_zeros(mResampler);
       }
     }
   }
 
   virtual void ProduceAudioBlock(AudioNodeStream* aStream,
                                  const AudioChunk& aInput,
                                  AudioChunk* aOutput,
                                  bool* aFinished)
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -9118,18 +9118,18 @@ class CGExampleRoot(CGThing):
                               [ "nsWrapperCache.h",
                                 "nsCycleCollectionParticipant.h",
                                 "mozilla/Attributes.h",
                                 "mozilla/ErrorResult.h" ],
                               [ "%s.h" % interfaceName,
                                 "mozilla/dom/%sBinding.h" % interfaceName,
                                 "nsContentUtils.h" ], "", self.root);
 
-        # In the header, #pragma once before everything
-        self.root = CGWrapper(self.root, declarePre="#pragma once\n\n")
+        # And now some include guards
+        self.root = CGIncludeGuard(interfaceName, self.root)
 
         # And our license block comes before everything else
         self.root = CGWrapper(self.root, pre="""/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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/. */
 
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -1888,17 +1888,19 @@ public:
     if (NS_FAILED(rv)) {
       mFile->mFile->Remove(false);
 
       nsCOMPtr<PostErrorEvent> event = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_UNKNOWN);
       NS_DispatchToMainThread(event);
       return NS_OK;
     }
 
-    nsCOMPtr<PostResultEvent> event = new PostResultEvent(mRequest.forget(), mFile->mPath);
+    nsString compositePath;
+    mFile->GetCompositePath(compositePath);
+    nsCOMPtr<PostResultEvent> event = new PostResultEvent(mRequest.forget(), compositePath);
     NS_DispatchToMainThread(event);
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
@@ -1967,17 +1969,19 @@ public:
 
     nsRefPtr<nsRunnable> r;
     bool check = false;
     mFile->mFile->Exists(&check);
     if (check) {
       r = new PostErrorEvent(mRequest.forget(), POST_ERROR_EVENT_FILE_DOES_NOT_EXIST);
     }
     else {
-      r = new PostResultEvent(mRequest.forget(), mFile->mPath);
+      nsString compositePath;
+      mFile->GetCompositePath(compositePath);
+      r = new PostResultEvent(mRequest.forget(), compositePath);
     }
     NS_DispatchToMainThread(r);
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
--- a/dom/telephony/test/marionette/test_outgoing_already_held.js
+++ b/dom/telephony/test/marionette/test_outgoing_already_held.js
@@ -73,24 +73,36 @@ function simulateIncoming() {
     incomingCall = event.call;
     ok(incomingCall);
     is(incomingCall.number, inNumber);
     is(incomingCall.state, "incoming");
 
     is(telephony.calls.length, 1);
     is(telephony.calls[0], incomingCall);
 
-    runEmulatorCmd("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      is(result[1], "OK");
-      answerIncoming();
+    // Wait for emulator to catch up before continuing
+    waitFor(verifyCallList,function() {
+      return(rcvdEmulatorCallback);
     });
   };
-  runEmulatorCmd("gsm call " + inNumber);
+
+  let rcvdEmulatorCallback = false;
+  runEmulatorCmd("gsm call " + inNumber, function(result) {
+    is(result[0], "OK", "emulator callback");
+    rcvdEmulatorCallback = true;
+  });
+}
+
+function verifyCallList(){
+  runEmulatorCmd("gsm list", function(result) {
+    log("Call list is now: " + result);
+    is(result[0], "inbound from " + inNumber + " : incoming");
+    is(result[1], "OK");
+    answerIncoming();
+  });
 }
 
 function answerIncoming() {
   log("Answering the incoming call.");
 
   let gotConnecting = false;
   incomingCall.onconnecting = function onconnectingIn(event) { 
     log("Received 'connecting' call event for original (incoming) call.");
@@ -185,25 +197,37 @@ function answerOutgoing() {
   // We get no "connecting" event when the remote party answers the call.
   outgoingCall.onconnected = function onconnectedOut(event) {
     log("Received 'connected' call event for outgoing/2nd call.");
     is(outgoingCall, event.call);
     is(outgoingCall.state, "connected");
 
     is(outgoingCall, telephony.active);
 
-    runEmulatorCmd("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      is(result[1], "outbound to  " + outNumber + " : active");
-      is(result[2], "OK");
-      hangUpIncoming();
+    // Wait for emulator to catch up before continuing
+    waitFor(checkCallList,function() {
+      return(rcvdEmulatorCallback);
     });
   };
-  runEmulatorCmd("gsm accept " + outNumber);
+
+  let rcvdEmulatorCallback = false;
+  runEmulatorCmd("gsm accept " + outNumber, function(result) {
+    is(result[0], "OK", "emulator callback");
+    rcvdEmulatorCallback = true;
+  });
+}
+
+function checkCallList(){
+  runEmulatorCmd("gsm list", function(result) {
+    log("Call list is now: " + result);
+    is(result[0], "inbound from " + inNumber + " : held");
+    is(result[1], "outbound to  " + outNumber + " : active");
+    is(result[2], "OK");
+    hangUpIncoming();
+  });
 }
 
 // Hang-up the original incoming call, which is now held
 function hangUpIncoming() {
   log("Hanging up the original incoming (now held) call.");
 
   let gotDisconnecting = false;
   incomingCall.ondisconnecting = function ondisconnectingIn(event) {
--- a/dom/telephony/test/marionette/test_outgoing_reject.js
+++ b/dom/telephony/test/marionette/test_outgoing_reject.js
@@ -96,23 +96,35 @@ function reject() {
   outgoing.ondisconnected = function ondisconnected(event) {
     log("Received 'disconnected' call event.");
     is(outgoing, event.call);
     is(outgoing.state, "disconnected");
 
     is(telephony.active, null);
     is(telephony.calls.length, 0);
 
-    runEmulatorCmd("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "OK");
-      cleanUp();
+    // Wait for emulator to catch up before continuing
+    waitFor(verifyCallList,function() {
+      return(rcvdEmulatorCallback);
     });
   };
-  runEmulatorCmd("gsm cancel " + number);
+
+  let rcvdEmulatorCallback = false;
+  runEmulatorCmd("gsm cancel " + number, function(result) {
+    is(result[0], "OK", "emulator callback");
+    rcvdEmulatorCallback = true;
+  });
 };
 
+function verifyCallList(){
+  runEmulatorCmd("gsm list", function(result) {
+    log("Call list is now: " + result);
+    is(result[0], "OK");
+    cleanUp();
+  });
+}
+
 function cleanUp() {
   SpecialPowers.removePermission("telephony", document);
   finish();
 }
 
 getExistingCalls();
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -834,16 +834,18 @@ public:
 
   SurfaceFormat GetFormat() { return mFormat; }
 
   /* Tries to get a native surface for a DrawTarget, this may fail if the
    * draw target cannot convert to this surface type.
    */
   virtual void *GetNativeSurface(NativeSurfaceType aType) { return NULL; }
 
+  virtual bool IsDualDrawTarget() { return false; }
+
   void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
     mUserData.Add(key, userData, destroy);
   }
   void *GetUserData(UserDataKey *key) {
     return mUserData.Get(key);
   }
 
   /* Within this rectangle all pixels will be opaque by the time the result of
@@ -1007,21 +1009,38 @@ private:
  * DrawTargetCG. This is used for drawing themed widgets.
  *
  * Callers should check the cg member after constructing the object
  * to see if it succeeded. The DrawTarget should not be used while
  * the context is borrowed. */
 class BorrowedCGContext
 {
 public:
-  BorrowedCGContext(DrawTarget *aDT) : mDT(aDT)
+  BorrowedCGContext()
+    : cg(nullptr)
+    , mDT(nullptr)
+  { }
+
+  BorrowedCGContext(DrawTarget *aDT)
+    : mDT(aDT)
   {
     cg = BorrowCGContextFromDrawTarget(aDT);
   }
 
+  // We can optionally Init after construction in
+  // case we don't know what the DT will be at construction
+  // time.
+  CGContextRef Init(DrawTarget *aDT)
+  {
+    MOZ_ASSERT(!mDT, "Can't initialize twice!");
+    mDT = aDT;
+    cg = BorrowCGContextFromDrawTarget(aDT);
+    return cg;
+  }
+
   // The caller needs to call Finish if cg is non-null when
   // they are done with the context. This is currently explicit
   // instead of happening implicitly in the destructor to make
   // what's happening in the caller more clear. It also
   // let's you resume using the DrawTarget in the same scope.
   void Finish()
   {
     if (cg) {
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -282,63 +282,30 @@ DrawTargetCG::DrawSurface(SourceSurface 
     image = subimage;
   }
 
   CGContextScaleCTM(cg, 1, -1);
 
   CGRect flippedRect = CGRectMake(aDest.x, -(aDest.y + aDest.height),
                                   aDest.width, aDest.height);
 
-  //XXX: we should implement this for patterns too
   if (aSurfOptions.mFilter == FILTER_POINT)
     CGContextSetInterpolationQuality(cg, kCGInterpolationNone);
+  else
+    CGContextSetInterpolationQuality(cg, kCGInterpolationLow);
 
   CGContextDrawImage(cg, flippedRect, image);
 
   fixer.Fix(mCg);
 
   CGContextRestoreGState(mCg);
 
   CGImageRelease(subimage);
 }
 
-void
-DrawTargetCG::MaskSurface(const Pattern &aSource,
-                          SourceSurface *aMask,
-                          Point aOffset,
-                          const DrawOptions &aDrawOptions)
-{
-  MarkChanged();
-
-  CGImageRef image;
-  CGContextSaveGState(mCg);
-
-  CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
-  UnboundnessFixer fixer;
-  CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
-  CGContextSetAlpha(cg, aDrawOptions.mAlpha);
-
-  CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
-  image = GetImageFromSourceSurface(aMask);
-
-  CGContextScaleCTM(cg, 1, -1);
-
-  IntSize size = aMask->GetSize();
-  CGContextClipToMask(cg, CGRectMake(aOffset.x, -(aOffset.y + size.height), size.width, size.height), image);
-
-  CGContextScaleCTM(cg, 1, -1);
-
-  FillRect(Rect(aOffset.x, aOffset.y, size.width, size.height), aSource, aDrawOptions);
-
-  fixer.Fix(mCg);
-
-  CGContextRestoreGState(mCg);
-
-}
-
 static CGColorRef ColorToCGColor(CGColorSpaceRef aColorSpace, const Color& aColor)
 {
   CGFloat components[4] = {aColor.r, aColor.g, aColor.b, aColor.a};
   return CGColorCreate(aColorSpace, components);
 }
 
 class GradientStopsCG : public GradientStops
 {
@@ -512,16 +479,21 @@ SetFillFromPattern(CGContextRef cg, CGCo
   } else if (aPattern.GetType() == PATTERN_SURFACE) {
 
     CGColorSpaceRef patternSpace;
     patternSpace = CGColorSpaceCreatePattern (nullptr);
     CGContextSetFillColorSpace(cg, patternSpace);
     CGColorSpaceRelease(patternSpace);
 
     CGPatternRef pattern = CreateCGPattern(aPattern, CGContextGetCTM(cg));
+    const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
+    if (pat.mFilter == FILTER_POINT)
+      CGContextSetInterpolationQuality(cg, kCGInterpolationNone);
+    else
+      CGContextSetInterpolationQuality(cg, kCGInterpolationLow);
     CGFloat alpha = 1.;
     CGContextSetFillPattern(cg, pattern, &alpha);
     CGPatternRelease(pattern);
   }
 }
 
 static void
 SetStrokeFromPattern(CGContextRef cg, CGColorSpaceRef aColorSpace, const Pattern &aPattern)
@@ -535,23 +507,70 @@ SetStrokeFromPattern(CGContextRef cg, CG
     CGColorRelease(cgcolor);
   } else if (aPattern.GetType() == PATTERN_SURFACE) {
     CGColorSpaceRef patternSpace;
     patternSpace = CGColorSpaceCreatePattern (nullptr);
     CGContextSetStrokeColorSpace(cg, patternSpace);
     CGColorSpaceRelease(patternSpace);
 
     CGPatternRef pattern = CreateCGPattern(aPattern, CGContextGetCTM(cg));
+    const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
+    if (pat.mFilter == FILTER_POINT)
+      CGContextSetInterpolationQuality(cg, kCGInterpolationNone);
+    else
+      CGContextSetInterpolationQuality(cg, kCGInterpolationLow);
     CGFloat alpha = 1.;
     CGContextSetStrokePattern(cg, pattern, &alpha);
     CGPatternRelease(pattern);
   }
 
 }
 
+void
+DrawTargetCG::MaskSurface(const Pattern &aSource,
+                          SourceSurface *aMask,
+                          Point aOffset,
+                          const DrawOptions &aDrawOptions)
+{
+  MarkChanged();
+
+  CGImageRef image;
+  CGContextSaveGState(mCg);
+
+  CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
+  UnboundnessFixer fixer;
+  CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
+  CGContextSetAlpha(cg, aDrawOptions.mAlpha);
+
+  CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
+  image = GetImageFromSourceSurface(aMask);
+
+  // use a negative-y so that the mask image draws right ways up
+  CGContextScaleCTM(cg, 1, -1);
+
+  IntSize size = aMask->GetSize();
+
+  CGContextClipToMask(cg, CGRectMake(aOffset.x, -(aOffset.y + size.height), size.width, size.height), image);
+
+  CGContextScaleCTM(cg, 1, -1);
+  if (isGradient(aSource)) {
+    // we shouldn't need to clip to an additional rectangle
+    // as the cliping to the mask should be sufficient.
+    DrawGradient(cg, aSource);
+  } else {
+    SetFillFromPattern(cg, mColorSpace, aSource);
+    CGContextFillRect(cg, CGRectMake(aOffset.x, aOffset.y, size.width, size.height));
+  }
+
+  fixer.Fix(mCg);
+
+  CGContextRestoreGState(mCg);
+}
+
+
 
 void
 DrawTargetCG::FillRect(const Rect &aRect,
                         const Pattern &aPattern,
                         const DrawOptions &aDrawOptions)
 {
   MarkChanged();
 
@@ -622,32 +641,17 @@ DrawTargetCG::StrokeRect(const Rect &aRe
 
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(mCg, aDrawOptions.mAlpha);
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
 
-  // we don't need to set all of the stroke state because
-  // it doesn't apply when stroking rects
-  switch (aStrokeOptions.mLineJoin)
-  {
-    case JOIN_BEVEL:
-      CGContextSetLineJoin(cg, kCGLineJoinBevel);
-      break;
-    case JOIN_ROUND:
-      CGContextSetLineJoin(cg, kCGLineJoinRound);
-      break;
-    case JOIN_MITER:
-    case JOIN_MITER_OR_BEVEL:
-      CGContextSetLineJoin(cg, kCGLineJoinMiter);
-      break;
-  }
-  CGContextSetLineWidth(cg, aStrokeOptions.mLineWidth);
+  SetStrokeOptions(cg, aStrokeOptions);
 
   if (isGradient(aPattern)) {
     // There's no CGContextClipStrokeRect so we do it by hand
     CGContextBeginPath(cg);
     CGContextAddRect(cg, RectToCGRect(aRect));
     CGContextReplacePathWithStrokedPath(cg);
     //XXX: should we use EO clip here?
     CGContextClip(cg);
@@ -1021,16 +1025,17 @@ DrawTargetCG::Init(CGContextRef cgContex
   //XXX: handle SurfaceFormat
 
   //XXX: we'd be better off reusing the Colorspace across draw targets
   mColorSpace = CGColorSpaceCreateDeviceRGB();
 
   mSize = aSize;
 
   mCg = cgContext;
+  CGContextRetain(mCg);
 
   mData = nullptr;
 
   assert(mCg);
 
   // CGContext's default to have the origin at the bottom left.
   // However, currently the only use of this function is to construct a
   // DrawTargetCG around a CGContextRef from a cairo quartz surface which
@@ -1185,16 +1190,18 @@ BorrowedCGContext::BorrowCGContextFromDr
 
     // swap out the context
     CGContextRef cg = cgDT->mCg;
     cgDT->mCg = nullptr;
 
     // save the state to make it easier for callers to avoid mucking with things
     CGContextSaveGState(cg);
 
+    CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(cgDT->mTransform));
+
     return cg;
   }
   return nullptr;
 }
 
 void
 BorrowedCGContext::ReturnCGContextToDrawTarget(DrawTarget *aDT, CGContextRef cg)
 {
--- a/gfx/2d/DrawTargetDual.h
+++ b/gfx/2d/DrawTargetDual.h
@@ -126,16 +126,21 @@ public:
   {
     return mA->CreateGradientStops(aStops, aNumStops, aExtendMode);
   }
      
   virtual void *GetNativeSurface(NativeSurfaceType aType)
   {
     return nullptr;
   }
+
+  virtual bool IsDualDrawTarget()
+  {
+    return true;
+  }
      
 private:
   RefPtr<DrawTarget> mA;
   RefPtr<DrawTarget> mB;
 };
      
 }
 }
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -633,19 +633,27 @@ GLContext::InitWithPrefix(const char *pr
                 mNeedsTextureSizeChecks = true;
             } else if (mVendor == VendorNVIDIA) {
                 SInt32 major, minor;
                 OSErr err1 = ::Gestalt(gestaltSystemVersionMajor, &major);
                 OSErr err2 = ::Gestalt(gestaltSystemVersionMinor, &minor);
 
                 if (err1 != noErr || err2 != noErr ||
                     major < 10 || (major == 10 && minor < 8)) {
+                    // See bug 877949.
                     mMaxTextureSize = std::min(mMaxTextureSize, 4096);
-                    mMaxRenderbufferSize   = std::min(mMaxRenderbufferSize, 4096);
+                    mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
                 }
+                else {
+                    // See bug 879656.  8192 fails, 8191 works.
+                    mMaxTextureSize = std::min(mMaxTextureSize, 8191);
+                    mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
+                }
+                // Part of the bug 879656, but it also doesn't hurt the 877949
+                mNeedsTextureSizeChecks = true;
             }
         }
 #endif
 #ifdef MOZ_X11
         if (mWorkAroundDriverBugs &&
             mVendor == VendorNouveau) {
             // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
             mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
+#include "gfxPlatform.h"
 
 #include "nsRect.h"
 
 #include "cairo.h"
 #include <algorithm>
 
 #ifdef CAIRO_HAS_WIN32_SURFACE
 #include "gfxWindowsSurface.h"
@@ -238,34 +239,37 @@ gfxASurface::GetDeviceOffset() const
 }
 
 void
 gfxASurface::Flush() const
 {
     if (!mSurfaceValid)
         return;
     cairo_surface_flush(mSurface);
+    gfxPlatform::ClearSourceSurfaceForSurface(const_cast<gfxASurface*>(this));
 }
 
 void
 gfxASurface::MarkDirty()
 {
     if (!mSurfaceValid)
         return;
     cairo_surface_mark_dirty(mSurface);
+    gfxPlatform::ClearSourceSurfaceForSurface(this);
 }
 
 void
 gfxASurface::MarkDirty(const gfxRect& r)
 {
     if (!mSurfaceValid)
         return;
     cairo_surface_mark_dirty_rectangle(mSurface,
                                        (int) r.X(), (int) r.Y(),
                                        (int) r.Width(), (int) r.Height());
+    gfxPlatform::ClearSourceSurfaceForSurface(this);
 }
 
 void
 gfxASurface::SetData(const cairo_user_data_key_t *key,
                      void *user_data,
                      thebes_destroy_func_t destroy)
 {
     if (!mSurfaceValid)
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -596,16 +596,22 @@ void SourceSnapshotDetached(cairo_surfac
 #else
 void SourceSnapshotDetached(void *nullSurf)
 {
   gfxImageSurface* origSurf = static_cast<gfxImageSurface*>(nullSurf);
   origSurf->SetData(&kSourceSurface, NULL, NULL);
 }
 #endif
 
+void
+gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
+{
+  aSurface->SetData(&kSourceSurface, nullptr, nullptr);
+}
+
 RefPtr<SourceSurface>
 gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
 {
   void *userData = aSurface->GetData(&kSourceSurface);
 
   if (userData) {
     SourceSurfaceUserData *surf = static_cast<SourceSurfaceUserData*>(userData);
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -189,16 +189,18 @@ public:
      * The returned surface keeps a reference to aTarget, so it is OK to keep the
      * surface, even if aTarget changes.
      * aTarget should not keep a reference to the returned surface because that
      * will cause a cycle.
      */
     virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
       GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
 
+    static void ClearSourceSurfaceForSurface(gfxASurface *aSurface);
+
     virtual mozilla::TemporaryRef<mozilla::gfx::ScaledFont>
       GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
 
     /*
      * Cairo doesn't give us a way to create a surface pointing to a context
      * without marking it as copy on write. For canvas we want to create
      * a surface that points to what is currently being drawn by a canvas
      * without a copy thus we need to create a special case. This works on
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -66,17 +66,17 @@ gfxPlatformMac::gfxPlatformMac()
 {
     mOSXVersion = 0;
     OSXVersion();
 
     DisableFontActivation();
     mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
 
     uint32_t canvasMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA) | (1 << BACKEND_COREGRAPHICS);
-    uint32_t contentMask = 0;
+    uint32_t contentMask = (1 << BACKEND_COREGRAPHICS);
     InitBackendPrefs(canvasMask, contentMask);
 }
 
 gfxPlatformMac::~gfxPlatformMac()
 {
     gfxCoreTextShaper::Shutdown();
 }
 
--- a/gfx/thebes/gfxQuartzNativeDrawing.cpp
+++ b/gfx/thebes/gfxQuartzNativeDrawing.cpp
@@ -3,39 +3,65 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsMathUtils.h"
 
 #include "gfxQuartzNativeDrawing.h"
 #include "gfxQuartzSurface.h"
 #include "cairo-quartz.h"
+#include "mozilla/gfx/2D.h"
 // see cairo-quartz-surface.c for the complete list of these
 enum {
     kPrivateCGCompositeSourceOver = 2
 };
 
+using namespace mozilla::gfx;
+using namespace mozilla;
+
 // private Quartz routine needed here
 extern "C" {
     CG_EXTERN void CGContextSetCompositeOperation(CGContextRef, int);
 }
 
 gfxQuartzNativeDrawing::gfxQuartzNativeDrawing(gfxContext* ctx,
                                                const gfxRect& nativeRect,
                                                gfxFloat aBackingScale)
-    : mContext(ctx), mNativeRect(nativeRect), mBackingScale(aBackingScale)
+    : mContext(ctx)
+    , mNativeRect(nativeRect)
+    , mBackingScale(aBackingScale)
 {
     mNativeRect.RoundOut();
 }
 
 CGContextRef
 gfxQuartzNativeDrawing::BeginNativeDrawing()
 {
     NS_ASSERTION(!mQuartzSurface, "BeginNativeDrawing called when drawing already in progress");
 
+    if (!mContext->IsCairo()) {
+      DrawTarget *dt = mContext->GetDrawTarget();
+      if (mContext->GetDrawTarget()->IsDualDrawTarget()) {
+        IntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
+                            NSToIntFloor(mNativeRect.height * mBackingScale));
+        mDrawTarget = Factory::CreateDrawTarget(BACKEND_COREGRAPHICS, backingSize, FORMAT_B8G8R8A8);
+
+        Matrix transform;
+        transform.Scale(mBackingScale, mBackingScale);
+        transform.Translate(-mNativeRect.x, -mNativeRect.y);
+
+        mDrawTarget->SetTransform(transform);
+        dt = mDrawTarget;
+      }
+
+      mCGContext = mBorrowedContext.Init(dt);
+      MOZ_ASSERT(mCGContext);
+      return mCGContext;
+    }
+
     gfxPoint deviceOffset;
     nsRefPtr<gfxASurface> surf = mContext->CurrentSurface(&deviceOffset.x, &deviceOffset.y);
     if (!surf || surf->CairoStatus())
         return nullptr;
 
     // if this is a native Quartz surface, we don't have to redirect
     // rendering to our own CGContextRef; in most cases, we are able to
     // use the CGContextRef from the surface directly.  we can extend
@@ -91,17 +117,44 @@ gfxQuartzNativeDrawing::BeginNativeDrawi
     }
 
     return mCGContext;
 }
 
 void
 gfxQuartzNativeDrawing::EndNativeDrawing()
 {
-    NS_ASSERTION(mQuartzSurface, "EndNativeDrawing called without BeginNativeDrawing");
+    NS_ASSERTION(mCGContext, "EndNativeDrawing called without BeginNativeDrawing");
+
+    if (mBorrowedContext.cg) {
+        MOZ_ASSERT(!mContext->IsCairo());
+        mBorrowedContext.Finish();
+        if (mDrawTarget) {
+          DrawTarget *dest = mContext->GetDrawTarget();
+          RefPtr<SourceSurface> source = mDrawTarget->Snapshot();
+
+          IntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
+                              NSToIntFloor(mNativeRect.height * mBackingScale));
+
+          Matrix oldTransform = dest->GetTransform();
+          Matrix newTransform = oldTransform;
+          newTransform.Translate(mNativeRect.x, mNativeRect.y);
+          newTransform.Scale(1.0f / mBackingScale, 1.0f / mBackingScale);
+
+          dest->SetTransform(newTransform);
+
+          dest->DrawSurface(source,
+                            gfx::Rect(0, 0, backingSize.width, backingSize.height),
+                            gfx::Rect(0, 0, backingSize.width, backingSize.height));
+
+
+          dest->SetTransform(oldTransform);
+        }
+        return;
+    }
 
     cairo_quartz_finish_cg_context_with_clip(mSurfaceContext->GetCairo());
     mQuartzSurface->MarkDirty();
     if (mSurfaceContext != mContext) {
         gfxContextMatrixAutoSaveRestore save(mContext);
 
         // Copy back to destination
         mContext->Translate(mNativeRect.TopLeft());
--- a/gfx/thebes/gfxQuartzNativeDrawing.h
+++ b/gfx/thebes/gfxQuartzNativeDrawing.h
@@ -51,18 +51,21 @@ public:
     /* Marks the end of native drawing */
     void EndNativeDrawing();
 
 private:
     // don't allow copying via construction or assignment
     gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&) MOZ_DELETE;
     const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&) MOZ_DELETE;
 
+
     // Final destination context
     nsRefPtr<gfxContext> mContext;
+    mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
+    mozilla::gfx::BorrowedCGContext mBorrowedContext;
     // context that draws to mQuartzSurface; can be different from mContext
     // if mContext is not drawing to Quartz
     nsRefPtr<gfxContext> mSurfaceContext;
     gfxRect mNativeRect;
     gfxFloat mBackingScale;
 
     // saved state
     nsRefPtr<gfxQuartzSurface> mQuartzSurface;
--- a/js/src/builtin/Profilers.cpp
+++ b/js/src/builtin/Profilers.cpp
@@ -16,20 +16,16 @@
 
 #ifdef __APPLE__
 #include "devtools/sharkctl.h"
 #include "devtools/Instruments.h"
 #endif
 
 #include "jscntxtinlines.h"
 
-#ifdef JSGC_GENERATIONAL
-#include "vm/Shape-inl.h"
-#endif
-
 using namespace js;
 
 using mozilla::ArrayLength;
 
 /* Thread-unsafe error management */
 
 static char gLastError[2000];
 
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -5,25 +5,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "frontend/BytecodeCompiler.h"
 
 #include "jsscript.h"
 #include "frontend/BytecodeEmitter.h"
 #include "frontend/FoldConstants.h"
 #include "frontend/NameFunctions.h"
+#include "frontend/Parser.h"
 #include "ion/AsmJS.h"
 #include "vm/GlobalObject.h"
 
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseMaps-inl.h"
-#include "frontend/SharedContext-inl.h"
-#include "vm/ScopeObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 using mozilla::Maybe;
 
 static bool
 CheckLength(JSContext *cx, size_t length)
 {
@@ -397,16 +396,18 @@ frontend::CompileLazyFunction(JSContext 
 
 // Compile a JS function body, which might appear as the value of an event
 // handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
 bool
 frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileOptions options,
                               const AutoNameVector &formals, const jschar *chars, size_t length,
                               bool isAsmJSRecompile)
 {
+    // FIXME: make Function pass in two strings and parse them as arguments and
+    // ProgramElements respectively.
     SkipRoot skip(cx, &chars);
 
     if (!CheckLength(cx, length))
         return false;
     ScriptSource *ss = cx->new_<ScriptSource>();
     if (!ss)
         return false;
     if (options.filename && !ss->setFilename(cx, options.filename))
@@ -438,51 +439,27 @@ frontend::CompileFunctionBody(JSContext 
                                     canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
     parser.sct = &sct;
 
     JS_ASSERT(fun);
     JS_ASSERT(fun->isTenured());
 
     fun->setArgCount(formals.length());
 
-    /* FIXME: make Function format the source for a function definition. */
-    ParseNode *fn = CodeNode::create(PNK_FUNCTION, &parser.handler);
-    if (!fn)
-        return false;
-
-    fn->pn_body = NULL;
-    fn->pn_funbox = NULL;
-    fn->pn_cookie.makeFree();
-
-    ParseNode *argsbody = ListNode::create(PNK_ARGSBODY, &parser.handler);
-    if (!argsbody)
-        return false;
-    argsbody->setOp(JSOP_NOP);
-    argsbody->makeEmpty();
-    fn->pn_body = argsbody;
-
-    Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), false, options,
-                                                  /* staticLevel = */ 0, sourceObject,
-                                                  /* sourceStart = */ 0, length));
-    if (!script)
-        return false;
-
     // If the context is strict, immediately parse the body in strict
     // mode. Otherwise, we parse it normally. If we see a "use strict"
     // directive, we backup and reparse it as strict.
+    ParseNode *fn;
     TokenStream::Position start(parser.keepAtoms);
     parser.tokenStream.tell(&start);
     bool strict = options.strictOption;
     bool becameStrict;
-    FunctionBox *funbox;
-    ParseNode *pn;
     while (true) {
-        pn = parser.standaloneFunctionBody(fun, formals, script, fn, &funbox,
-                                           strict, &becameStrict);
-        if (pn)
+        fn = parser.standaloneFunctionBody(fun, formals, strict, &becameStrict);
+        if (fn)
             break;
 
         if (parser.hadAbortedSyntaxParse()) {
             // Hit some unrecoverable ambiguity during an inner syntax parse.
             // Syntax parsing has now been disabled in the parser, so retry
             // the parse.
             parser.clearAbortedSyntaxParse();
         } else {
@@ -490,60 +467,60 @@ frontend::CompileFunctionBody(JSContext 
             if (strict || !becameStrict || parser.tokenStream.hadError())
                 return false;
             strict = true;
         }
 
         parser.tokenStream.seek(start);
     }
 
-    if (!NameFunctions(cx, pn))
+    if (!NameFunctions(cx, fn))
         return false;
 
-    if (fn->pn_body) {
-        JS_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
-        fn->pn_body->append(pn);
-        fn->pn_body->pn_pos = pn->pn_pos;
-        pn = fn->pn_body;
-    }
-
     bool generateBytecode = true;
 #ifdef JS_ION
     JS_ASSERT_IF(isAsmJSRecompile, fn->pn_funbox->useAsm);
     if (fn->pn_funbox->useAsm && !isAsmJSRecompile) {
         RootedFunction moduleFun(cx);
         if (!CompileAsmJS(cx, parser.tokenStream, fn, options,
                           ss, /* bufStart = */ 0, /* bufEnd = */ length,
                           &moduleFun))
             return false;
 
         if (moduleFun) {
-            funbox->object = moduleFun;
+            fn->pn_funbox->object = moduleFun;
             fun.set(moduleFun); // replace the existing function with the LinkAsmJS native
             generateBytecode = false;
         }
     }
 #endif
 
+    Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), false, options,
+                                                  /* staticLevel = */ 0, sourceObject,
+                                                  /* sourceStart = */ 0, length));
+    if (!script)
+        return false;
+    script->bindings = fn->pn_funbox->bindings;
+
     if (generateBytecode) {
         /*
          * The reason for checking fun->environment() below is that certain
          * consumers of JS::CompileFunction, namely
          * nsEventListenerManager::CompileEventHandlerInternal, passes in a
          * NULL environment. This compiled function is never used, but instead
          * is cloned immediately onto the right scope chain.
          */
-        BytecodeEmitter funbce(/* parent = */ NULL, &parser, funbox, script,
+        BytecodeEmitter funbce(/* parent = */ NULL, &parser, fn->pn_funbox, script,
                                /* insideEval = */ false, /* evalCaller = */ NullPtr(),
                                fun->environment() && fun->environment()->is<GlobalObject>(),
                                options.lineno);
         if (!funbce.init())
             return false;
 
-        if (!EmitFunctionScript(cx, &funbce, pn))
+        if (!EmitFunctionScript(cx, &funbce, fn->pn_body))
             return false;
     }
 
     if (!SetSourceMap(cx, parser.tokenStream, ss, script))
         return false;
 
     if (!sct.complete())
         return false;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -33,17 +33,16 @@
 
 #include "jsatominlines.h"
 #include "jsfuninlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseMaps-inl.h"
 #include "frontend/ParseNode-inl.h"
-#include "frontend/SharedContext-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 using mozilla::DebugOnly;
 using mozilla::DoubleIsInt32;
 using mozilla::PodCopy;
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -379,16 +379,20 @@ class FullParseHandler
             pn->append(kid);
         }
         return pn;
     }
     void addList(ParseNode *pn, ParseNode *kid) {
         pn->append(kid);
     }
 
+    bool isUnparenthesizedYield(ParseNode *pn) {
+        return pn->isKind(PNK_YIELD) && !pn->isInParens();
+    }
+
     void setOp(ParseNode *pn, JSOp op) {
         pn->setOp(op);
     }
     void setBlockId(ParseNode *pn, unsigned blockid) {
         pn->pn_blockid = blockid;
     }
     void setFlag(ParseNode *pn, unsigned flag) {
         pn->pn_dflags |= flag;
--- a/js/src/frontend/ParseMaps.cpp
+++ b/js/src/frontend/ParseMaps.cpp
@@ -3,19 +3,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jscntxt.h"
 #include "frontend/FullParseHandler.h"
 #include "frontend/SyntaxParseHandler.h"
 
-#include "frontend/ParseMaps-inl.h"
-#include "vm/String-inl.h"
-
 using namespace js;
 using namespace js::frontend;
 
 void
 ParseMapPool::checkInvariants()
 {
     /*
      * Having all values be of the same size permits us to easily reuse the
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -208,30 +208,27 @@ enum ParseNodeKind
 /*
  * Label        Variant     Members
  * -----        -------     -------
  * <Definitions>
  * PNK_FUNCTION name        pn_funbox: ptr to js::FunctionBox holding function
  *                            object containing arg and var properties.  We
  *                            create the function object at parse (not emit)
  *                            time to specialize arg and var bytecodes early.
- *                          pn_body: PNK_ARGSBODY if formal parameters,
- *                                   PNK_STATEMENTLIST node for function body
- *                                     statements,
- *                                   PNK_RETURN for expression closure, or
- *                                   PNK_SEQ for expression closure with
- *                                     destructured formal parameters
- *                                   PNK_LEXICALSCOPE for implicit function
- *                                     in generator-expression
+ *                          pn_body: PNK_ARGSBODY, ordinarily;
+ *                            PNK_LEXICALSCOPE for implicit function in genexpr
  *                          pn_cookie: static level and var index for function
  *                          pn_dflags: PND_* definition/use flags (see below)
  *                          pn_blockid: block id number
- * PNK_ARGSBODY list        list of formal parameters followed by
- *                            PNK_STATEMENTLIST node for function body
- *                            statements as final element
+ * PNK_ARGSBODY list        list of formal parameters followed by:
+ *                              PNK_STATEMENTLIST node for function body
+ *                                statements,
+ *                              PNK_RETURN for expression closure, or
+ *                              PNK_SEQ for expression closure with
+ *                                destructured formal parameters
  *                          pn_count: 1 + number of formal parameters
  *                          pn_tree: PNK_ARGSBODY or PNK_STATEMENTLIST node
  * PNK_SPREAD   unary       pn_kid: expression being spread
  *
  * <Statements>
  * PNK_STATEMENTLIST list   pn_head: list of pn_count statements
  * PNK_IF       ternary     pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
  *                            In body of a comprehension or desugared generator
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -38,17 +38,16 @@
 
 #include "jsatominlines.h"
 #include "jsfuninlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseMaps-inl.h"
 #include "frontend/ParseNode-inl.h"
-#include "frontend/SharedContext-inl.h"
 
 #include "vm/NumericConversions.h"
 
 using namespace js;
 using namespace js::gc;
 using mozilla::Maybe;
 
 namespace js {
@@ -831,28 +830,38 @@ Parser<ParseHandler>::checkStrictBinding
     }
 
     return true;
 }
 
 template <>
 ParseNode *
 Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals,
-                                                 HandleScript script, Node fn, FunctionBox **funbox,
                                                  bool strict, bool *becameStrict)
 {
     if (becameStrict)
         *becameStrict = false;
 
-    *funbox = newFunctionBox(fun, /* outerpc = */ NULL, strict);
+    Node fn = handler.newFunctionDefinition();
+    if (!fn)
+        return null();
+
+    ParseNode *argsbody = ListNode::create(PNK_ARGSBODY, &handler);
+    if (!argsbody)
+        return null();
+    argsbody->setOp(JSOP_NOP);
+    argsbody->makeEmpty();
+    fn->pn_body = argsbody;
+
+    FunctionBox *funbox = newFunctionBox(fun, /* outerpc = */ NULL, strict);
     if (!funbox)
         return null();
-    handler.setFunctionBox(fn, *funbox);
-
-    ParseContext<FullParseHandler> funpc(this, pc, *funbox, /* staticLevel = */ 0, /* bodyid = */ 0);
+    handler.setFunctionBox(fn, funbox);
+
+    ParseContext<FullParseHandler> funpc(this, pc, funbox, /* staticLevel = */ 0, /* bodyid = */ 0);
     if (!funpc.init())
         return null();
 
     for (unsigned i = 0; i < formals.length(); i++) {
         if (!defineArg(fn, formals[i]))
             return null();
     }
 
@@ -866,28 +875,25 @@ Parser<FullParseHandler>::standaloneFunc
     if (!tokenStream.matchToken(TOK_EOF)) {
         report(ParseError, false, null(), JSMSG_SYNTAX_ERROR);
         return null();
     }
 
     if (!FoldConstants(context, &pn, this))
         return null();
 
-    InternalHandle<Bindings*> scriptBindings(script, &script->bindings);
-    if (!funpc.generateFunctionBindings(context, alloc, scriptBindings))
-        return null();
-
-    // Also populate the internal bindings of the function box, so that
-    // heavyweight tests while emitting bytecode work.
     InternalHandle<Bindings*> funboxBindings =
-        InternalHandle<Bindings*>::fromMarkedLocation(&(*funbox)->bindings);
+        InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
     if (!funpc.generateFunctionBindings(context, alloc, funboxBindings))
         return null();
 
-    return pn;
+    JS_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
+    fn->pn_body->append(pn);
+    fn->pn_body->pn_pos = pn->pn_pos;
+    return fn;
 }
 
 template <>
 bool
 Parser<FullParseHandler>::checkFunctionArguments()
 {
     /*
      * Non-top-level functions use JSOP_DEFFUN which is a dynamic scope
@@ -1920,17 +1926,16 @@ Parser<ParseHandler>::functionDef(Handle
 
     RootedFunction fun(context, newFunction(pc, funName, kind));
     if (!fun)
         return null();
 
     // If the outer scope is strict, immediately parse the function in strict
     // mode. Otherwise, we parse it normally. If we see a "use strict"
     // directive, we backup and reparse it as strict.
-    handler.setFunctionBody(pn, null());
     bool initiallyStrict = pc->sc->strict;
     bool becameStrict;
     if (!functionArgsAndBody(pn, fun, funName, startOffset, type, kind, initiallyStrict,
                              &becameStrict))
     {
         if (initiallyStrict || !becameStrict || tokenStream.hadError())
             return null();
 
@@ -4473,16 +4478,18 @@ Parser<ParseHandler>::returnStatementOrY
 
     return pn;
 }
 
 template <>
 ParseNode *
 Parser<FullParseHandler>::withStatement()
 {
+    // test262/ch12/12.10/12.10-0-1.js fails if we try to parse with-statements
+    // in syntax-parse mode. See bug 892583.
     if (handler.syntaxParser) {
         handler.disableSyntaxParser();
         abortedSyntaxParse = true;
         return null();
     }
 
     JS_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH));
     uint32_t begin = pos().begin;
@@ -4770,44 +4777,38 @@ Parser<ParseHandler>::debuggerStatement(
 
     return handler.newDebuggerStatement(p);
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::statement(bool canHaveDirectives)
 {
-    Node pn;
-
     JS_CHECK_RECURSION(context, return null());
 
-    switch (tokenStream.getToken(TSF_OPERAND)) {
+    switch (TokenKind tt = tokenStream.getToken(TSF_OPERAND)) {
       case TOK_LC:
         return blockStatement();
 
-      case TOK_VAR:
-        pn = variables(PNK_VAR);
-        if (!pn)
-            return null();
-
-        /* Tell js_EmitTree to generate a final POP. */
-        handler.setListFlag(pn, PNX_POPVAR);
-        break;
-
       case TOK_CONST:
         if (!abortIfSyntaxParser())
             return null();
-
-        pn = variables(PNK_CONST);
+        // FALL THROUGH
+      case TOK_VAR: {
+        Node pn = variables(tt == TOK_CONST ? PNK_CONST : PNK_VAR);
         if (!pn)
             return null();
 
-        /* Tell js_EmitTree to generate a final POP. */
+        // Tell js_EmitTree to generate a final POP.
         handler.setListFlag(pn, PNX_POPVAR);
-        break;
+
+        if (!MatchOrInsertSemicolon(tokenStream))
+            return null();
+        return pn;
+      }
 
 #if JS_HAS_BLOCK_SCOPE
       case TOK_LET:
         return letStatement();
 #endif
 
       case TOK_SEMI:
         return handler.newEmptyStatement(pos());
@@ -4865,60 +4866,39 @@ Parser<ParseHandler>::statement(bool can
         {
             return moduleDecl();
         }
         return expressionStatement();
 
       default:
         return expressionStatement();
     }
-
-    /* Check termination of this primitive statement. */
-    return MatchOrInsertSemicolon(tokenStream) ? pn : null();
 }
 
-template <>
-ParseNode *
-Parser<FullParseHandler>::expr()
-{
-    ParseNode *pn = assignExpr();
-    if (pn && tokenStream.matchToken(TOK_COMMA)) {
-        ParseNode *pn2 = ListNode::create(PNK_COMMA, &handler);
-        if (!pn2)
-            return null();
-        pn2->pn_pos.begin = pn->pn_pos.begin;
-        pn2->initList(pn);
-        pn = pn2;
-        do {
-            pn2 = pn->last();
-            if (pn2->isKind(PNK_YIELD) && !pn2->isInParens()) {
-                report(ParseError, false, pn2, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str);
-                return null();
-            }
-            pn2 = assignExpr();
-            if (!pn2)
-                return null();
-            pn->append(pn2);
-        } while (tokenStream.matchToken(TOK_COMMA));
-        pn->pn_pos.end = pn->last()->pn_pos.end;
-    }
-    return pn;
-}
-
-template <>
-SyntaxParseHandler::Node
-Parser<SyntaxParseHandler>::expr()
+template <typename ParseHandler>
+typename ParseHandler::Node
+Parser<ParseHandler>::expr()
 {
     Node pn = assignExpr();
     if (pn && tokenStream.matchToken(TOK_COMMA)) {
+        Node seq = handler.newList(PNK_COMMA, pn);
+        if (!seq)
+            return null();
         do {
-            if (!assignExpr())
+            if (handler.isUnparenthesizedYield(pn)) {
+                report(ParseError, false, pn, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str);
                 return null();
+            }
+
+            pn = assignExpr();
+            if (!pn)
+                return null();
+            handler.addList(seq, pn);
         } while (tokenStream.matchToken(TOK_COMMA));
-        return SyntaxParseHandler::NodeGeneric;
+        return seq;
     }
     return pn;
 }
 
 static const JSOp ParseNodeKindToJSOp[] = {
     JSOP_OR,
     JSOP_AND,
     JSOP_BITOR,
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -397,19 +397,18 @@ class Parser : private AutoGCRooter, pub
 
   public:
 
     /* Public entry points for parsing. */
     Node statement(bool canHaveDirectives = false);
     bool maybeParseDirective(Node pn, bool *cont);
 
     // Parse a function, given only its body. Used for the Function constructor.
-    Node standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals, HandleScript script,
-                                Node fn, FunctionBox **funbox, bool strict,
-                                bool *becameStrict = NULL);
+    Node standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals,
+                                bool strict, bool *becameStrict);
 
     // Parse a function, given only its arguments and body. Used for lazily
     // parsed functions.
     Node standaloneLazyFunction(HandleFunction fun, unsigned staticLevel, bool strict);
 
     /*
      * Parse a function body.  Pass StatementListBody if the body is a list of
      * statements; pass ExpressionBody if the body is a single expression.
@@ -578,24 +577,16 @@ class Parser : private AutoGCRooter, pub
     friend class CompExprTransplanter;
     friend class GenexpGuard<ParseHandler>;
     friend struct BindData<ParseHandler>;
 };
 
 /* Declare some required template specializations. */
 
 template <>
-ParseNode *
-Parser<FullParseHandler>::expr();
-
-template <>
-SyntaxParseHandler::Node
-Parser<SyntaxParseHandler>::expr();
-
-template <>
 bool
 Parser<FullParseHandler>::setAssignmentLhsOps(ParseNode *pn, bool isPlainAssignment);
 
 template <>
 bool
 Parser<SyntaxParseHandler>::setAssignmentLhsOps(Node pn, bool isPlainAssignment);
 
 } /* namespace frontend */
deleted file mode 100644
--- a/js/src/frontend/SharedContext-inl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef frontend_SharedContext_inl_h
-#define frontend_SharedContext_inl_h
-
-#include "frontend/Parser.h"
-#include "frontend/SharedContext.h"
-
-namespace js {
-namespace frontend {
-
-inline bool
-SharedContext::needStrictChecks()
-{
-    return strict || extraWarnings;
-}
-
-} /* namespace frontend */
-} // namespace js
-
-#endif /* frontend_SharedContext_inl_h */
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -175,17 +175,19 @@ class SharedContext
     bool bindingsAccessedDynamically() const { return anyCxFlags.bindingsAccessedDynamically; }
     bool hasDebuggerStatement()        const { return anyCxFlags.hasDebuggerStatement; }
 
     void setExplicitUseStrict()           { anyCxFlags.hasExplicitUseStrict        = true; }
     void setBindingsAccessedDynamically() { anyCxFlags.bindingsAccessedDynamically = true; }
     void setHasDebuggerStatement()        { anyCxFlags.hasDebuggerStatement        = true; }
 
     // JSOPTION_EXTRA_WARNINGS warnings or strict mode errors.
-    inline bool needStrictChecks();
+    bool needStrictChecks() {
+        return strict || extraWarnings;
+    }
 };
 
 class GlobalSharedContext : public SharedContext
 {
   private:
     const RootedObject scopeChain_; /* scope chain object for the script */
 
   public:
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -169,16 +169,17 @@ class SyntaxParseHandler
     TokenPos getPosition(Node pn) {
         return tokenStream.currentToken().pos;
     }
 
     Node newList(ParseNodeKind kind, Node kid = NodeGeneric, JSOp op = JSOP_NOP) {
         return NodeGeneric;
     }
     void addList(Node pn, Node kid) {}
+    bool isUnparenthesizedYield(Node pn) { return false; }
 
     void setOp(Node pn, JSOp op) {}
     void setBlockId(Node pn, unsigned blockid) {}
     void setFlag(Node pn, unsigned flag) {}
     void setListFlag(Node pn, unsigned flag) {}
     Node setInParens(Node pn) {
         // String literals enclosed by parentheses are ignored during
         // strict mode parsing.
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -12,17 +12,16 @@
 #include "jsutil.h"
 
 #include "gc/GCInternals.h"
 #include "gc/Memory.h"
 #include "vm/ArrayObject.h"
 #include "vm/Debugger.h"
 #include "vm/TypedArrayObject.h"
 
-#include "gc/Barrier-inl.h"
 #include "gc/Nursery-inl.h"
 #include "vm/ObjectImpl-inl.h"
 
 using namespace js;
 using namespace gc;
 using namespace mozilla;
 
 bool
--- a/js/src/gc/StoreBuffer.cpp
+++ b/js/src/gc/StoreBuffer.cpp
@@ -7,17 +7,16 @@
 #ifdef JSGC_GENERATIONAL
 
 #include "gc/StoreBuffer.h"
 
 #include "mozilla/Assertions.h"
 
 #include "vm/ForkJoin.h"
 
-#include "gc/Barrier-inl.h"
 #include "vm/ObjectImpl-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
 /*** SlotEdge ***/
 
 JS_ALWAYS_INLINE HeapSlot *
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -372,17 +372,17 @@ class StoreBuffer
     void *buffer;
 
     bool aboutToOverflow;
     bool overflowed;
     bool enabled;
 
     /* TODO: profile to find the ideal size for these. */
     static const size_t ValueBufferSize = 1 * 1024 * sizeof(ValueEdge);
-    static const size_t CellBufferSize = 2 * 1024 * sizeof(CellPtrEdge);
+    static const size_t CellBufferSize = 8 * 1024 * sizeof(CellPtrEdge);
     static const size_t SlotBufferSize = 2 * 1024 * sizeof(SlotEdge);
     static const size_t WholeCellBufferSize = 2 * 1024 * sizeof(WholeCellEdges);
     static const size_t RelocValueBufferSize = 1 * 1024 * sizeof(ValueEdge);
     static const size_t RelocCellBufferSize = 1 * 1024 * sizeof(CellPtrEdge);
     static const size_t GenericBufferSize = 1 * 1024 * sizeof(int);
     static const size_t TotalSize = ValueBufferSize + CellBufferSize +
                                     SlotBufferSize + WholeCellBufferSize +
                                     RelocValueBufferSize + RelocCellBufferSize +
--- a/js/src/ion/AsmJSSignalHandlers.cpp
+++ b/js/src/ion/AsmJSSignalHandlers.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jscntxt.h"
 
 #include "ion/AsmJS.h"
 #include "ion/AsmJSModule.h"
 #include "assembler/assembler/MacroAssembler.h"
 
-#include "gc/Barrier-inl.h"
 #include "vm/ObjectImpl-inl.h"
 
 using namespace js;
 using namespace js::ion;
 using namespace mozilla;
 
 #if defined(XP_WIN)
 # define XMM_sig(p,i) ((p)->Xmm##i)
--- a/js/src/ion/Bailouts.cpp
+++ b/js/src/ion/Bailouts.cpp
@@ -12,17 +12,16 @@
 #include "ion/Bailouts.h"
 #include "ion/SnapshotReader.h"
 #include "ion/Ion.h"
 #include "ion/IonCompartment.h"
 #include "ion/IonSpewer.h"
 #include "vm/Interpreter.h"
 #include "ion/BaselineJIT.h"
 
-#include "ion/IonFrames-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 // These constructor are exactly the same except for the type of the iterator
 // which is given to the SnapshotIterator constructor. Doing so avoid the
 // creation of virtual functions for the IonIterator but may introduce some
--- a/js/src/ion/BaselineBailouts.cpp
+++ b/js/src/ion/BaselineBailouts.cpp
@@ -6,18 +6,16 @@
 
 #include "ion/BaselineCompiler.h"
 #include "ion/BaselineIC.h"
 #include "ion/BaselineJIT.h"
 #include "ion/CompileInfo.h"
 #include "ion/IonSpewer.h"
 #include "ion/IonFrames-inl.h"
 
-#include "vm/Stack-inl.h"
-
 #include "jsfuninlines.h"
 
 using namespace js;
 using namespace js::ion;
 
 // BaselineStackBuilder may reallocate its buffer if the current one is too
 // small. To avoid dangling pointers, BufferPointer represents a pointer into
 // this buffer as a pointer to the header and a fixed offset.
--- a/js/src/ion/BaselineCompiler.cpp
+++ b/js/src/ion/BaselineCompiler.cpp
@@ -7,17 +7,16 @@
 #include "ion/BaselineJIT.h"
 #include "ion/BaselineIC.h"
 #include "ion/BaselineHelpers.h"
 #include "ion/BaselineCompiler.h"
 #include "ion/FixedList.h"
 #include "ion/IonLinker.h"
 #include "ion/IonSpewer.h"
 #include "ion/VMFunctions.h"
-#include "ion/IonFrames-inl.h"
 
 #include "vm/Interpreter-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script)
   : BaselineCompilerSpecific(cx, script)
--- a/js/src/ion/BaselineFrameInfo.cpp
+++ b/js/src/ion/BaselineFrameInfo.cpp
@@ -5,18 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ion/BaselineFrameInfo.h"
 #include "ion/IonSpewer.h"
 #include "ion/shared/BaselineCompiler-shared.h"
 
 #include "jsanalyze.h"
 
-#include "vm/Shape-inl.h"
-
 using namespace js;
 using namespace js::ion;
 
 bool
 FrameInfo::init() {
     // One slot is always needed for this/arguments type checks.
     size_t nstack = Max(script->nslots - script->nfixed, 1);
     if (!stack.init(nstack))
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -9,18 +9,16 @@
 #include "builtin/Eval.h"
 #include "ion/BaselineCompiler.h"
 #include "ion/BaselineHelpers.h"
 #include "ion/BaselineIC.h"
 #include "ion/IonLinker.h"
 #include "ion/IonSpewer.h"
 #include "ion/VMFunctions.h"
 
-#include "builtin/Iterator-inl.h"
-#include "ion/IonFrames-inl.h"
 #include "vm/Interpreter-inl.h"
 
 namespace js {
 namespace ion {
 
 #ifdef DEBUG
 void
 FallbackICSpew(JSContext *cx, ICFallbackStub *stub, const char *fmt, ...)
--- a/js/src/ion/BaselineInspector.cpp
+++ b/js/src/ion/BaselineInspector.cpp
@@ -2,18 +2,16 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ion/BaselineIC.h"
 #include "ion/BaselineInspector.h"
 
-#include "vm/Shape-inl.h"
-
 using namespace js;
 using namespace js::ion;
 
 bool
 SetElemICInspector::sawOOBDenseWrite() const
 {
     if (!icEntry_)
         return false;
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -21,17 +21,16 @@
 #include "ion/ParallelFunctions.h"
 #include "ion/ExecutionModeInlines.h"
 #include "builtin/Eval.h"
 #include "gc/Nursery.h"
 #include "vm/ForkJoin.h"
 #include "ion/ParallelSafetyAnalysis.h"
 
 #include "vm/Interpreter-inl.h"
-#include "vm/StringObject-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 using mozilla::DebugOnly;
 using mozilla::Maybe;
 
 namespace js {
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -42,19 +42,17 @@
 # include "ion/arm/Lowering-arm.h"
 #endif
 #include "gc/Marking.h"
 
 #include "jscompartmentinlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
 
-#include "gc/Barrier-inl.h"
 #include "vm/Stack-inl.h"
-#include "ion/IonFrames-inl.h"
 #include "ion/CompilerRoot.h"
 #include "ion/ExecutionModeInlines.h"
 #include "ion/AsmJS.h"
 #include "ion/AsmJSModule.h"
 
 #if JS_TRACE_LOGGING
 #include "TraceLogging.h"
 #endif
@@ -167,16 +165,17 @@ ion::InitializeIon()
 #endif
     CheckLogging();
     CheckPerf();
     return true;
 }
 
 IonRuntime::IonRuntime()
   : execAlloc_(NULL),
+    exceptionTail_(NULL),
     enterJIT_(NULL),
     bailoutHandler_(NULL),
     argumentsRectifier_(NULL),
     argumentsRectifierReturnAddr_(NULL),
     parallelArgumentsRectifier_(NULL),
     invalidator_(NULL),
     debugTrapHandler_(NULL),
     functionWrappers_(NULL),
@@ -205,16 +204,20 @@ IonRuntime::initialize(JSContext *cx)
 
     if (!cx->compartment()->ensureIonCompartmentExists(cx))
         return false;
 
     functionWrappers_ = cx->new_<VMWrapperMap>(cx);
     if (!functionWrappers_ || !functionWrappers_->init())
         return false;
 
+    exceptionTail_ = generateExceptionTailStub(cx);
+    if (!exceptionTail_)
+        return false;
+
     if (cx->runtime()->jitSupportsFloatingPoint) {
         // Initialize some Ion-only stubs that require floating-point support.
         if (!bailoutTables_.reserve(FrameSizeClass::ClassLimit().classId()))
             return false;
 
         for (uint32_t id = 0;; id++) {
             FrameSizeClass class_ = FrameSizeClass::FromClass(id);
             if (class_ == FrameSizeClass::ClassLimit())
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -14,21 +14,22 @@
 #include "ion/BaselineInspector.h"
 #include "ion/Ion.h"
 #include "ion/IonAnalysis.h"
 #include "ion/IonAnalysis.h"
 #include "ion/IonSpewer.h"
 #include "ion/Lowering.h"
 #include "ion/MIRGraph.h"
 
+#include "jsinferinlines.h"
+#include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 #include "ion/CompileInfo-inl.h"
 #include "ion/ExecutionModeInlines.h"
-#include "vm/ScopeObject-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 using mozilla::DebugOnly;
 
 IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
                        BaselineInspector *inspector, CompileInfo *info, BaselineFrame *baselineFrame,
--- a/js/src/ion/IonCaches.cpp
+++ b/js/src/ion/IonCaches.cpp
@@ -11,18 +11,16 @@
 #include "ion/Ion.h"
 #include "ion/IonCaches.h"
 #include "ion/IonLinker.h"
 #include "ion/IonSpewer.h"
 #include "ion/VMFunctions.h"
 
 #include "vm/Shape.h"
 
-#include "ion/IonFrames-inl.h"
-
 #include "vm/Interpreter-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 using mozilla::DebugOnly;
 
 void
--- a/js/src/ion/IonCompartment.h
+++ b/js/src/ion/IonCompartment.h
@@ -121,16 +121,19 @@ struct FallbackICStubSpace : public ICSt
 
 class IonRuntime
 {
     friend class IonCompartment;
 
     // Executable allocator.
     JSC::ExecutableAllocator *execAlloc_;
 
+    // Shared post-exception-handler tail
+    IonCode *exceptionTail_;
+
     // Trampoline for entering JIT code. Contains OSR prologue.
     IonCode *enterJIT_;
 
     // Trampoline for entering baseline JIT code.
     IonCode *enterBaselineJIT_;
 
     // Vector mapping frame class sizes to bailout tables.
     Vector<IonCode*, 4, SystemAllocPolicy> bailoutTables_;
@@ -164,16 +167,17 @@ class IonRuntime
     // too long, it's also freed in IonCompartment::mark and in EnterBaseline
     // (after returning from JIT code).
     uint8_t *osrTempData_;
 
     // Keep track of memoryregions that are going to be flushed.
     AutoFlushCache *flusher_;
 
   private:
+    IonCode *generateExceptionTailStub(JSContext *cx);
     IonCode *generateEnterJIT(JSContext *cx, EnterJitType type);
     IonCode *generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut);
     IonCode *generateBailoutTable(JSContext *cx, uint32_t frameClass);
     IonCode *generateBailoutHandler(JSContext *cx);
     IonCode *generateInvalidator(JSContext *cx);
     IonCode *generatePreBarrier(JSContext *cx, MIRType type);
     IonCode *generateDebugTrapHandler(JSContext *cx);
     IonCode *generateVMWrapper(JSContext *cx, const VMFunction &f);
@@ -279,16 +283,20 @@ class IonCompartment
     JSC::ExecutableAllocator *execAlloc() {
         return rt->execAlloc_;
     }
 
     IonCode *getGenericBailoutHandler() {
         return rt->bailoutHandler_;
     }
 
+    IonCode *getExceptionTail() {
+        return rt->exceptionTail_;
+    }
+
     IonCode *getBailoutTable(const FrameSizeClass &frameClass);
 
     IonCode *getArgumentsRectifier(ExecutionMode mode) {
         switch (mode) {
           case SequentialExecution: return rt->argumentsRectifier_;
           case ParallelExecution:   return rt->parallelArgumentsRectifier_;
           default:                  MOZ_ASSUME_UNREACHABLE("No such execution mode");
         }
--- a/js/src/ion/ParallelFunctions.cpp
+++ b/js/src/ion/ParallelFunctions.cpp
@@ -2,19 +2,22 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ion/ParallelFunctions.h"
 
 #include "ion/IonSpewer.h"
+#include "vm/ArrayObject.h"
 #include "vm/Interpreter.h"
 
-#include "vm/Interpreter-inl.h"
+#include "jsfuninlines.h"
+#include "jsgcinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace ion;
 
 using parallel::Spew;
 using parallel::SpewOps;
 using parallel::SpewBailouts;
 using parallel::SpewBailoutIR;
--- a/js/src/ion/UnreachableCodeElimination.cpp
+++ b/js/src/ion/UnreachableCodeElimination.cpp
@@ -90,66 +90,116 @@ UnreachableCodeElimination::removeUnmark
         if (mir_->shouldCancel("GVN-after-UCE"))
             return false;
     }
 
     return true;
 }
 
 bool
+UnreachableCodeElimination::enqueue(MBasicBlock *block, BlockList &list)
+{
+    if (block->isMarked())
+        return true;
+
+    block->mark();
+    marked_++;
+    return list.append(block);
+}
+
+MBasicBlock *
+UnreachableCodeElimination::optimizableSuccessor(MBasicBlock *block)
+{
+    // If the last instruction in `block` is a test instruction of a
+    // constant value, returns the successor that the branch will
+    // always branch to at runtime. Otherwise, returns NULL.
+
+    MControlInstruction *ins = block->lastIns();
+    if (!ins->isTest())
+        return NULL;
+
+    MTest *testIns = ins->toTest();
+    MDefinition *v = testIns->getOperand(0);
+    if (!v->isConstant())
+        return NULL;
+
+    const Value &val = v->toConstant()->value();
+    BranchDirection bdir = ToBoolean(val) ? TRUE_BRANCH : FALSE_BRANCH;
+    return testIns->branchSuccessor(bdir);
+}
+
+bool
 UnreachableCodeElimination::prunePointlessBranchesAndMarkReachableBlocks()
 {
-    Vector<MBasicBlock *, 16, SystemAllocPolicy> worklist;
+    BlockList worklist, optimizableBlocks;
 
-    // Seed with the two entry points.
-    MBasicBlock *entries[] = { graph_.entryBlock(), graph_.osrBlock() };
-    for (size_t i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) {
-        if (entries[i]) {
-            entries[i]->mark();
-            marked_++;
-            if (!worklist.append(entries[i]))
-                return false;
-        }
-    }
-
-    // Process everything reachable from there.
+    // Process everything reachable from the start block, ignoring any
+    // OSR block.
+    if (!enqueue(graph_.entryBlock(), worklist))
+        return false;
     while (!worklist.empty()) {
         if (mir_->shouldCancel("Eliminate Unreachable Code"))
             return false;
 
         MBasicBlock *block = worklist.popCopy();
-        MControlInstruction *ins = block->lastIns();
 
-        // Rewrite test false or test true to goto.
-        if (ins->isTest()) {
-            MTest *testIns = ins->toTest();
-            MDefinition *v = testIns->getOperand(0);
-            if (v->isConstant()) {
-                const Value &val = v->toConstant()->value();
-                BranchDirection bdir = ToBoolean(val) ? TRUE_BRANCH : FALSE_BRANCH;
-                MBasicBlock *succ = testIns->branchSuccessor(bdir);
-                MGoto *gotoIns = MGoto::New(succ);
-                block->discardLastIns();
-                block->end(gotoIns);
-                MBasicBlock *successorWithPhis = block->successorWithPhis();
-                if (successorWithPhis && successorWithPhis != succ)
-                    block->setSuccessorWithPhis(NULL, 0);
-            }
-        }
-
-        for (size_t i = 0; i < block->numSuccessors(); i++) {
-            MBasicBlock *succ = block->getSuccessor(i);
-            if (!succ->isMarked()) {
-                succ->mark();
-                marked_++;
-                if (!worklist.append(succ))
+        // If this block is a test on a constant operand, only enqueue
+        // the relevant successor. Also, remember the block for later.
+        if (MBasicBlock *succ = optimizableSuccessor(block)) {
+            if (!optimizableBlocks.append(block))
+                return false;
+            if (!enqueue(succ, worklist))
+                return false;
+        } else {
+            // Otherwise just visit all successors.
+            for (size_t i = 0; i < block->numSuccessors(); i++) {
+                MBasicBlock *succ = block->getSuccessor(i);
+                if (!enqueue(succ, worklist))
                     return false;
             }
         }
     }
+
+    // Now, if there is an OSR block, check that all of its successors
+    // were reachable (bug 880377). If not, we are in danger of
+    // creating a CFG with two disjoint parts, so simply mark all
+    // blocks as reachable. This generally occurs when the TI info for
+    // stack types is incorrect or incomplete, due to operations that
+    // have not yet executed in baseline.
+    if (graph_.osrBlock()) {
+        MBasicBlock *osrBlock = graph_.osrBlock();
+        JS_ASSERT(!osrBlock->isMarked());
+        if (!enqueue(osrBlock, worklist))
+            return false;
+        for (size_t i = 0; i < osrBlock->numSuccessors(); i++) {
+            if (!osrBlock->getSuccessor(i)->isMarked()) {
+                // OSR block has an otherwise unreachable successor, abort.
+                for (MBasicBlockIterator iter(graph_.begin()); iter != graph_.end(); iter++)
+                    iter->mark();
+                marked_ = graph_.numBlocks();
+                return true;
+            }
+        }
+    }
+
+    // Now that we know we will not abort due to OSR, go back and
+    // transform any tests on constant operands into gotos.
+    for (uint32_t i = 0; i < optimizableBlocks.length(); i++) {
+        MBasicBlock *block = optimizableBlocks[i];
+        MBasicBlock *succ = optimizableSuccessor(block);
+        JS_ASSERT(succ);
+
+        MGoto *gotoIns = MGoto::New(succ);
+        block->discardLastIns();
+        block->end(gotoIns);
+        MBasicBlock *successorWithPhis = block->successorWithPhis();
+        if (successorWithPhis && successorWithPhis != succ)
+            block->setSuccessorWithPhis(NULL, 0);
+    }
+
     return true;
 }
 
 void
 UnreachableCodeElimination::checkDependencyAndRemoveUsesFromUnmarkedBlocks(MDefinition *instr)
 {
     // When the instruction depends on removed block,
     // alias analysis needs to get rerun to have the right dependency.
--- a/js/src/ion/UnreachableCodeElimination.h
+++ b/js/src/ion/UnreachableCodeElimination.h
@@ -12,27 +12,32 @@
 
 namespace js {
 namespace ion {
 
 class MIRGraph;
 
 class UnreachableCodeElimination
 {
+    typedef Vector<MBasicBlock *, 16, SystemAllocPolicy> BlockList;
+
     MIRGenerator *mir_;
     MIRGraph &graph_;
     uint32_t marked_;
     bool redundantPhis_;
     bool rerunAliasAnalysis_;
 
     bool prunePointlessBranchesAndMarkReachableBlocks();
     void checkDependencyAndRemoveUsesFromUnmarkedBlocks(MDefinition *instr);
     bool removeUnmarkedBlocksAndClearDominators();
     bool removeUnmarkedBlocksAndCleanup();
 
+    bool enqueue(MBasicBlock *block, BlockList &list);
+    MBasicBlock *optimizableSuccessor(MBasicBlock *block);
+
   public:
     UnreachableCodeElimination(MIRGenerator *mir, MIRGraph &graph)
       : mir_(mir),
         graph_(graph),
         marked_(0),
         redundantPhis_(false),
         rerunAliasAnalysis_(false)
     {}
--- a/js/src/ion/VMFunctions.cpp
+++ b/js/src/ion/VMFunctions.cpp
@@ -16,20 +16,17 @@
 #include "vm/StringObject-inl.h"
 
 #include "builtin/ParallelArray.h"
 
 #include "frontend/BytecodeCompiler.h"
 
 #include "jsboolinlines.h"
 
-#include "ion/IonFrames-inl.h" // for GetTopIonJSScript
-
 #include "vm/Interpreter-inl.h"
-#include "vm/StringObject-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 namespace js {
 namespace ion {
 
 // Don't explicitly initialize, it's not guaranteed that this initializer will
--- a/js/src/ion/arm/Bailouts-arm.cpp
+++ b/js/src/ion/arm/Bailouts-arm.cpp
@@ -3,17 +3,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "ion/Bailouts.h"
 #include "ion/IonCompartment.h"
-#include "ion/IonFrames-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 #if 0
 // no clue what these asserts should be.
 JS_STATIC_ASSERT(sizeof(BailoutStack) ==
                  sizeof(uintptr_t) +
--- a/js/src/ion/arm/MacroAssembler-arm.cpp
+++ b/js/src/ion/arm/MacroAssembler-arm.cpp
@@ -3238,16 +3238,23 @@ MacroAssemblerARMCompat::handleFailureWi
     ma_sub(Imm32(size), sp);
     ma_mov(sp, r0);
 
     // Ask for an exception handler.
     setupUnalignedABICall(1, r1);
     passABIArg(r0);
     callWithABI(handler);
 
+    IonCode *excTail = GetIonContext()->compartment->ionCompartment()->getExceptionTail();
+    branch(excTail);
+}
+
+void
+MacroAssemblerARMCompat::handleFailureWithHandlerTail()
+{
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
 
     ma_ldr(Operand(sp, offsetof(ResumeFromException, kind)), r0);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_CATCH), &catch_);
--- a/js/src/ion/arm/MacroAssembler-arm.h
+++ b/js/src/ion/arm/MacroAssembler-arm.h
@@ -1016,16 +1016,17 @@ class MacroAssemblerARMCompat : public M
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         ma_lsl(Imm32(FRAMESIZE_SHIFT), frameSizeReg, frameSizeReg);
         ma_orr(Imm32(type), frameSizeReg);
     }
 
     void linkExitFrame();
     void linkParallelExitFrame(const Register &pt);
     void handleFailureWithHandler(void *handler);
+    void handleFailureWithHandlerTail();
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
   public:
     // The following functions are exposed for use in platform-shared code.
     void Push(const Register &reg) {
         ma_push(reg);
--- a/js/src/ion/arm/Trampoline-arm.cpp
+++ b/js/src/ion/arm/Trampoline-arm.cpp
@@ -819,8 +819,19 @@ IonRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.mov(r11, sp);
     masm.pop(r11);
     masm.ret();
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
+
+IonCode *
+IonRuntime::generateExceptionTailStub(JSContext *cx)
+{
+    MacroAssembler masm;
+
+    masm.handleFailureWithHandlerTail();
+
+    Linker linker(masm);
+    return linker.newCode(cx, JSC::OTHER_CODE);
+}
--- a/js/src/ion/x64/Bailouts-x64.cpp
+++ b/js/src/ion/x64/Bailouts-x64.cpp
@@ -3,17 +3,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "ion/Bailouts.h"
 #include "ion/IonCompartment.h"
-#include "ion/IonFrames-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 #if defined(_WIN32)
 # pragma pack(push, 1)
 #endif
 
--- a/js/src/ion/x64/CodeGenerator-x64.cpp
+++ b/js/src/ion/x64/CodeGenerator-x64.cpp
@@ -9,17 +9,16 @@
 #include "ion/x64/CodeGenerator-x64.h"
 #include "ion/MIR.h"
 #include "ion/MIRGraph.h"
 #include "vm/Shape.h"
 
 #include "jsscriptinlines.h"
 
 #include "ion/shared/CodeGenerator-shared-inl.h"
-#include "vm/Shape-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 CodeGeneratorX64::CodeGeneratorX64(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
   : CodeGeneratorX86Shared(gen, graph, masm)
 {
 }
--- a/js/src/ion/x64/MacroAssembler-x64.cpp
+++ b/js/src/ion/x64/MacroAssembler-x64.cpp
@@ -235,16 +235,23 @@ MacroAssemblerX64::handleFailureWithHand
     subq(Imm32(sizeof(ResumeFromException)), rsp);
     movq(rsp, rax);
 
     // Ask for an exception handler.
     setupUnalignedABICall(1, rcx);
     passABIArg(rax);
     callWithABI(handler);
 
+    IonCode *excTail = GetIonContext()->compartment->ionCompartment()->getExceptionTail();
+    jmp(excTail);
+}
+
+void
+MacroAssemblerX64::handleFailureWithHandlerTail()
+{
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
 
     loadPtr(Address(rsp, offsetof(ResumeFromException, kind)), rax);
     branch32(Assembler::Equal, rax, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
     branch32(Assembler::Equal, rax, Imm32(ResumeFromException::RESUME_CATCH), &catch_);
--- a/js/src/ion/x64/MacroAssembler-x64.h
+++ b/js/src/ion/x64/MacroAssembler-x64.h
@@ -1072,16 +1072,17 @@ class MacroAssemblerX64 : public MacroAs
     void callWithABIPost(uint32_t stackAdjust, Result result);
 
   public:
     // Emits a call to a C/C++ function, resolving all argument moves.
     void callWithABI(void *fun, Result result = GENERAL);
     void callWithABI(Address fun, Result result = GENERAL);
 
     void handleFailureWithHandler(void *handler);
+    void handleFailureWithHandlerTail();
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         shlq(Imm32(FRAMESIZE_SHIFT), frameSizeReg);
         orq(Imm32(type), frameSizeReg);
     }
 
     // Save an exit frame (which must be aligned to the stack pointer) to
     // ThreadData::ionTop of the main thread.
--- a/js/src/ion/x64/Trampoline-x64.cpp
+++ b/js/src/ion/x64/Trampoline-x64.cpp
@@ -710,8 +710,19 @@ IonRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.mov(rbp, rsp);
     masm.pop(rbp);
     masm.ret();
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
+
+IonCode *
+IonRuntime::generateExceptionTailStub(JSContext *cx)
+{
+    MacroAssembler masm;
+
+    masm.handleFailureWithHandlerTail();
+
+    Linker linker(masm);
+    return linker.newCode(cx, JSC::OTHER_CODE);
+}
--- a/js/src/ion/x86/Bailouts-x86.cpp
+++ b/js/src/ion/x86/Bailouts-x86.cpp
@@ -3,17 +3,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "ion/Bailouts.h"
 #include "ion/IonCompartment.h"
-#include "ion/IonFrames-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 #if defined(_WIN32)
 # pragma pack(push, 1)
 #endif
 
--- a/js/src/ion/x86/MacroAssembler-x86.cpp
+++ b/js/src/ion/x86/MacroAssembler-x86.cpp
@@ -207,16 +207,23 @@ MacroAssemblerX86::handleFailureWithHand
     subl(Imm32(sizeof(ResumeFromException)), esp);
     movl(esp, eax);
 
     // Ask for an exception handler.
     setupUnalignedABICall(1, ecx);
     passABIArg(eax);
     callWithABI(handler);
 
+    IonCode *excTail = GetIonContext()->compartment->ionCompartment()->getExceptionTail();
+    jmp(excTail);
+}
+
+void
+MacroAssemblerX86::handleFailureWithHandlerTail()
+{
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
 
     loadPtr(Address(esp, offsetof(ResumeFromException, kind)), eax);
     branch32(Assembler::Equal, eax, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
     branch32(Assembler::Equal, eax, Imm32(ResumeFromException::RESUME_CATCH), &catch_);
--- a/js/src/ion/x86/MacroAssembler-x86.h
+++ b/js/src/ion/x86/MacroAssembler-x86.h
@@ -935,16 +935,17 @@ class MacroAssemblerX86 : public MacroAs
 
   public:
     // Emits a call to a C/C++ function, resolving all argument moves.
     void callWithABI(void *fun, Result result = GENERAL);
     void callWithABI(const Address &fun, Result result = GENERAL);
 
     // Used from within an Exit frame to handle a pending exception.
     void handleFailureWithHandler(void *handler);
+    void handleFailureWithHandlerTail();
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         shll(Imm32(FRAMESIZE_SHIFT), frameSizeReg);
         orl(Imm32(type), frameSizeReg);
     }
 
     // Save an exit frame (which must be aligned to the stack pointer) to
     // ThreadData::ionTop of the main thread.
--- a/js/src/ion/x86/Trampoline-x86.cpp
+++ b/js/src/ion/x86/Trampoline-x86.cpp
@@ -736,8 +736,19 @@ IonRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.mov(ebp, esp);
     masm.pop(ebp);
     masm.ret();
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
+
+IonCode *
+IonRuntime::generateExceptionTailStub(JSContext *cx)
+{
+    MacroAssembler masm;
+
+    masm.handleFailureWithHandlerTail();
+
+    Linker linker(masm);
+    return linker.newCode(cx, JSC::OTHER_CODE);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug880377.js
@@ -0,0 +1,10 @@
+var actual = '';
+var obj0 = {}
+obj2 = {};
+obj2['b'+1] = 1;
+if (actual[0] != 0[0])
+  throw new i();
+for (var k in obj2) {
+  for (var apply in obj0)
+    ++count;
+}
\ No newline at end of file
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -77,17 +77,16 @@
 #include "yarr/BumpPointerAllocator.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsscriptinlines.h"
 
 #include "vm/Interpreter-inl.h"
 #include "vm/ObjectImpl-inl.h"
-#include "vm/RegExpObject-inl.h"
 #include "vm/RegExpStatics-inl.h"
 #include "vm/Shape-inl.h"
 #include "vm/String-inl.h"
 
 #if ENABLE_YARR_JIT
 #include "assembler/jit/ExecutableAllocator.h"
 #endif
 
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -19,19 +19,16 @@
 #include "jsstr.h"
 #include "jstypes.h"
 
 #include "gc/Marking.h"
 #include "vm/Xdr.h"
 
 #include "jscompartmentinlines.h"
 
-#ifdef JSGC_GENERATIONAL
-#include "vm/Shape-inl.h"
-#endif
 #include "vm/String-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
 using mozilla::ArrayEnd;
 using mozilla::ArrayLength;
 using mozilla::RangedPtr;
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -18,17 +18,16 @@
 
 #include "vm/GlobalObject.h"
 #include "vm/ProxyObject.h"
 #include "vm/StringBuffer.h"
 
 #include "jsboolinlines.h"
 
 #include "vm/BooleanObject-inl.h"
-#include "vm/GlobalObject-inl.h"
 
 using namespace js;
 using namespace js::types;
 
 Class BooleanObject::class_ = {
     "Boolean",
     JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
     JS_PropertyStub,         /* addProperty */
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -31,18 +31,18 @@
 #include "jsclone.h"
 
 #include "mozilla/FloatingPoint.h"
 
 #include "jsdate.h"
 
 #include "vm/TypedArrayObject.h"
 
-#include "vm/BooleanObject-inl.h"
-#include "vm/RegExpObject-inl.h"
+#include "jscntxtinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 
 using mozilla::IsNaN;
 using mozilla::LittleEndian;
 using mozilla::NativeEndian;
 
 enum StructuredDataType {
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -37,17 +37,16 @@
 #include "jsscriptinlines.h"
 
 #include "vm/Interpreter-inl.h"
 #include "vm/Stack-inl.h"
 
 #ifdef JS_ION
 #include "ion/Ion.h"
 #include "ion/IonFrameIterator.h"
-#include "ion/IonFrameIterator-inl.h"
 #endif
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::frontend;
 
 using mozilla::ArrayLength;
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -32,18 +32,16 @@
 #include "jsanalyzeinlines.h"
 #include "jsatominlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
 #include "jsopcodeinlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
-#include "vm/Stack-inl.h"
-
 #ifdef __SUNPRO_CC
 #include <alloca.h>
 #endif
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::analyze;
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -985,41 +985,47 @@ Number_toInteger(JSContext *cx, unsigned
 }
 
 
 static const JSFunctionSpec number_static_methods[] = {
     JS_FN("isFinite", Number_isFinite, 1, 0),
     JS_FN("isInteger", Number_isInteger, 1, 0),
     JS_FN("isNaN", Number_isNaN, 1, 0),
     JS_FN("toInteger", Number_toInteger, 1, 0),
+    /* ES6 additions. */
+    JS_FN("parseFloat", num_parseFloat, 1, 0),
+    JS_FN("parseInt", num_parseInt, 2, 0),
     JS_FS_END
 };
 
 
 /* NB: Keep this in synch with number_constants[]. */
 enum nc_slot {
     NC_NaN,
     NC_POSITIVE_INFINITY,
     NC_NEGATIVE_INFINITY,
     NC_MAX_VALUE,
     NC_MIN_VALUE,
+    NC_EPSILON,
     NC_LIMIT
 };
 
 /*
  * Some to most C compilers forbid spelling these at compile time, or barf
  * if you try, so all but MAX_VALUE are set up by InitRuntimeNumberState
  * using union jsdpun.
  */
 static JSConstDoubleSpec number_constants[] = {
     {0,                         "NaN",               0,{0,0,0}},
     {0,                         "POSITIVE_INFINITY", 0,{0,0,0}},
     {0,                         "NEGATIVE_INFINITY", 0,{0,0,0}},
     {1.7976931348623157E+308,   "MAX_VALUE",         0,{0,0,0}},
     {0,                         "MIN_VALUE",         0,{0,0,0}},
+    /* ES6 (May 2013 draft) 15.7.3.7 */
+    {2.2204460492503130808472633361816e-16, "EPSILON", 0,{0,0,0}},
     {0,0,0,{0,0,0}}
 };
 
 double js_NaN;
 double js_PositiveInfinity;
 double js_NegativeInfinity;
 
 #if (defined __GNUC__ && defined __i386__) || \
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -40,19 +40,18 @@
 #include "vm/RegExpStatics.h"
 #include "vm/RegExpStaticsObject.h"
 #include "vm/Shape.h"
 
 #include "jsatominlines.h"
 #include "jsboolinlines.h"
 #include "jscntxtinlines.h"
 #include "jscompartmentinlines.h"
-#include "builtin/Iterator-inl.h"
+
 #include "vm/ArrayObject-inl.h"
-#include "vm/ArgumentsObject-inl.h"
 #include "vm/BooleanObject-inl.h"
 #include "vm/NumberObject-inl.h"
 #include "vm/Runtime-inl.h"
 #include "vm/Shape-inl.h"
 #include "vm/StringObject-inl.h"
 
 using namespace js;
 using namespace js::gc;
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -29,27 +29,27 @@
 #include "jsobj.h"
 #include "jsscript.h"
 #include "jsstr.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/SourceNotes.h"
 #include "js/CharacterEncoding.h"
 #include "vm/Shape.h"
+#include "vm/ScopeObject.h"
 #include "vm/StringBuffer.h"
 
 #include "jscntxtinlines.h"
 #include "jscompartmentinlines.h"
+#include "jsinferinlines.h"
 #include "jsopcodeinlines.h"
+#include "jsscriptinlines.h"
 
 #include "jsautooplen.h"
 
-#include "vm/RegExpObject-inl.h"
-#include "vm/ScopeObject-inl.h"
-
 using namespace js;
 using namespace js::gc;
 
 using js::frontend::IsIdentifier;
 using mozilla::ArrayLength;
 
 /*
  * Index limit must stay within 32 bits.
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -15,18 +15,16 @@
 #include "jsprvtd.h"
 
 #include "gc/Marking.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 
-#include "vm/RegExpObject-inl.h"
-
 using namespace js;
 using namespace js::gc;
 using mozilla::ArrayLength;
 
 void
 js::AutoEnterPolicy::reportError(JSContext *cx, jsid id)
 {
     if (JSID_IS_VOID(id)) {
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -29,22 +29,22 @@
 #include "frontend/BytecodeEmitter.h"
 #include "ion/IonCode.h"
 #include "ion/BaselineJIT.h"
 #include "vm/Debugger.h"
 #include "vm/Interpreter.h"
 #include "vm/Shape.h"
 #include "vm/Xdr.h"
 
+#include "jsfuninlines.h"
 #include "jsinferinlines.h"
 #include "jsscriptinlines.h"
 
-#include "vm/Interpreter-inl.h"
-#include "vm/RegExpObject-inl.h"
 #include "vm/ScopeObject-inl.h"
+#include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 using mozilla::PodCopy;
 using mozilla::PodZero;
 
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -48,17 +48,16 @@
 #include "vm/Shape.h"
 #include "vm/StringBuffer.h"
 
 #include "jsinferinlines.h"
 #include "jsstrinlines.h"
 #include "jsautooplen.h"        // generated headers last
 
 #include "vm/Interpreter-inl.h"
-#include "vm/RegExpObject-inl.h"
 #include "vm/StringObject-inl.h"
 #include "vm/String-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::unicode;
 
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -12,18 +12,16 @@
 #include "jsexn.h"
 #include "jsgc.h"
 #include "jsiter.h"
 
 #include "vm/ErrorObject.h"
 
 #include "jsobjinlines.h"
 
-#include "builtin/Iterator-inl.h"
-
 using namespace js;
 using namespace js::gc;
 
 int js::sWrapperFamily;
 
 void *
 Wrapper::getWrapperFamily()
 {
--- a/js/src/perf/jsperf.cpp
+++ b/js/src/perf/jsperf.cpp
@@ -3,18 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "perf/jsperf.h"
 
 #include "jscntxt.h" /* for error messages */
 #include "jsobj.h" /* for unwrapping without a context */
 
-#include "vm/ObjectImpl-inl.h"
-
 using JS::PerfMeasurement;
 
 // You cannot forward-declare a static object in C++, so instead
 // we have to forward-declare the helper functions that refer to it.
 static PerfMeasurement* GetPM(JSContext* cx, JS::HandleObject obj, const char* fname);
 static PerfMeasurement* GetPMFromThis(JSContext* cx, jsval* vp);
 
 // Property access
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Number/15.7.3.7-EPSILON.js
@@ -0,0 +1,24 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 885798;
+var summary = "ES6 (draft May 2013) 15.7.3.7 Number.EPSILON";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+// Test value
+assertEq(Number.EPSILON, Math.pow(2, -52));
+
+// Test property attributes
+var descriptor = Object.getOwnPropertyDescriptor(Number, 'EPSILON');
+assertEq(descriptor.writable, false);
+assertEq(descriptor.configurable, false);
+assertEq(descriptor.enumerable, false);
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Number/parseFloat-01.js
@@ -0,0 +1,24 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 886949;
+var summary = "ES6 (draft May 2013) 15.7.3.10 Number.parseFloat(string)";
+
+print(BUGNUMBER + ": " + summary);
+
+assertEq(Number.parseFloat("Infinity"), Infinity);
+assertEq(Number.parseFloat("+Infinity"), Infinity);
+assertEq(Number.parseFloat("-Infinity"), -Infinity);
+
+assertEq(Number.parseFloat("inf"), NaN);
+assertEq(Number.parseFloat("Inf"), NaN);
+assertEq(Number.parseFloat("infinity"), NaN);
+
+assertEq(Number.parseFloat("nan"), NaN);
+assertEq(Number.parseFloat("NaN"), NaN);
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("All tests passed!");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Number/parseInt-01.js
@@ -0,0 +1,170 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 886949;
+var summary = "ES6 (draft May 2013) 15.7.3.9 Number.parseInt(string, radix)";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var str, radix;
+var upvar;
+
+/* 1. Let inputString be ToString(string). */
+
+assertEq(Number.parseInt({ toString: function() { return "17" } }, 10), 17);
+
+upvar = 0;
+str = { get toString() { upvar++; return function() { upvar++; return "12345"; } } };
+assertEq(Number.parseInt(str, 10), 12345);
+assertEq(upvar, 2);
+
+
+/*
+ * 2. Let S be a newly created substring of inputString consisting of the first
+ *    character that is not a StrWhiteSpaceChar and all characters following
+ *    that character. (In other words, remove leading white space.)
+ */
+
+var ws =
+  ["\t", "\v", "\f", " ", "\xA0", "\uFEFF",
+     "\u2004", "\u3000", // a few Unicode whitespaces
+   "\r", "\n", "\u2028", "\u2029"];
+
+str = "8675309";
+for (var i = 0, sz = ws.length; i < sz; i++)
+{
+  assertEq(Number.parseInt(ws[i] + str, 10), 8675309);
+  for (var j = 0, sz = ws.length; j < sz; j++)
+  {
+    assertEq(Number.parseInt(ws[i] + ws[j] + str, 10), 8675309,
+             ws[i].charCodeAt(0).toString(16) + ", " +
+             ws[j].charCodeAt(0).toString(16));
+  }
+}
+
+
+/*
+ * 3. Let sign be 1.
+ * 4. If S is not empty and the first character of S is a minus sign -, let
+ *    sign be −1.
+ */
+str = "5552368";
+assertEq(Number.parseInt("-" + str, 10), -Number.parseInt(str, 10));
+assertEq(Number.parseInt(" -" + str, 10), -Number.parseInt(str, 10));
+assertEq(Number.parseInt("-", 10), NaN);
+assertEq(Number.parseInt("", 10), NaN);
+assertEq(Number.parseInt("-0", 10), -0);
+
+
+/*
+ * 5. If S is not empty and the first character of S is a plus sign + or a
+ *    minus sign -, then remove the first character from S.
+ */
+assertEq(Number.parseInt("+12345", 10), 12345);
+assertEq(Number.parseInt(" +12345", 10), 12345);
+assertEq(Number.parseInt("-12345", 10), -12345);
+assertEq(Number.parseInt(" -12345", 10), -12345);
+
+
+/*
+ * 6.  Let R = ToInt32(radix).
+ */
+
+upvar = "";
+str =
+  { toString: function() { if (!upvar) upvar = "string"; return "42"; } };
+radix =
+  { toString: function() { if (!upvar) upvar = "radix"; return "10"; } };
+
+assertEq(Number.parseInt(str, radix), 42);
+assertEq(upvar, "string");
+
+assertEq(Number.parseInt("123", null), 123);
+assertEq(Number.parseInt("123", undefined), 123);
+assertEq(Number.parseInt("123", NaN), 123);
+assertEq(Number.parseInt("123", -0), 123);
+assertEq(Number.parseInt("10", 72057594037927950), 16);
+assertEq(Number.parseInt("10", -4294967292), 4);
+assertEq(Number.parseInt("0x10", 1e308), 16);
+assertEq(Number.parseInt("10", 1e308), 10);
+assertEq(Number.parseInt("10", { valueOf: function() { return 16; } }), 16);
+
+
+/*
+ * 7.  Let stripPrefix be true.
+ * 8.  If R ≠ 0, then
+ *     a. If R < 2 or R > 36, then return NaN.
+ *     b. If R ≠ 16, let stripPrefix be false.
+ * 9.  Else, R = 0
+ *     a. Let R = 10.
+ * 10. If stripPrefix is true, then
+ *     a. If the length of S is at least 2 and the first two characters of S
+ *     are either “0x” or “0X”, then remove the first two characters from S and
+ *     let R = 16.
+ */
+var vs = ["1", "51", "917", "2343", "99963"];
+for (var i = 0, sz = vs.length; i < sz; i++)
+  assertEq(Number.parseInt(vs[i], 0), Number.parseInt(vs[i], 10), "bad " + vs[i]);
+
+assertEq(Number.parseInt("0x10"), 16);
+assertEq(Number.parseInt("0x10", 0), 16);
+assertEq(Number.parseInt("0x10", 16), 16);
+assertEq(Number.parseInt("0x10", 8), 0);
+assertEq(Number.parseInt("-0x10", 16), -16);
+
+assertEq(Number.parseInt("5", 1), NaN);
+assertEq(Number.parseInt("5", 37), NaN);
+assertEq(Number.parseInt("5", { valueOf: function() { return -1; } }), NaN);
+
+
+/*
+ * 11. If S contains any character that is not a radix-R digit, then let Z be
+ *     the substring of S consisting of all characters before the first such
+ *     character; otherwise, let Z be S.
+ * 12. If Z is empty, return NaN.
+ */
+assertEq(Number.parseInt(""), NaN);
+assertEq(Number.parseInt("ohai"), NaN);
+assertEq(Number.parseInt("0xohai"), NaN);
+assertEq(Number.parseInt("-ohai"), NaN);
+assertEq(Number.parseInt("+ohai"), NaN);
+assertEq(Number.parseInt(" ohai"), NaN);
+
+assertEq(Number.parseInt("0xaohai"), 10);
+assertEq(Number.parseInt("hohai", 18), 17);
+
+
+/*
+ * 13. Let mathInt be the mathematical integer value that is represented by Z
+ *     in radix-R notation, using the letters A-Z and a-z for digits with
+ *     values 10 through 35. (However, if R is 10 and Z contains more than 20
+ *     significant digits, every significant digit after the 20th may be
+ *     replaced by a 0 digit, at the option of the implementation; and if R is
+ *     not 2, 4, 8, 10, 16, or 32, then mathInt may be an implementation-
+ *     dependent approximation to the mathematical integer value that is
+ *     represented by Z in radix-R notation.)
+ * 14. Let number be the Number value for mathInt.
+ * 15. Return sign × number.
+ */
+assertEq(Number.parseInt("ohai", 36), 1142154);
+assertEq(Number.parseInt("0ohai", 36), 1142154);
+assertEq(Number.parseInt("00ohai", 36), 1142154);
+assertEq(Number.parseInt("A", 16), 10);
+assertEq(Number.parseInt("0A", 16), 10);
+assertEq(Number.parseInt("00A", 16), 10);
+assertEq(Number.parseInt("A", 17), 10);
+assertEq(Number.parseInt("0A", 17), 10);
+assertEq(Number.parseInt("00A", 17), 10);
+
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("All tests passed!");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Number/parseInt-default-to-decimal.js
@@ -0,0 +1,30 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 886949;
+var summary = "ES6 (draft May 2013) 15.7.3.9 Number.parseInt(string, radix)." +
+			  " Verify that Number.parseInt defaults to decimal.";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+assertEq(Number.parseInt("08"), 8);
+assertEq(Number.parseInt("09"), 9);
+assertEq(Number.parseInt("014"), 14);
+
+function strictParseInt(s) { "use strict"; return Number.parseInt(s); }
+
+assertEq(strictParseInt("08"), 8);
+assertEq(strictParseInt("09"), 9);
+assertEq(strictParseInt("014"), 14);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("All tests passed!");
new file mode 100644
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -14,23 +14,23 @@
 #include "json.h"
 #include "jsweakmap.h"
 
 #include "builtin/Eval.h"
 #include "builtin/Intl.h"
 #include "builtin/MapObject.h"
 #include "builtin/Object.h"
 #include "builtin/RegExp.h"
+#include "vm/RegExpStatics.h"
 
 #include "jscompartmentinlines.h"
 #include "jsfuninlines.h"
 #include "jsobjinlines.h"
 
 #include "vm/GlobalObject-inl.h"
-#include "vm/RegExpStatics-inl.h"
 
 using namespace js;
 
 JSObject *
 js_InitObjectClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -36,17 +36,16 @@
 #include "vm/Debugger.h"
 #include "vm/Shape.h"
 
 #include "jsatominlines.h"
 #include "jsboolinlines.h"
 #include "jsinferinlines.h"
 #include "jsscriptinlines.h"
 
-#include "builtin/Iterator-inl.h"
 #include "ion/IonFrames-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/Probes-inl.h"
 #include "vm/Stack-inl.h"
 
 #include "jsautooplen.h"
 
 #if JS_TRACE_LOGGING
--- a/js/src/vm/PropertyKey.cpp
+++ b/js/src/vm/PropertyKey.cpp
@@ -3,22 +3,23 @@
  * 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/. */
 
 /* PropertyKey implementation details. */
 
 #include "js/PropertyKey.h"
 
+#include "jsatom.h"
+#include "jscntxt.h"
+
 #include "js/RootingAPI.h"
 #include "js/Value.h"
 #include "vm/String.h"
 
-#include "vm/String-inl.h"
-
 using namespace js;
 
 bool
 JS::detail::ToPropertyKeySlow(JSContext *cx, HandleValue v, PropertyKey *key)
 {
     MOZ_ASSERT_IF(v.isInt32(), v.toInt32() < 0);
 
     RootedAtom atom(cx);
--- a/js/src/vm/RegExpStatics.cpp
+++ b/js/src/vm/RegExpStatics.cpp
@@ -5,18 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/RegExpStatics.h"
 
 #include "vm/RegExpStaticsObject.h"
 
 #include "jsobjinlines.h"
 
-#include "vm/RegExpObject-inl.h"
-
 using namespace js;
 
 /*
  * RegExpStatics allocates memory -- in order to keep the statics stored
  * per-global and not leak, we create a js::Class to wrap the C++ instance and
  * provide an appropriate finalizer. We store an instance of that js::Class in
  * a global reserved slot.
  */
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -15,17 +15,16 @@
 
 #include "vm/ForkJoin.h"
 #include "vm/Interpreter.h"
 
 #include "jsfuninlines.h"
 
 #include "vm/BooleanObject-inl.h"
 #include "vm/NumberObject-inl.h"
-#include "vm/RegExpObject-inl.h"
 #include "vm/StringObject-inl.h"
 
 #include "selfhosted.out.h"
 
 using namespace js;
 using namespace js::selfhosted;
 
 namespace js {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -12,17 +12,16 @@
 
 #include "gc/Marking.h"
 #ifdef JS_ION
 #include "ion/BaselineFrame.h"
 #include "ion/IonCompartment.h"
 #endif
 
 #include "vm/Interpreter-inl.h"
-#include "vm/ScopeObject-inl.h"
 #include "vm/Stack-inl.h"
 #include "vm/Probes-inl.h"
 
 using namespace js;
 
 using mozilla::PodCopy;
 
 /*****************************************************************************/
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -9,20 +9,16 @@
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/RangedPtr.h"
 
 #include "gc/Marking.h"
 
 #include "jscompartmentinlines.h"
 
-#ifdef JSGC_GENERATIONAL
-#include "vm/Shape-inl.h"
-#endif
-
 using namespace js;
 
 using mozilla::PodCopy;
 using mozilla::RangedPtr;
 
 bool
 JSString::isShort() const
 {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2553,16 +2553,25 @@ GetPercentHeight(const nsStyleCoord& aSt
              "GetAbsoluteCoord should have handled this");
 
   nsIFrame *f = aFrame->GetContainingBlock();
   if (!f) {
     NS_NOTREACHED("top of frame tree not a containing block");
     return false;
   }
 
+  // During reflow, nsHTMLScrollFrame::ReflowScrolledFrame uses
+  // SetComputedHeight on the reflow state for its child to propagate its
+  // computed height to the scrolled content. So here we skip to the scroll
+  // frame that contains this scrolled content in order to get the same
+  // behavior as layout when computing percentage heights.
+  if (f->StyleContext()->GetPseudo() == nsCSSAnonBoxes::scrolledContent) {
+    f = f->GetParent();
+  }
+
   const nsStylePosition *pos = f->StylePosition();
   nscoord h;
   if (!GetAbsoluteCoord(pos->mHeight, h) &&
       !GetPercentHeight(pos->mHeight, f, h)) {
     NS_ASSERTION(pos->mHeight.GetUnit() == eStyleUnit_Auto ||
                  pos->mHeight.HasPercent(),
                  "unknown height unit");
     nsIAtom* fType = f->GetType();
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1351,16 +1351,20 @@ nsBlockFrame::ComputeFinalSize(const nsH
       // Set status to complete except for overflow
       NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
     }
 
     if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
       if (computedHeightLeftOver > 0 &&
           NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight &&
           aMetrics.height > aReflowState.availableHeight) {
+        if (ShouldAvoidBreakInside(aReflowState)) {
+          aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+          return;
+        }
         // We don't fit and we consumed some of the computed height,
         // so we should consume all the available height and then
         // break.  If our bottom border/padding straddles the break
         // point, then this will increase our height and push the
         // border/padding to the next page/column.
         aMetrics.height = std::max(aReflowState.availableHeight,
                                  aState.mY + nonCarriedOutVerticalMargin);
         NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/829958-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<style>
+.container{
+  overflow: hidden;
+  white-space: nowrap;
+  list-style: none;
+  height: 180px;
+  margin: 0;
+  padding: 0;
+}
+
+.container div{
+  display: inline-block;
+  height: 180px;
+  background: #f00; 
+}
+
+.container img{ height: 180px; }
+</style>
+<body>
+    <div class='container'>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+    </div>
+</body>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/829958.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+    Test that the intrinsic width is properly calculated for images with
+    percent height with a percent height parent when their container has
+    overflow not visible.
+-->
+<style>
+.container{
+  overflow: hidden;
+  white-space: nowrap;
+  list-style: none;
+  height: 180px;
+  margin: 0;
+  padding: 0;
+}
+
+.container div{
+  display: inline-block;
+  height: 100%;
+  background: #f00; 
+}
+
+.container img{ height: 100%; }
+</style>
+<body>
+    <div class='container'>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+        <div><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEsCAMAAADaaRXwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowNDBEMjk2RkUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowNDBEMjk3MEUwREExMUUyQURFMTlFN0Y5RjRDNTgyQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA0MEQyOTZERTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0MEQyOTZFRTBEQTExRTJBREUxOUU3RjlGNEM1ODJDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KmJqgwAAAAZQTFRFAP8AAAAAbwN+QwAAAI5JREFUeNrswTEBAAAAwqD1T20JT6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBjAgwA1fsAAbWxRKUAAAAASUVORK5CYII='/></div>
+    </div>
+</body>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1744,16 +1744,17 @@ skip-if(B2G) fuzzy-if(Android,4,61) == 8
 == 816458-1.html 816458-1-ref.html
 == 816948-1.html 816948-1-ref.html
 == 817019-1.html about:blank
 skip-if(B2G) == 818276-1.html 818276-1-ref.html
 == 825999.html 825999-ref.html
 == 827577-1a.html 827577-1-ref.html
 == 827577-1b.html 827577-1-ref.html
 == 827799-1.html about:blank
+== 829958.html 829958-ref.html
 fails-if(Android&&AndroidVersion<15) == 836844-1.html 836844-1-ref.html
 == 841192-1.html 841192-1-ref.html
 == 844178.html 844178-ref.html
 == 846144-1.html 846144-1-ref.html
 == 847850-1.html 847850-1-ref.html
 == 848421-1.html 848421-1-ref.html
 test-pref(layout.css.flexbox.enabled,true) == 849407-1.html 849407-1-ref.html
 == 849996-1.html 849996-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-14-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en-US" class="reftest-print">
+<head>
+  <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
+  <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
+  <meta name="flags" content="paged">
+<style type="text/css">
+@page { size:5in 3in; margin:0.5in; }
+p { height: 1in; width: 1in; margin:0; background-color:blue; }
+.test { page-break-before:always; height:1.5in; }
+</style>
+</head>
+<body>
+<p>1</p>
+<p class="test">2</p>
+<p class="test">3</p>
+</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-14.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en-US" class="reftest-print">
+<head>
+  <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
+  <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
+  <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <meta name="flags" content="paged">
+<style type="text/css">
+@page { size:5in 3in; margin:0.5in; }
+p { height: 1in; width: 1in; margin:0; background-color:blue; }
+.test { page-break-inside:avoid; height:1.5in; }
+</style>
+</head>
+<body>
+<p>1</p>
+<p class="test">2</p>
+<p class="test">3</p>
+</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-15-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en-US" class="reftest-print">
+<head>
+  <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
+  <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
+  <meta name="flags" content="paged">
+<style type="text/css">
+@page { size:5in 3in; margin:0.5in; }
+p { height: 1in; width: 1in; margin:0; background-color:blue; }
+.test { page-break-before:always; height:2.5in; }
+</style>
+</head>
+<body>
+<p>1</p>
+<p class="test">2</p>
+<p class="test">4</p>
+</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-15.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en-US" class="reftest-print">
+<head>
+  <title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
+  <link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
+  <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
+  <meta name="flags" content="paged">
+<style type="text/css">
+@page { size:5in 3in; margin:0.5in; }
+p { height: 1in; width: 1in; margin:0; background-color:blue; }
+.test { page-break-inside:avoid; height:2.5in; }
+</style>
+</head>
+<body>
+<p>1</p>
+<p class="test">2</p>
+<p class="test">4</p>
+</div>
+
+</body>
+</html>
--- a/layout/reftests/w3c-css/submitted/css21/pagination/reftest.list
+++ b/layout/reftests/w3c-css/submitted/css21/pagination/reftest.list
@@ -6,16 +6,18 @@
 == moz-css21-block-page-break-inside-avoid-6.html moz-css21-block-page-break-inside-avoid-ref.html
 == moz-css21-block-page-break-inside-avoid-7.html moz-css21-block-page-break-inside-avoid-ref.html
 == moz-css21-block-page-break-inside-avoid-8.html moz-css21-block-page-break-inside-avoid-8-ref.html
 == moz-css21-block-page-break-inside-avoid-9.html moz-css21-block-page-break-inside-avoid-ref.html
 == moz-css21-block-page-break-inside-avoid-10.html moz-css21-block-page-break-inside-avoid-ref.html
 == moz-css21-block-page-break-inside-avoid-11.html moz-css21-block-page-break-inside-avoid-ref.html
 == moz-css21-block-page-break-inside-avoid-12.html moz-css21-block-page-break-inside-avoid-ref.html
 == moz-css21-block-page-break-inside-avoid-13.html moz-css21-block-page-break-inside-avoid-8-ref.html
+== moz-css21-block-page-break-inside-avoid-14.html moz-css21-block-page-break-inside-avoid-14-ref.html
+== moz-css21-block-page-break-inside-avoid-15.html moz-css21-block-page-break-inside-avoid-15-ref.html
 == moz-css21-table-page-break-inside-avoid-1.html moz-css21-table-page-break-inside-avoid-ref.html
 == moz-css21-table-page-break-inside-avoid-2.html moz-css21-table-page-break-inside-avoid-2-ref.html
 == moz-css21-table-page-break-inside-avoid-3.html moz-css21-table-page-break-inside-avoid-3-ref.html
 == moz-css21-table-page-break-inside-avoid-4.html moz-css21-table-page-break-inside-avoid-4-ref.html
 == moz-css21-table-page-break-inside-avoid-5.html moz-css21-table-page-break-inside-avoid-5-ref.html
 == moz-css21-float-page-break-inside-avoid-1.html moz-css21-table-page-break-inside-avoid-ref.html
 == moz-css21-float-page-break-inside-avoid-2.html moz-css21-float-page-break-inside-avoid-2-ref.html
 == moz-css21-float-page-break-inside-avoid-3.html moz-css21-block-page-break-inside-avoid-ref.html
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -109,16 +109,17 @@ NS_QUERYFRAME_TAIL_INHERITING(nsLeafBoxF
 
 // Constructor
 nsTreeBodyFrame::nsTreeBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 :nsLeafBoxFrame(aPresShell, aContext),
  mSlots(nullptr),
  mTopRowIndex(0),
  mPageLength(0),
  mHorzPosition(0),
+ mOriginalHorzWidth(-1),
  mHorzWidth(0),
  mAdjustWidth(0),
  mRowHeight(0),
  mIndentation(0),
  mStringWidth(-1),
  mUpdateBatchNest(0),
  mRowCount(0),
  mMouseOverRow(-1),
@@ -380,25 +381,38 @@ nsTreeBodyFrame::EnsureView()
         // view current.
         box->RemoveProperty(NS_LITERAL_STRING("topRow").get());
       }
     }
   }
 }
 
 void
+nsTreeBodyFrame::ManageReflowCallback(const nsRect& aRect, nscoord aHorzWidth)
+{
+  if (!mReflowCallbackPosted &&
+      (!aRect.IsEqualEdges(mRect) || mHorzWidth != aHorzWidth)) {
+    PresContext()->PresShell()->PostReflowCallback(this);
+    mReflowCallbackPosted = true;
+    mOriginalHorzWidth = mHorzWidth;
+  }
+  else if (mReflowCallbackPosted &&
+           mHorzWidth != aHorzWidth && mOriginalHorzWidth == aHorzWidth) {
+    PresContext()->PresShell()->CancelReflowCallback(this);
+    mReflowCallbackPosted = false;
+    mOriginalHorzWidth = -1;
+  }
+}
+
+void
 nsTreeBodyFrame::SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
                            bool aRemoveOverflowArea)
 {
   nscoord horzWidth = CalcHorzWidth(GetScrollParts());
-  if ((!aRect.IsEqualEdges(mRect) || mHorzWidth != horzWidth) && !mReflowCallbackPosted) {
-    mReflowCallbackPosted = true;
-    PresContext()->PresShell()->PostReflowCallback(this);
-  }
-
+  ManageReflowCallback(aRect, horzWidth);
   mHorzWidth = horzWidth;
 
   nsLeafBoxFrame::SetBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
 }
 
 
 bool
 nsTreeBodyFrame::ReflowFinished()
--- a/layout/xul/tree/nsTreeBodyFrame.h
+++ b/layout/xul/tree/nsTreeBodyFrame.h
@@ -115,16 +115,18 @@ public:
                                 int32_t *aX, int32_t *aY,
                                 int32_t *aWidth, int32_t *aHeight);
   nsresult IsCellCropped(int32_t aRow, nsITreeColumn *aCol, bool *aResult);
   nsresult RowCountChanged(int32_t aIndex, int32_t aCount);
   nsresult BeginUpdateBatch();
   nsresult EndUpdateBatch();
   nsresult ClearStyleAndImageCaches();
 
+  void ManageReflowCallback(const nsRect& aRect, nscoord aHorzWidth);
+
   virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
   virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
                          bool aRemoveOverflowArea = false) MOZ_OVERRIDE;
 
   // nsIReflowCallback
   virtual bool ReflowFinished() MOZ_OVERRIDE;
   virtual void ReflowCallbackCanceled() MOZ_OVERRIDE;
 
@@ -571,16 +573,23 @@ protected: // Data Members
   // The index of the first visible row and the # of rows visible onscreen.  
   // The tree only examines onscreen rows, starting from
   // this index and going up to index+pageLength.
   int32_t mTopRowIndex;
   int32_t mPageLength;
 
   // The horizontal scroll position
   nscoord mHorzPosition;
+
+  // The original desired horizontal width before changing it and posting a
+  // reflow callback. In some cases, the desired horizontal width can first be
+  // different from the current desired horizontal width, only to return to
+  // the same value later during the same reflow. In this case, we can cancel
+  // the posted reflow callback and prevent an unnecessary reflow.
+  nscoord mOriginalHorzWidth;
   // Our desired horizontal width (the width for which we actually have tree
   // columns).
   nscoord mHorzWidth;
   // The amount by which to adjust the width of the last cell.
   // This depends on whether or not the columnpicker and scrollbars are present.
   nscoord mAdjustWidth;
 
   // Cached heights and indent info.
--- a/media/webrtc/signaling/src/sipcc/core/gsm/gsm_sdp.c
+++ b/media/webrtc/signaling/src/sipcc/core/gsm/gsm_sdp.c
@@ -4805,17 +4805,17 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t 
             unsupported_line = TRUE;
             break;
         }
 
         /* TODO (abr) -- temporarily hardcode rtcb-fb attributes to match our
            actual behavior. This really needs to be a negotiation, with the
            results of the negotiation propagating into the codec configuration.
            See Bug 880067. */
-        if (media_type == SDP_MEDIA_VIDEO) {
+        if (media && media_type == SDP_MEDIA_VIDEO) {
             gsmsdp_set_rtcp_fb_nack_attribute(media->level, sdp_p->src_sdp,
                                               SDP_ALL_PAYLOADS,
                                               SDP_RTCP_FB_NACK_UNSPECIFIED);
             gsmsdp_set_rtcp_fb_ccm_attribute(media->level, sdp_p->src_sdp,
                                              SDP_ALL_PAYLOADS,
                                              SDP_RTCP_FB_CCM_FIR);
         }
 
--- a/mobile/android/base/GeckoAccessibility.java
+++ b/mobile/android/base/GeckoAccessibility.java
@@ -195,19 +195,20 @@ public class GeckoAccessibility {
                 sVirtualCursorNode.setBoundsInParent(relativeBounds);
                 int[] locationOnScreen = new int[2];
                 view.getLocationOnScreen(locationOnScreen);
                 Rect screenBounds = new Rect(relativeBounds);
                 screenBounds.offset(locationOnScreen[0], locationOnScreen[1]);
                 sVirtualCursorNode.setBoundsInScreen(screenBounds);
             }
 
-            final String brailleText = message.optString("brailleText");
-            if (!brailleText.isEmpty()) {
-                sendBrailleText(view, brailleText);
+            final JSONObject braille = message.optJSONObject("brailleOutput");
+            if (braille != null) {
+                sendBrailleText(view, braille.optString("text"),
+                                braille.optInt("selectionStart"), braille.optInt("selectionEnd"));
             }
 
             ThreadUtils.postToUiThread(new Runnable() {
                     @Override
                     public void run() {
                         // If this is an accessibility focus, a lot of internal voodoo happens so we perform an
                         // accessibility focus action on the view, and it in turn sends the right events.
                         switch (eventType) {
@@ -229,23 +230,23 @@ public class GeckoAccessibility {
                             break;
                         }
                     }
                 });
 
         }
     }
 
-    private static void sendBrailleText(final View view, final String text) {
+    private static void sendBrailleText(final View view, final String text, final int selectionStart, final int selectionEnd) {
         AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(view, VIRTUAL_CURSOR_POSITION);
         WriteData data = WriteData.forInfo(info);
         data.setText(text);
-        // Set the focus blink
-        data.setSelectionStart(0);
-        data.setSelectionEnd(0);
+        // Set either the focus blink or the current caret position/selection
+        data.setSelectionStart(selectionStart);
+        data.setSelectionEnd(selectionEnd);
         sSelfBrailleClient.write(data);
     }
 
     public static void setDelegate(LayerView layerview) {
         // Only use this delegate in Jelly Bean.
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
             layerview.setAccessibilityDelegate(new GeckoAccessibilityDelegate());
             layerview.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
--- a/mobile/android/chrome/content/browser.xul
+++ b/mobile/android/chrome/content/browser.xul
@@ -1,13 +1,14 @@
 <?xml version="1.0"?>
 <!-- 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/. -->
 
+<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
 
 <window id="main-window"
         onload="BrowserApp.startup();"
         windowtype="navigator:browser"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <script type="application/javascript" src="chrome://browser/content/browser.js"/>
   <script type="application/javascript" src="chrome://browser/content/downloads.js"/>
--- a/security/manager/boot/src/nsSTSPreloadList.errors
+++ b/security/manager/boot/src/nsSTSPreloadList.errors
@@ -3,16 +3,17 @@ aladdinschools.appspot.com: did not rece
 alpha.irccloud.com: could not connect to host
 api.mega.co.nz: could not connect to host
 api.recurly.com: did not receive HSTS header
 api.simple.com: did not receive HSTS header
 apis.google.com: did not receive HSTS header
 appengine.google.com: did not receive HSTS header
 betnet.fr: could not connect to host
 bigshinylock.minazo.net: could not connect to host
+blueseed.co: did not receive HSTS header
 braintreegateway.com: could not connect to host
 braintreepayments.com: did not receive HSTS header
 browserid.org: did not receive HSTS header
 carlolly.co.uk: did not receive HSTS header
 cert.se: max-age too low: 2628001
 checkout.google.com: did not receive HSTS header
 chrome-devtools-frontend.appspot.com: did not receive HSTS header
 chrome.google.com: did not receive HSTS header
@@ -45,23 +46,25 @@ iop.intuit.com: max-age too low: 86400
 irccloud.com: did not receive HSTS header
 jitsi.org: did not receive HSTS header
 jottit.com: did not receive HSTS header
 kiwiirc.com: max-age too low: 5256000
 ledgerscope.net: max-age too low: 86400
 lists.mayfirst.org: did not receive HSTS header
 logentries.com: did not receive HSTS header
 mail.google.com: did not receive HSTS header
+makeyourlaws.org: did not receive HSTS header
 market.android.com: did not receive HSTS header
 my.alfresco.com: did not receive HSTS header
 mydigipass.com: did not receive HSTS header
 neonisi.com: could not connect to host
 openshift.redhat.com: did not receive HSTS header
 ottospora.nl: could not connect to host
 packagist.org: max-age too low: 2592000
+passwd.io: could not connect to host
 paypal.com: max-age too low: 14400
 piratenlogin.de: could not connect to host
 plus.google.com: did not receive HSTS header
 plus.sandbox.google.com: did not receive HSTS header
 profiles.google.com: did not receive HSTS header
 romab.com: max-age too low: 2628000
 sah3.net: could not connect to host
 script.google.com: did not receive HSTS header
--- a/security/manager/boot/src/nsSTSPreloadList.inc
+++ b/security/manager/boot/src/nsSTSPreloadList.inc
@@ -3,36 +3,36 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
 /* nsStrictTransportSecurityService.cpp, you shouldn't be #including it.     */
 /*****************************************************************************/
 
 #include "mozilla/StandardInteger.h"
-const PRTime gPreloadListExpirationTime = INT64_C(1383992137406000);
+const PRTime gPreloadListExpirationTime = INT64_C(1384596271277000);
 
 class nsSTSPreload
 {
   public:
     const char *mHost;
     const bool mIncludeSubdomains;
 };
 
 static const nsSTSPreload kSTSPreloadList[] = {
   { "alpha.irccloud.com", false },
   { "api.intercom.io", false },
   { "app.recurly.com", false },
   { "arivo.com.br", true },
+  { "bank.simple.com", false },
   { "bassh.net", true },
   { "bccx.com", true },
   { "blog.cyveillance.com", true },
   { "blog.linode.com", false },
   { "blog.torproject.org", false },
-  { "blueseed.co", false },
   { "bugzilla.mozilla.org", true },
   { "business.medbank.com.mt", true },
   { "carezone.com", false },
   { "check.torproject.org", false },
   { "cloudsecurityalliance.org", true },
   { "conformal.com", true },
   { "controlcenter.gigahost.dk", true },
   { "crate.io", true },
@@ -64,17 +64,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "linode.com", false },
   { "linx.net", false },
   { "lockify.com", true },
   { "login.persona.org", true },
   { "login.sapo.pt", true },
   { "logotype.se", true },
   { "lookout.com", false },
   { "luneta.nearbuysystems.com", false },
-  { "makeyourlaws.org", false },
   { "manager.linode.com", false },
   { "mattmccutchen.net", true },
   { "mega.co.nz", false },
   { "members.mayfirst.org", false },
   { "members.nearlyfreespeech.net", false },
   { "my.onlime.ch", false },
   { "mylookout.com", false },
   { "neg9.org", false },
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -916,31 +916,31 @@ cryptojs_ReadArgsAndGenerateKey(JSContex
                                 PK11SlotInfo **slot, bool willEscrow)
 {
   JSString  *jsString;
   JSAutoByteString params, keyGenAlg;
   int    keySize;
   nsresult  rv;
 
   if (!JSVAL_IS_INT(argv[0])) {
-    JS_ReportError(cx, "%s%s\n", JS_ERROR,
+    JS_ReportError(cx, "%s%s", JS_ERROR,
                    "passed in non-integer for key size");
     return NS_ERROR_FAILURE;
   }
   keySize = JSVAL_TO_INT(argv[0]);
   if (!JSVAL_IS_NULL(argv[1])) {
     jsString = JS_ValueToString(cx,argv[1]);
     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
     argv[1] = STRING_TO_JSVAL(jsString);
     params.encodeLatin1(cx, jsString);
     NS_ENSURE_TRUE(!!params, NS_ERROR_OUT_OF_MEMORY);
   }
 
   if (JSVAL_IS_NULL(argv[2])) {
-    JS_ReportError(cx,"%s%s\n", JS_ERROR,
+    JS_ReportError(cx,"%s%s", JS_ERROR,
              "key generation type not specified");
     return NS_ERROR_FAILURE;
   }
   jsString = JS_ValueToString(cx, argv[2]);
   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
   argv[2] = STRING_TO_JSVAL(jsString);
   keyGenAlg.encodeLatin1(cx, jsString);
   NS_ENSURE_TRUE(!!keyGenAlg, NS_ERROR_OUT_OF_MEMORY);
@@ -1858,23 +1858,23 @@ nsCrypto::GenerateCRMFRequest(nsIDOMCRMF
   NS_ENSURE_SUCCESS(nrv, nrv);
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
 
   /*
    * Get all of the parameters.
    */
   if (argc < 5 || ((argc-5) % 3) != 0) {
-    JS_ReportError(cx, "%s", "%s%s\n", JS_ERROR,
+    JS_ReportError(cx, "%s%s", JS_ERROR,
                   "incorrect number of parameters");
     return NS_ERROR_FAILURE;
   }
   
   if (JSVAL_IS_NULL(argv[0])) {
-    JS_ReportError(cx, "%s%s\n", JS_ERROR, "no DN specified");
+    JS_ReportError(cx, "%s%s", JS_ERROR, "no DN specified");
     return NS_ERROR_FAILURE;
   }
   
   JSString *jsString = JS_ValueToString(cx,argv[0]);
   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
   argv[0] = STRING_TO_JSVAL(jsString);
   JSAutoByteString reqDN(cx,jsString);
   NS_ENSURE_TRUE(!!reqDN, NS_ERROR_OUT_OF_MEMORY);
@@ -1899,17 +1899,17 @@ nsCrypto::GenerateCRMFRequest(nsIDOMCRMF
   if (!JSVAL_IS_NULL(argv[3])) {
     jsString     = JS_ValueToString(cx, argv[3]);
     NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
     argv[3] = STRING_TO_JSVAL(jsString);
     eaCert.encodeLatin1(cx, jsString);
     NS_ENSURE_TRUE(!!eaCert, NS_ERROR_OUT_OF_MEMORY);
   }
   if (JSVAL_IS_NULL(argv[4])) {
-    JS_ReportError(cx, "%s%s\n", JS_ERROR, "no completion "
+    JS_ReportError(cx, "%s%s", JS_ERROR, "no completion "
                    "function specified");
     return NS_ERROR_FAILURE;
   }
   jsString = JS_ValueToString(cx, argv[4]);
   NS_ENSURE_TRUE(jsString, NS_ERROR_OUT_OF_MEMORY);
   argv[4] = STRING_TO_JSVAL(jsString);
   JSAutoByteString jsCallback(cx, jsString);
   NS_ENSURE_TRUE(!!jsCallback, NS_ERROR_OUT_OF_MEMORY);
@@ -2497,17 +2497,17 @@ nsCrypto::SignText(const nsAString& aStr
   if (!cx) {
     aResult.Append(internalError);
 
     return NS_OK;
   }
 
   if (!aCaOption.EqualsLiteral("auto") &&
       !aCaOption.EqualsLiteral("ask")) {
-    JS_ReportError(cx, "%s%s\n", JS_ERROR, "caOption argument must be ask or auto");
+    JS_ReportError(cx, "%s%s", JS_ERROR, "caOption argument must be ask or auto");
 
     aResult.Append(internalError);
 
     return NS_OK;
   }
 
   // It was decided to always behave as if "ask" were specified.
   // XXX Should we warn in the JS Console for auto?
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -8,33 +8,27 @@
 
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "nsNSSComponent.h"
 #include "nsNSSIOLayer.h"
 #include "nsIWebProgressListener.h"
 #include "nsProtectedAuthThread.h"
 #include "nsITokenDialogs.h"
-#include "nsNSSShutDown.h"
 #include "nsIUploadChannel.h"
-#include "nsThreadUtils.h"
 #include "nsIPrompt.h"
 #include "nsProxyRelease.h"
 #include "PSMRunnable.h"
 #include "ScopedNSSTypes.h"
 #include "nsIConsoleService.h"
 #include "nsIHttpChannelInternal.h"
-#include "nsCRT.h"
 #include "nsNetUtil.h"
 #include "SharedSSLState.h"
-
 #include "ssl.h"
 #include "sslproto.h"
-#include "ocsp.h"
-#include "nssb64.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gPIPNSSLog;
@@ -1001,20 +995,17 @@ CanFalseStartCallback(PRFileDesc* fd, vo
   infoObject->NoteTimeUntilReady();
   *canFalseStart = true;
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CanFalseStartCallback [%p] ok\n", fd));
   return SECSuccess;
 }
 
 void HandshakeCallback(PRFileDesc* fd, void* client_data) {
   nsNSSShutDownPreventionLock locker;
-  int32_t sslStatus;
-  char* cipherName = nullptr;
-  int32_t keyLength;
-  int32_t encryptBits;
+  SECStatus rv;
 
   nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
 
   // certificate validation sets FirstServerHelloReceived, so if that flag
   // is absent at handshake time we have a resumed session. Check this before
   // PreliminaryHandshakeDone() because that function also sets that flag.
   bool isResumedSession = !(infoObject->GetFirstServerHelloReceived());
 
@@ -1023,57 +1014,53 @@ void HandshakeCallback(PRFileDesc* fd, v
   // need the handshake to be completed.
   PreliminaryHandshakeDone(fd);
 
   // If the handshake completed, then we know the site is TLS tolerant (if this
   // was a TLS connection).
   nsSSLIOLayerHelpers& ioLayerHelpers = infoObject->SharedState().IOLayerHelpers();
   ioLayerHelpers.rememberTolerantSite(infoObject);
 
-  if (SECSuccess != SSL_SecurityStatus(fd, &sslStatus, &cipherName, &keyLength,
-                                       &encryptBits, nullptr, nullptr)) {
-    return;
+  PRBool siteSupportsSafeRenego;
+  rv = SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn,
+                                        &siteSupportsSafeRenego);
+  MOZ_ASSERT(rv == SECSuccess);
+  if (rv != SECSuccess) {
+    siteSupportsSafeRenego = false;
+  }
+
+  if (siteSupportsSafeRenego ||
+      !ioLayerHelpers.treatUnsafeNegotiationAsBroken()) {
+    infoObject->SetSecurityState(nsIWebProgressListener::STATE_IS_SECURE |
+                                 nsIWebProgressListener::STATE_SECURE_HIGH);
+  } else {
+    infoObject->SetSecurityState(nsIWebProgressListener::STATE_IS_BROKEN);
   }
 
-  int32_t secStatus;
-  if (sslStatus == SSL_SECURITY_STATUS_OFF)
-    secStatus = nsIWebProgressListener::STATE_IS_BROKEN;
-  else
-    secStatus = nsIWebProgressListener::STATE_IS_SECURE
-              | nsIWebProgressListener::STATE_SECURE_HIGH;
-
-  PRBool siteSupportsSafeRenego;
-  if (SSL_HandshakeNegotiatedExtension(fd, ssl_renegotiation_info_xtn, &siteSupportsSafeRenego) != SECSuccess
-      || !siteSupportsSafeRenego) {
-
-    bool wantWarning = (ioLayerHelpers.getWarnLevelMissingRFC5746() > 0);
+  // XXX Bug 883674: We shouldn't be formatting messages here in PSM; instead,
+  // we should set a flag on the channel that higher (UI) level code can check
+  // to log the warning. In particular, these warnings should go to the web
+  // console instead of to the error console. Also, the warning is not
+  // localized.
+  if (!siteSupportsSafeRenego &&
+      ioLayerHelpers.getWarnLevelMissingRFC5746() > 0) {
+    nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+    if (console) {
+      nsXPIDLCString hostName;
+      infoObject->GetHostName(getter_Copies(hostName));
 
-    nsCOMPtr<nsIConsoleService> console;
-    if (infoObject && wantWarning) {
-      console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-      if (console) {
-        nsXPIDLCString hostName;
-        infoObject->GetHostName(getter_Copies(hostName));
-
-        nsAutoString msg;
-        msg.Append(NS_ConvertASCIItoUTF16(hostName));
-        msg.Append(NS_LITERAL_STRING(" : server does not support RFC 5746, see CVE-2009-3555"));
-
-        console->LogStringMessage(msg.get());
-      }
-    }
-    if (ioLayerHelpers.treatUnsafeNegotiationAsBroken()) {
-      secStatus = nsIWebProgressListener::STATE_IS_BROKEN;
+      nsAutoString msg;
+      msg.Append(NS_ConvertASCIItoUTF16(hostName));
+      msg.Append(NS_LITERAL_STRING(" : server does not support RFC 5746, see CVE-2009-3555"));
+      console->LogStringMessage(msg.get());
     }
   }
 
   ScopedCERTCertificate serverCert(SSL_PeerCertificate(fd));
 
-  infoObject->SetSecurityState(secStatus);
-
   /* Set the SSL Status information */
   RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
   if (!status) {
     status = new nsSSLStatus();
     infoObject->SetSSLStatus(status);
   }
 
   RememberCertErrorsTable::GetInstance().LookupCertErrorBits(infoObject,
@@ -1103,215 +1090,38 @@ void HandshakeCallback(PRFileDesc* fd, v
     }
     else {
       PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
               ("HandshakeCallback using NEW cert %p\n", nssc.get()));
       status->mServerCert = nssc;
     }
   }
 
-  status->mHaveKeyLengthAndCipher = true;
-  status->mKeyLength = keyLength;
-  status->mSecretKeyLength = encryptBits;
-  status->mCipherName.Assign(cipherName);
-
   SSLChannelInfo channelInfo;
-  if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) == SECSuccess) {
+  rv = SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo));
+  MOZ_ASSERT(rv == SECSuccess);
+  if (rv == SECSuccess) {
     // Get the protocol version for telemetry
     // 0=ssl3, 1=tls1, 2=tls1.1, 3=tls1.2
     unsigned int versionEnum = channelInfo.protocolVersion & 0xFF;
     Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum);
 
     SSLCipherSuiteInfo cipherInfo;
-    if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
-                               sizeof (cipherInfo)) == SECSuccess) {
+    rv = SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
+                                sizeof cipherInfo);
+    MOZ_ASSERT(rv == SECSuccess);
+    if (rv == SECSuccess) {
+      status->mHaveKeyLengthAndCipher = true;
+      status->mKeyLength = cipherInfo.symKeyBits;
+      status->mSecretKeyLength = cipherInfo.effectiveKeyBits;
+      status->mCipherName.Assign(cipherInfo.cipherSuiteName);
+
       // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4
       Telemetry::Accumulate(Telemetry::SSL_KEY_EXCHANGE_ALGORITHM,
                             cipherInfo.keaType);
       infoObject->SetKEAUsed(cipherInfo.keaType);
       infoObject->SetSymmetricCipherUsed(cipherInfo.symCipher);
     }
   }
 
   infoObject->NoteTimeUntilReady();
   infoObject->SetHandshakeCompleted(isResumedSession);
-
-  PORT_Free(cipherName);
 }
-
-struct OCSPDefaultResponders {
-    const char *issuerName_string;
-    CERTName *issuerName;
-    const char *issuerKeyID_base64;
-    SECItem *issuerKeyID;
-    const char *ocspUrl;
-};
-
-static struct OCSPDefaultResponders myDefaultOCSPResponders[] = {
-  /* COMODO */
-  {
-    "CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE",
-    nullptr, "rb2YejS0Jvf6xCZU7wO94CTLVBo=", nullptr,
-    "http://ocsp.comodoca.com"
-  },
-  {
-    "CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB",
-    nullptr, "C1jli8ZMFTekQKkwqSG+RzZaVv8=", nullptr,
-    "http://ocsp.comodoca.com"
-  },
-  {
-    "CN=COMODO EV SGC CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB",
-    nullptr, "f/ZMNigUrs0eN6/eWvJbw6CsK/4=", nullptr,
-    "http://ocsp.comodoca.com"
-  },
-  {
-    "CN=COMODO EV SSL CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB",
-    nullptr, "aRZJ7LZ1ZFrpAyNgL1RipTRcPuI=", nullptr,
-    "http://ocsp.comodoca.com"
-  },
-  {
-    "CN=UTN - DATACorp SGC,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US",
-    nullptr, "UzLRs89/+uDxoF2FTpLSnkUdtE8=", nullptr,
-    "http://ocsp.usertrust.com"
-  },
-  {
-    "CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US",
-    nullptr, "oXJfJhsomEOVXQc31YWWnUvSw0U=", nullptr,
-    "http://ocsp.usertrust.com"
-  },
-  /* Network Solutions */
-  {
-    "CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US",
-    nullptr, "ITDJ+wDXTpjah6oq0KcusUAxp0w=", nullptr,
-    "http://ocsp.netsolssl.com"
-  },
-  {
-    "CN=Network Solutions EV SSL CA,O=Network Solutions L.L.C.,C=US",
-    nullptr, "tk6FnYQfGx3UUolOB5Yt+d7xj8w=", nullptr,
-    "http://ocsp.netsolssl.com"
-  },
-  /* GlobalSign */
-  {
-    "CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE",
-    nullptr, "YHtmGkUNl8qJUC99BM00qP/8/Us=", nullptr,
-    "http://ocsp.globalsign.com/ExtendedSSLCACross"
-  },
-  {
-    "CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R2",
-    nullptr, "m+IHV2ccHsBqBt5ZtJot39wZhi4=", nullptr,
-    "http://ocsp.globalsign.com/ExtendedSSLCA"
-  },
-  {
-    "CN=GlobalSign Extended Validation CA,O=GlobalSign,OU=Extended Validation CA",
-    nullptr, "NLH5yYxrNUTMCGkK7uOjuVy/FuA=", nullptr,
-    "http://ocsp.globalsign.com/ExtendedSSL"
-  },
-  /* Trustwave */
-  {
-    "CN=SecureTrust CA,O=SecureTrust Corporation,C=US",
-    nullptr, "QjK2FvoE/f5dS3rD/fdMQB1aQ68=", nullptr,
-    "http://ocsp.trustwave.com"
-  }
-};
-
-static const unsigned int numResponders =
-    (sizeof myDefaultOCSPResponders) / (sizeof myDefaultOCSPResponders[0]);
-
-static CERT_StringFromCertFcn oldOCSPAIAInfoCallback = nullptr;
-
-/*
- * See if we have a hard-coded default responder for this certificate's
- * issuer (unless this certificate is a root certificate).
- *
- * The result needs to be freed (PORT_Free) when no longer in use.
- */
-char* MyAlternateOCSPAIAInfoCallback(CERTCertificate *cert) {
-  if (cert && !cert->isRoot) {
-    unsigned int i;
-    for (i=0; i < numResponders; i++) {
-      if (!(myDefaultOCSPResponders[i].issuerName));
-      else if (!(myDefaultOCSPResponders[i].issuerKeyID));
-      else if (!(cert->authKeyID));
-      else if (CERT_CompareName(myDefaultOCSPResponders[i].issuerName,
-                                &(cert->issuer)) != SECEqual);
-      else if (SECITEM_CompareItem(myDefaultOCSPResponders[i].issuerKeyID,
-                                   &(cert->authKeyID->keyID)) != SECEqual);
-      else        // Issuer Name and Key Identifier match, so use this OCSP URL.
-        return PORT_Strdup(myDefaultOCSPResponders[i].ocspUrl);
-    }
-  }
-
-  // If we've not found a hard-coded default responder, chain to the old
-  // callback function (if there is one).
-  if (oldOCSPAIAInfoCallback)
-    return (*oldOCSPAIAInfoCallback)(cert);
-
-  return nullptr;
-}
-
-void cleanUpMyDefaultOCSPResponders() {
-  unsigned int i;
-
-  for (i=0; i < numResponders; i++) {
-    if (myDefaultOCSPResponders[i].issuerName) {
-      CERT_DestroyName(myDefaultOCSPResponders[i].issuerName);
-      myDefaultOCSPResponders[i].issuerName = nullptr;
-    }
-    if (myDefaultOCSPResponders[i].issuerKeyID) {
-      SECITEM_FreeItem(myDefaultOCSPResponders[i].issuerKeyID, true);
-      myDefaultOCSPResponders[i].issuerKeyID = nullptr;
-    }
-  }
-}
-
-SECStatus RegisterMyOCSPAIAInfoCallback() {
-  // Prevent multiple registrations.
-  if (myDefaultOCSPResponders[0].issuerName)
-    return SECSuccess;                 // Already registered ok.
-
-  // Populate various fields in the myDefaultOCSPResponders[] array.
-  SECStatus rv = SECFailure;
-  unsigned int i;
-  for (i=0; i < numResponders; i++) {
-    // Create a CERTName structure from the issuer name string.
-    myDefaultOCSPResponders[i].issuerName = CERT_AsciiToName(
-      const_cast<char*>(myDefaultOCSPResponders[i].issuerName_string));
-    if (!(myDefaultOCSPResponders[i].issuerName))
-      goto loser;
-    // Create a SECItem from the Base64 authority key identifier keyID.
-    myDefaultOCSPResponders[i].issuerKeyID = NSSBase64_DecodeBuffer(nullptr,
-          nullptr, myDefaultOCSPResponders[i].issuerKeyID_base64,
-          (uint32_t)PORT_Strlen(myDefaultOCSPResponders[i].issuerKeyID_base64));
-    if (!(myDefaultOCSPResponders[i].issuerKeyID))
-      goto loser;
-  }
-
-  // Register our alternate OCSP Responder URL lookup function.
-  rv = CERT_RegisterAlternateOCSPAIAInfoCallBack(MyAlternateOCSPAIAInfoCallback,
-                                                 &oldOCSPAIAInfoCallback);
-  if (rv != SECSuccess)
-    goto loser;
-
-  return SECSuccess;
-
-loser:
-  cleanUpMyDefaultOCSPResponders();
-  return rv;
-}
-
-SECStatus UnregisterMyOCSPAIAInfoCallback() {
-  SECStatus rv;
-
-  // Only allow unregistration if we're already registered.
-  if (!(myDefaultOCSPResponders[0].issuerName))
-    return SECFailure;
-
-  // Unregister our alternate OCSP Responder URL lookup function.
-  rv = CERT_RegisterAlternateOCSPAIAInfoCallBack(oldOCSPAIAInfoCallback,
-                                                 nullptr);
-  if (rv != SECSuccess)
-    return rv;
-
-  // Tidy up.
-  oldOCSPAIAInfoCallback = nullptr;
-  cleanUpMyDefaultOCSPResponders();
-  return SECSuccess;
-}
--- a/security/manager/ssl/src/nsNSSCallbacks.h
+++ b/security/manager/ssl/src/nsNSSCallbacks.h
@@ -21,19 +21,16 @@ class nsILoadGroup;
 
 char*
 PK11PasswordPrompt(PK11SlotInfo *slot, PRBool retry, void* arg);
 
 void HandshakeCallback(PRFileDesc *fd, void *client_data);
 SECStatus CanFalseStartCallback(PRFileDesc* fd, void* client_data,
                                 PRBool *canFalseStart);
 
-SECStatus RegisterMyOCSPAIAInfoCallback();
-SECStatus UnregisterMyOCSPAIAInfoCallback();
-
 class nsHTTPListener MOZ_FINAL : public nsIStreamLoaderObserver
 {
 private:
   // For XPCOM implementations that are not a base class for some other
   // class, it is good practice to make the destructor non-virtual and
   // private.  Then the only way to delete the object is via Release.
   ~nsHTTPListener();
 
@@ -219,11 +216,8 @@ public:
   static void initTable();
   static SEC_HttpClientFcn sNSSInterfaceTable;
 
   void registerHttpClient();
   void unregisterHttpClient();
 };
 
 #endif // _NSNSSCALLBACKS_H_
-
-
-
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -1251,18 +1251,16 @@ nsNSSComponent::InitializeNSS(bool showW
       SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
       SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
       SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
       PORT_SetUCS2_ASCIIConversionFunction(pip_ucs2_ascii_conversion_fn);
 
       // dynamic options from prefs
       setValidationOptions(mPrefBranch);
 
-      RegisterMyOCSPAIAInfoCallback();
-
       mHttpForNSS.initTable();
       mHttpForNSS.registerHttpClient();
 
       InstallLoadableRoots();
 
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
       LaunchSmartCardThreads();
 #endif
@@ -1296,17 +1294,16 @@ nsNSSComponent::ShutdownNSS()
 
   MutexAutoLock lock(mutex);
 
   if (mNSSInitialized) {
     mNSSInitialized = false;
 
     PK11_SetPasswordFunc((PK11PasswordFunc)nullptr);
     mHttpForNSS.unregisterHttpClient();
-    UnregisterMyOCSPAIAInfoCallback();
 
     if (mPrefBranch) {
       mPrefBranch->RemoveObserver("security.", this);
     }
 
 #ifndef MOZ_DISABLE_CRYPTOLEGACY
     ShutdownSmartCardThreads();
 #endif
--- a/services/healthreport/providers.jsm
+++ b/services/healthreport/providers.jsm
@@ -150,30 +150,49 @@ AppVersionMeasurement2.prototype = Objec
   fields: {
     appVersion: {type: Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT},
     platformVersion: {type: Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT},
     appBuildID: {type: Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT},
     platformBuildID: {type: Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT},
   },
 });
 
+/**
+ * Holds data on the application update functionality.
+ */
+function AppUpdateMeasurement1() {
+  Metrics.Measurement.call(this);
+}
+
+AppUpdateMeasurement1.prototype = Object.freeze({
+  __proto__: Metrics.Measurement.prototype,
+
+  name: "update",
+  version: 1,
+
+  fields: {
+    enabled: {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC},
+    autoDownload: {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC},
+  },
+});
 
 this.AppInfoProvider = function AppInfoProvider() {
   Metrics.Provider.call(this);
 
   this._prefs = new Preferences({defaultBranch: null});
 }
 AppInfoProvider.prototype = Object.freeze({
   __proto__: Metrics.Provider.prototype,
 
   name: "org.mozilla.appInfo",
 
   measurementTypes: [
     AppInfoMeasurement,
     AppInfoMeasurement1,
+    AppUpdateMeasurement1,
     AppVersionMeasurement1,
     AppVersionMeasurement2,
   ],
 
   pullOnly: true,
 
   appInfoFields: {
     // From nsIXULAppInfo.
@@ -367,16 +386,27 @@ AppInfoProvider.prototype = Object.freez
       } catch (ex) {
         this._log.warn("Could not determine if default browser: " +
                        CommonUtils.exceptionStr(ex));
       }
     }
 
     return m.setDailyLastNumeric("isDefaultBrowser", isDefault);
   },
+
+  collectDailyData: function () {
+    let m = this.getMeasurement(AppUpdateMeasurement1.prototype.name,
+                                AppUpdateMeasurement1.prototype.version);
+
+    let enabled = this._prefs.get("app.update.enabled", false);
+    yield m.setDailyLastNumeric("enabled", enabled ? 1 : 0);
+
+    let auto = this._prefs.get("app.update.auto", false);
+    yield m.setDailyLastNumeric("autoDownload", auto ? 1 : 0);
+  },
 });
 
 
 function SysInfoMeasurement() {
   Metrics.Measurement.call(this);
 }
 
 SysInfoMeasurement.prototype = Object.freeze({
--- a/services/healthreport/tests/xpcshell/test_provider_appinfo.js
+++ b/services/healthreport/tests/xpcshell/test_provider_appinfo.js
@@ -216,8 +216,37 @@ add_task(function test_record_blocklist(
   m = provider.getMeasurement("appinfo", 2);
   data = yield m.getValues();
   d = yield m.serializer(m.SERIALIZE_JSON).daily(data.days.getDay(now));
   do_check_eq(d.isBlocklistEnabled, 0);
   yield provider.shutdown();
 
   yield storage.close();
 });
+
+add_task(function test_record_app_update () {
+  let storage = yield Metrics.Storage("record_update");
+
+  Services.prefs.setBoolPref("app.update.enabled", true);
+  Services.prefs.setBoolPref("app.update.auto", true);
+  let provider = new AppInfoProvider();
+  yield provider.init(storage);
+  let now = new Date();
+  yield provider.collectDailyData();
+
+  let m = provider.getMeasurement("update", 1);
+  let data = yield m.getValues();
+  let d = yield m.serializer(m.SERIALIZE_JSON).daily(data.days.getDay(now));
+  do_check_eq(d.enabled, 1);
+  do_check_eq(d.autoDownload, 1);
+
+  Services.prefs.setBoolPref("app.update.enabled", false);
+  Services.prefs.setBoolPref("app.update.auto", false);
+
+  yield provider.collectDailyData();
+  data = yield m.getValues();
+  d = yield m.serializer(m.SERIALIZE_JSON).daily(data.days.getDay(now));
+  do_check_eq(d.enabled, 0);
+  do_check_eq(d.autoDownload, 0);
+
+  yield provider.shutdown();
+  yield storage.close();
+});
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -1,6 +1,134 @@
 {
     "talos.zip": {
         "url": "http://build.mozilla.org/talos/zips/talos.a11542b55a70.zip",
         "path": ""
+    },
+    "global": {
+        "talos_url": "http://puppetagain.pub.build.mozilla.org/data/python/packages/talos-7d4ae29b7d1f.tar.gz",
+        "talos_revision": "7d4ae29b7d1f"
+    },
+    "suites": {
+        "chromez": {
+            "tests": ["tdhtmlr", "tresize"],
+            "talos_options": [
+                "--mozAfterPaint",
+                "--filter",
+                "ignore_first:5",
+                "--filter",
+                "median"
+            ]
+        },
+        "dirtypaint": {
+            "tests": [
+                "tspaint_places_generated_med",
+                "tspaint_places_generated_max"
+            ],
+            "talos_addons": [
+                "http://build.mozilla.org/talos/profiles/dirtyDBs.zip",
+                "http://build.mozilla.org/talos/profiles/dirtyMaxDBs.zip"
+            ],
+            "talos_options": [
+                "--setPref",
+                "hangmonitor.timeout=0",
+                "--mozAfterPaint"
+            ]
+        },
+        "dromaeojs": {
+            "tests": [
+                "dromaeo_css",
+                "dromaeo_dom",
+                "kraken:v8_7"
+            ]
+        },
+        "nochromer": {
+            "tests": [ "tdhtmlr" ],
+            "talos_options": [
+                "--noChrome",
+                "--mozAfterPaint",
+                "--filter",
+                "ignore_first:5",
+                "--filter",
+                "median"
+            ]
+        },
+        "other": {
+            "tests": ["tscrollr", "a11yr", "ts_paint", "tpaint"],
+            "talos_options": [
+                "--mozAfterPaint",
+                "--filter",
+                "ignore_first:5",
+                "--filter",
+                "median"
+            ]
+        },
+        "svgr": {
+            "tests": ["tsvgr", "tsvgr_opacity"],
+            "talos_options": [
+                "--filter",
+                "ignore_first:5",
+                "--filter",
+                "median"
+            ]
+        },
+        "tpn": {
+            "tests": ["tp5n"],
+            "pagesets_url": "http://build.mozilla.org/talos/zips/tp5n.zip",
+            "pagesets_parent_dir_path": "talos/page_load_test/",
+            "pagesets_manifest_path": "talos/page_load_test/tp5n/tp5n.manifest",
+            "plugins": {
+                "32": "http://build.mozilla.org/talos/zips/flash32_10_3_183_5.zip",
+                "64": "http://build.mozilla.org/talos/zips/flash64_11_0_d1_98.zip"
+            },
+            "talos_options": [
+                "--mozAfterPaint",
+                "--responsiveness",
+                "--filter",
+                "ignore_first:5",
+                "--filter",
+                "median",
+                "--test_timeout",
+                "3600"
+            ]
+        },
+        "tp5o": {
+            "tests": ["tp5o"],
+            "pagesets_url": "http://build.mozilla.org/talos/zips/tp5n.zip",
+            "pagesets_parent_dir_path": "talos/page_load_test/",
+            "pagesets_manifest_path": "talos/page_load_test/tp5n/tp5o.manifest",
+            "plugins": {
+                "32": "http://build.mozilla.org/talos/zips/flash32_10_3_183_5.zip",
+                "64": "http://build.mozilla.org/talos/zips/flash64_11_0_d1_98.zip"
+            },
+            "talos_options": [
+                "--mozAfterPaint",
+                "--responsiveness",
+                "--filter",
+                "ignore_first:5",
+                "--filter",
+                "median",
+                "--test_timeout",
+                "3600"
+            ]
+        },
+        "xperf": {
+            "tests": ["tp5n"],
+            "pagesets_url": "http://build.mozilla.org/talos/zips/tp5n.zip",
+            "pagesets_parent_dir_path": "talos/page_load_test/",
+            "pagesets_manifest_path": "talos/page_load_test/tp5n/tp5n.manifest",
+            "plugins": {
+                "32": "http://build.mozilla.org/talos/zips/flash32_10_3_183_5.zip",
+                "64": "http://build.mozilla.org/talos/zips/flash64_11_0_d1_98.zip"
+            },
+            "talos_options": [
+                "--mozAfterPaint",
+                "--xperf_path",
+                "\"c:/Program Files/Microsoft Windows Performance Toolkit/xperf.exe\"",
+                "--filter",
+                "ignore_first:5",
+                "--filter",
+                "median",
+                "C:/slave/talos-data/talos/xperf.config"
+            ]
+        }
     }
 }
--- a/toolkit/components/captivedetect/test/unit/head_setprefs.js
+++ b/toolkit/components/captivedetect/test/unit/head_setprefs.js
@@ -1,25 +1,49 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const kServerURL = 'http://localhost:4444';
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://testing-common/httpd.js');
+
+XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
+                                   '@mozilla.org/toolkit/captive-detector;1',
+                                   'nsICaptivePortalDetector');
+
 const kCanonicalSitePath = '/canonicalSite.html';
 const kCanonicalSiteContent = 'true';
 const kPrefsCanonicalURL = 'captivedetect.canonicalURL';
 const kPrefsCanonicalContent = 'captivedetect.canonicalContent';
 const kPrefsMaxWaitingTime = 'captivedetect.maxWaitingTime';
 const kPrefsPollingTime = 'captivedetect.pollingTime';
 
+var gServer;
+var gServerURL;
+
 function setupPrefs() {
   let prefs = Components.classes["@mozilla.org/preferences-service;1"]
                 .getService(Components.interfaces.nsIPrefService)
                 .QueryInterface(Components.interfaces.nsIPrefBranch);
-  prefs.setCharPref(kPrefsCanonicalURL, kServerURL + kCanonicalSitePath);
+  prefs.setCharPref(kPrefsCanonicalURL, gServerURL + kCanonicalSitePath);
   prefs.setCharPref(kPrefsCanonicalContent, kCanonicalSiteContent);
   prefs.setIntPref(kPrefsMaxWaitingTime, 0);
   prefs.setIntPref(kPrefsPollingTime, 1);
 }
 
-setupPrefs();
+function run_captivedetect_test(xhr_handler, fakeUIResponse, testfun)
+{
+  gServer = new HttpServer();
+  gServer.registerPathHandler(kCanonicalSitePath, xhr_handler);
+  gServer.start(-1);
+  gServerURL = 'http://localhost:' + gServer.identity.primaryPort;
+
+  setupPrefs();
+
+  fakeUIResponse();
+
+  testfun();
+}
--- a/toolkit/components/captivedetect/test/unit/test_abort.js
+++ b/toolkit/components/captivedetect/test/unit/test_abort.js
@@ -1,25 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
   response.setHeader('Content-Type', 'text/plain', false);
@@ -49,20 +40,14 @@ function test_abort() {
     },
     complete: function complete(success) {
       do_throw('should not execute |complete| callback');
     },
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
   gCaptivePortalDetector.abort(kInterfaceName);
-  server.stop(do_test_finished);
+  gServer.stop(do_test_finished);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_abort();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_abort);
 }
--- a/toolkit/components/captivedetect/test/unit/test_abort_during_user_login.js
+++ b/toolkit/components/captivedetect/test/unit/test_abort_during_user_login.js
@@ -1,25 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
   response.setHeader('Content-Type', 'text/plain', false);
@@ -31,29 +22,29 @@ function xhr_handler(metadata, response)
 }
 
 function fakeUIResponse() {
   let requestId;
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login') {
       let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                   .createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open('GET', kServerURL + kCanonicalSitePath, true);
+      xhr.open('GET', gServerURL + kCanonicalSitePath, true);
       xhr.send();
       loginFinished = true;
       do_check_eq(++step, 2);
       requestId = JSON.parse(data).id;
       gCaptivePortalDetector.abort(kInterfaceName);
     }
   }, 'captive-portal-login', false);
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login-abort') {
       do_check_eq(++step, 3);
       do_check_eq(JSON.parse(data).id, requestId);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     }
   }, 'captive-portal-login-abort', false);
 }
 
 function test_abort() {
   do_test_pending();
 
   let callback = {
@@ -66,16 +57,10 @@ function test_abort() {
       do_throw('should not execute |complete| callback');
     },
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_abort();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_abort);
 }
--- a/toolkit/components/captivedetect/test/unit/test_abort_ongoing_request.js
+++ b/toolkit/components/captivedetect/test/unit/test_abort_ongoing_request.js
@@ -1,26 +1,17 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 const kOtherInterfaceName = 'ril';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
   response.setHeader('Content-Type', 'text/plain', false);
@@ -31,17 +22,17 @@ function xhr_handler(metadata, response)
   }
 }
 
 function fakeUIResponse() {
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login') {
       let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                   .createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open('GET', kServerURL + kCanonicalSitePath, true);
+      xhr.open('GET', gServerURL + kCanonicalSitePath, true);
       xhr.send();
       loginFinished = true;
       do_check_eq(++step, 3);
     }
   }, 'captive-portal-login', false);
 }
 
 function test_multiple_requests_abort() {
@@ -62,26 +53,20 @@ function test_multiple_requests_abort() 
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_check_eq(++step, 2);
       gCaptivePortalDetector.finishPreparation(kOtherInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 4);
       do_check_true(success);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     }
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
   gCaptivePortalDetector.checkCaptivePortal(kOtherInterfaceName, otherCallback);
   gCaptivePortalDetector.abort(kInterfaceName);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_multiple_requests_abort();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_multiple_requests_abort);
 }
--- a/toolkit/components/captivedetect/test/unit/test_abort_pending_request.js
+++ b/toolkit/components/captivedetect/test/unit/test_abort_pending_request.js
@@ -1,26 +1,17 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 const kOtherInterfaceName = 'ril';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
   response.setHeader('Content-Type', 'text/plain', false);
@@ -31,17 +22,17 @@ function xhr_handler(metadata, response)
   }
 }
 
 function fakeUIResponse() {
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login') {
       let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                   .createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open('GET', kServerURL + kCanonicalSitePath, true);
+      xhr.open('GET', gServerURL + kCanonicalSitePath, true);
       xhr.send();
       loginFinished = true;
       do_check_eq(++step, 2);
     }
   }, 'captive-portal-login', false);
 }
 
 function test_abort() {
@@ -51,17 +42,17 @@ function test_abort() {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_check_eq(++step, 1);
       gCaptivePortalDetector.finishPreparation(kInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 3);
       do_check_true(success);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     },
   };
 
   let otherCallback = {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_throw('should not execute |prepare| callback for ' + kOtherInterfaceName);
     },
@@ -71,16 +62,10 @@ function test_abort() {
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
   gCaptivePortalDetector.checkCaptivePortal(kOtherInterfaceName, otherCallback);
   gCaptivePortalDetector.abort(kOtherInterfaceName);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_abort();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_abort);
 }
--- a/toolkit/components/captivedetect/test/unit/test_captive_portal_found.js
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_found.js
@@ -1,25 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
   response.setHeader('Content-Type', 'text/plain', false);
@@ -30,17 +21,17 @@ function xhr_handler(metadata, response)
   }
 }
 
 function fakeUIResponse() {
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login') {
       let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                   .createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open('GET', kServerURL + kCanonicalSitePath, true);
+      xhr.open('GET', gServerURL + kCanonicalSitePath, true);
       xhr.send();
       loginFinished = true;
       do_check_eq(++step, 2);
     }
   }, 'captive-portal-login', false);
 }
 
 function test_portal_found() {
@@ -50,24 +41,18 @@ function test_portal_found() {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_check_eq(++step, 1);
       gCaptivePortalDetector.finishPreparation(kInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 3);
       do_check_true(success);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     },
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_portal_found();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_found);
 }
--- a/toolkit/components/captivedetect/test/unit/test_captive_portal_found_303.js
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_found_303.js
@@ -1,25 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 
 function xhr_handler(metadata, response) {
   if (loginFinished) {
     response.setStatusLine(metadata.httpVersion, 200, 'OK');
     response.setHeader('Cache-Control', 'no-cache', false);
@@ -32,17 +23,17 @@ function xhr_handler(metadata, response)
   }
 }
 
 function fakeUIResponse() {
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login') {
       let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                   .createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open('GET', kServerURL + kCanonicalSitePath, true);
+      xhr.open('GET', gServerURL + kCanonicalSitePath, true);
       xhr.send();
       loginFinished = true;
       do_check_eq(++step, 2);
     }
   }, 'captive-portal-login', false);
 }
 
 function test_portal_found() {
@@ -52,24 +43,26 @@ function test_portal_found() {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_check_eq(++step, 1);
       gCaptivePortalDetector.finishPreparation(kInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 3);
       do_check_true(success);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     },
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
 }
 
 function run_test() {
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_found);
+
   server = new HttpServer();
   server.registerPathHandler(kCanonicalSitePath, xhr_handler);
   server.start(4444);
 
   fakeUIResponse();
 
   test_portal_found();
 }
--- a/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found.js
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found.js
@@ -1,25 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var attempt = 0;
 
 function xhr_handler(metadata, response) {
   dump('HTTP activity\n');
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
@@ -44,24 +35,18 @@ function test_portal_not_found() {
     prepare: function prepare() {
       do_check_eq(++step, 1);
       gCaptivePortalDetector.finishPreparation(kInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 2);
       do_check_true(success);
       do_check_eq(attempt, 1);
-      server.stop(function(){dump('server stop\n'); do_test_finished(); });
+      gServer.stop(function(){dump('server stop\n'); do_test_finished(); });
     }
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_portal_not_found();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_not_found);
 }
--- a/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js
+++ b/toolkit/components/captivedetect/test/unit/test_captive_portal_not_found_404.js
@@ -1,25 +1,16 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 var attempt = 0;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 404, "Page not Found");
   attempt++;
@@ -41,24 +32,18 @@ function test_portal_not_found() {
     prepare: function prepare() {
       do_check_eq(++step, 1);
       gCaptivePortalDetector.finishPreparation(kInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 2);
       do_check_true(success);
       do_check_eq(attempt, 6);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     },
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_portal_not_found();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_portal_not_found);
 }
--- a/toolkit/components/captivedetect/test/unit/test_multiple_requests.js
+++ b/toolkit/components/captivedetect/test/unit/test_multiple_requests.js
@@ -1,26 +1,17 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 const kOtherInterfaceName = 'ril';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 var loginFinished = false;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
   response.setHeader('Content-Type', 'text/plain', false);
@@ -31,17 +22,17 @@ function xhr_handler(metadata, response)
   }
 }
 
 function fakeUIResponse() {
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login') {
       let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                   .createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open('GET', kServerURL + kCanonicalSitePath, true);
+      xhr.open('GET', gServerURL + kCanonicalSitePath, true);
       xhr.send();
       loginFinished = true;
       do_check_eq(++step, 2);
     }
   }, 'captive-portal-login', false);
 }
 
 function test_multiple_requests() {
@@ -63,25 +54,19 @@ function test_multiple_requests() {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_check_eq(++step, 4);
       gCaptivePortalDetector.finishPreparation(kOtherInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 5);
       do_check_true(success);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     }
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
   gCaptivePortalDetector.checkCaptivePortal(kOtherInterfaceName, otherCallback);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_multiple_requests();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_multiple_requests);
 }
--- a/toolkit/components/captivedetect/test/unit/test_user_cancel.js
+++ b/toolkit/components/captivedetect/test/unit/test_user_cancel.js
@@ -1,41 +1,32 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://testing-common/httpd.js');
-
 const kInterfaceName = 'wifi';
 
-XPCOMUtils.defineLazyServiceGetter(this, 'gCaptivePortalDetector',
-                                   '@mozilla.org/toolkit/captive-detector;1',
-                                   'nsICaptivePortalDetector');
 var server;
 var step = 0;
 
 function xhr_handler(metadata, response) {
   response.setStatusLine(metadata.httpVersion, 200, 'OK');
   response.setHeader('Cache-Control', 'no-cache', false);
   response.setHeader('Content-Type', 'text/plain', false);
   response.write('false');
 }
 
 function fakeUIResponse() {
   Services.obs.addObserver(function observe(subject, topic, data) {
     if (topic === 'captive-portal-login') {
       let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                   .createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open('GET', kServerURL + kCanonicalSitePath, true);
+      xhr.open('GET', gServerURL + kCanonicalSitePath, true);
       xhr.send();
       do_check_eq(++step, 2);
       let details = JSON.parse(data);
       gCaptivePortalDetector.cancelLogin(details.id);
     }
   }, 'captive-portal-login', false);
 }
 
@@ -46,24 +37,18 @@ function test_cancel() {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsICaptivePortalCallback]),
     prepare: function prepare() {
       do_check_eq(++step, 1);
       gCaptivePortalDetector.finishPreparation(kInterfaceName);
     },
     complete: function complete(success) {
       do_check_eq(++step, 3);
       do_check_false(success);
-      server.stop(do_test_finished);
+      gServer.stop(do_test_finished);
     },
   };
 
   gCaptivePortalDetector.checkCaptivePortal(kInterfaceName, callback);
 }
 
 function run_test() {
-  server = new HttpServer();
-  server.registerPathHandler(kCanonicalSitePath, xhr_handler);
-  server.start(4444);
-
-  fakeUIResponse();
-
-  test_cancel();
+  run_captivedetect_test(xhr_handler, fakeUIResponse, test_cancel);
 }
--- a/toolkit/devtools/server/transport.js
+++ b/toolkit/devtools/server/transport.js
@@ -6,39 +6,41 @@
 
 "use strict";
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 
 /**
  * An adapter that handles data transfers between the debugger client and
  * server. It can work with both nsIPipe and nsIServerSocket transports so
  * long as the properly created input and output streams are specified.
+ * (However, for intra-process connections, LocalDebuggerTransport, below,
+ * is more efficient than using an nsIPipe pair with DebuggerTransport.)
  *
  * @param aInput nsIInputStream
  *        The input stream.
  * @param aOutput nsIAsyncOutputStream
  *        The output stream.
  *
  * Given a DebuggerTransport instance dt:
  * 1) Set dt.hooks to a packet handler object (described below).
  * 2) Call dt.ready() to begin watching for input packets.
- * 3) Send packets as you please, and handle incoming packets passed to 
- *    hook.onPacket.
+ * 3) Call dt.send() to send packets as you please, and handle incoming
+ *    packets passed to hook.onPacket.
  * 4) Call dt.close() to close the connection, and disengage from the event
  *    loop.
  *
- * A packet handler object is an object with two methods:
+ * A packet handler is an object with two methods:
  *
  * - onPacket(packet) - called when we have received a complete packet.
  *   |Packet| is the parsed form of the packet --- a JavaScript value, not
  *   a JSON-syntax string.
  *
  * - onClosed(status) - called when the connection is closed. |Status| is
  *   an nsresult, of the sort passed to nsIRequestObserver.
- * 
+ *
  * Data is transferred as a JSON packet serialized into a string, with the
  * string length prepended to the packet, followed by a colon
  * ([length]:[packet]). The contents of the JSON packet are specified in
  * the Remote Debugging Protocol specification.
  */
 this.DebuggerTransport = function DebuggerTransport(aInput, aOutput)
 {
   this._input = aInput;
@@ -273,8 +275,55 @@ LocalDebuggerTransport.prototype = {
       // an unfrozen object.
       if (aObject.hasOwnProperty(prop) && typeof aObject === "object" &&
           !Object.isFrozen(aObject)) {
         this._deepFreeze(o[prop]);
       }
     }
   }
 };
+
+/**
+ * A transport for the debugging protocol that uses nsIMessageSenders to
+ * exchange packets with servers running in child processes.
+ *
+ * In the parent process, |aSender| should be the nsIMessageSender for the
+ * child process. In a child process, |aSender| should be the child process
+ * message manager, which sends packets to the parent.
+ *
+ * aPrefix is a string included in the message names, to distinguish
+ * multiple servers running in the same child process.
+ *
+ * This transport exchanges messages named 'debug:<prefix>:packet', where
+ * <prefix> is |aPrefix|, whose data is the protocol packet.
+ */
+function ChildDebuggerTransport(aSender, aPrefix) {
+  this._sender = aSender.QueryInterface(Components.interfaces.nsIMessageSender);
+  this._messageName = "debug:" + aPrefix + ":packet";
+}
+
+/*
+ * To avoid confusion, we use 'message' to mean something that
+ * nsIMessageSender conveys, and 'packet' to mean a remote debugging
+ * protocol packet.
+ */
+ChildDebuggerTransport.prototype = {
+  constructor: ChildDebuggerTransport,
+
+  hooks: null,
+
+  ready: function () {
+    this._sender.addMessageListener(this._messageName, this);
+  },
+
+  close: function () {
+    this._sender.removeMessageListener(this._messageName, this);
+    this.hooks.onClosed();
+  },
+
+  receiveMessage: function ({data}) {
+    this.hooks.onPacket(data);
+  },
+
+  send: function (packet) {
+    this._sender.sendAsyncMessage(this._messageName, packet);
+  }
+};
--- a/toolkit/locales/Makefile.in
+++ b/toolkit/locales/Makefile.in
@@ -22,29 +22,25 @@ endif
 vpath crashreporter.% $(LOCALE_SRCDIR)/crashreporter
 ifdef LOCALE_MERGEDIR
 vpath crashreporter.% @srcdir@/en-US/crashreporter
 endif
 
 libs-%:
 	@$(MAKE) -C ../../netwerk/locales/ libs AB_CD=$* XPI_NAME=locale-$*
 	@$(MAKE) -C ../../dom/locales/ libs AB_CD=$* XPI_NAME=locale-$*
-ifdef MOZ_PSM
 	@$(MAKE) -C ../../security/manager/locales/ libs AB_CD=$* XPI_NAME=locale-$*
-endif
 	@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$*
 
 # target to be used by multi-locale l10n builds, just add this locale 
 # like regular chrome code
 chrome-%:
 	@$(MAKE) -C $(DEPTH)/netwerk/locales/ chrome AB_CD=$*
 	@$(MAKE) -C $(DEPTH)/dom/locales/ chrome AB_CD=$*
-ifdef MOZ_PSM
 	@$(MAKE) -C $(DEPTH)/security/manager/locales/ chrome AB_CD=$*
-endif
 	@$(MAKE) chrome AB_CD=$*
 
 ifdef MOZ_UPDATER
 libs:: update.locale
 	cat $< | sed -e "s/%AB_CD%/$(AB_CD)/" > $(FINAL_TARGET)/update.locale
 endif
 
 ifdef MOZ_CRASHREPORTER
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -7,17 +7,17 @@ if CONFIG['LIBXUL_SDK']:
     error('toolkit.mozbuild is not compatible with --enable-libxul-sdk=')
 
 if not CONFIG['MOZ_NATIVE_NSPR']:
     add_tier_dir('nspr', 'config/nspr')
 
 if not CONFIG['MOZ_NATIVE_SQLITE']:
     add_tier_dir('nss', 'db/sqlite3/src')
 
-if CONFIG['MOZ_PSM'] and not CONFIG['MOZ_NATIVE_NSS']:
+if not CONFIG['MOZ_NATIVE_NSS']:
     add_tier_dir('nss', 'security/build')
 
 include('/config/js/js.mozbuild')
 
 if CONFIG['NS_TRACE_MALLOC']:
     add_tier_dir('platform', 'tools/trace-malloc/lib')
 
 if CONFIG['MOZ_DMD']:
@@ -171,23 +171,17 @@ add_tier_dir('platform', 'tools/profiler
 add_tier_dir('platform', 'xpfe/components')
 
 if CONFIG['MOZ_ENABLE_XREMOTE']:
     add_tier_dir('platform', 'widget/xremoteclient')
 
 if CONFIG['MOZ_SPELLCHECK']:
     add_tier_dir('platform', 'extensions/spellcheck')
 
-if CONFIG['MOZ_PSM']:
-    add_tier_dir('platform', 'security/manager')
-else:
-    add_tier_dir('platform', [
-        'security/manager/boot/public',
-        'security/manager/ssl/public',
-    ])
+add_tier_dir('platform', 'security/manager')
 
 if CONFIG['MOZ_UPDATER']:
     add_tier_dir('platform', 'modules/libmar')
 
 add_tier_dir('platform', 'toolkit')
 
 if CONFIG['MOZ_PREF_EXTENSIONS']:
     add_tier_dir('platform', 'extensions/pref')
--- a/webapprt/WebappsHandler.jsm
+++ b/webapprt/WebappsHandler.jsm
@@ -23,17 +23,17 @@ this.WebappsHandler = {
   },
 
   observe: function(subject, topic, data) {
     data = JSON.parse(data);
     data.mm = subject;
 
     switch (topic) {
       case "webapps-ask-install":
-        let chromeWin = Services.wm.getOuterWindowById(data.oid);
+        let chromeWin = Services.wm.getOuterWindowWithId(data.oid);
         if (chromeWin)
           this.doInstall(data, chromeWin);
         break;
       case "webapps-launch":
         WebappOSUtils.launch(data);
         break;
       case "webapps-uninstall":
         WebappOSUtils.uninstall(data);
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -2187,27 +2187,27 @@ IMEInputHandler::OnCurrentTextInputSourc
       tis5.GetInputSourceID(is5);
       tis.GetInputSourceType(type0);
       tis.GetPrimaryLanguage(lang0);
       tis.GetBundleID(bundleID0);
 
       PR_LOG(gLog, PR_LOG_ALWAYS,
         ("IMEInputHandler::OnCurrentTextInputSourceChange,\n"
          "  Current Input Source is changed to:\n"
-         "    currentInputManager=%p\n"
+         "    currentInputContext=%p\n"
          "    %s\n"
          "      type=%s %s\n"
          "      overridden keyboard layout=%s\n"
          "      used keyboard layout for translation=%s\n"
          "    primary language=%s\n"
          "    bundle ID=%s\n"
          "    current ASCII capable Input Source=%s\n"
          "    current Keyboard Layout=%s\n"
          "    current ASCII capable Keyboard Layout=%s",
-         [NSInputManager currentInputManager], GetCharacters(is0),
+         [NSTextInputContext currentInputContext], GetCharacters(is0),
          GetCharacters(type0), tis.IsASCIICapable() ? "- ASCII capable " : "",
          GetCharacters(is4), GetCharacters(is5),
          GetCharacters(lang0), GetCharacters(bundleID0),
          GetCharacters(is2), GetCharacters(is1), GetCharacters(is3)));
     }
     sLastTIS = newTIS;
   }
 #endif // #ifdef PR_LOGGING
@@ -2263,21 +2263,21 @@ IMEInputHandler::DebugPrintAllIMEModes()
   }
 #endif // #ifdef PR_LOGGING
 }
 
 //static
 TSMDocumentID
 IMEInputHandler::GetCurrentTSMDocumentID()
 {
-  // On OS X 10.6.x at least, ::TSMGetActiveDocument() has a bug that prevents
-  // it from returning accurate results unless
-  // [NSInputManager currentInputManager] is called first.
-  // So, we need to call [NSInputManager currentInputManager] first here.
-  [NSInputManager currentInputManager];
+  // At least on Mac OS X 10.6.x and 10.7.x, ::TSMGetActiveDocument() has a bug.
+  // The result of ::TSMGetActiveDocument() isn't modified for new active text
+  // input context until [NSTextInputContext currentInputContext] is called.
+  // Therefore, we need to call it here.
+  [NSTextInputContext currentInputContext];
   return ::TSMGetActiveDocument();
 }
 
 
 #pragma mark -
 
 
 /******************************************************************************
@@ -2333,41 +2333,35 @@ IMEInputHandler::NotifyIMEOfFocusChangeI
 
 void
 IMEInputHandler::DiscardIMEComposition()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p IMEInputHandler::DiscardIMEComposition, "
-     "Destroyed()=%s, IsFocused()=%s, currentInputManager=%p",
+     "Destroyed()=%s, IsFocused()=%s, mView=%p, inputContext=%p",
      this, TrueOrFalse(Destroyed()), TrueOrFalse(IsFocused()),
-     [NSInputManager currentInputManager]));
+     mView, mView ? [mView inputContext] : nullptr));
 
   if (Destroyed()) {
     return;
   }
 
   if (!IsFocused()) {
     // retry at next focus event
     mPendingMethods |= kDiscardIMEComposition;
     return;
   }
 
-  NSInputManager* im = [NSInputManager currentInputManager];
-  if (!im) {
-    // retry
-    mPendingMethods |= kDiscardIMEComposition;
-    NS_WARNING("Application is active but there is no currentInputManager");
-    ResetTimer();
-    return;
-  }
-
+  NS_ENSURE_TRUE_VOID(mView);
+  NSTextInputContext* inputContext = [mView inputContext];
+  NS_ENSURE_TRUE_VOID(inputContext);
   mIgnoreIMECommit = true;
-  [im markedTextAbandoned: mView];
+  [inputContext discardMarkedText];
   mIgnoreIMECommit = false;
 
   NS_OBJC_END_TRY_ABORT_BLOCK
 }
 
 void
 IMEInputHandler::SyncASCIICapableOnly()
 {
@@ -3227,18 +3221,18 @@ IMEInputHandler::OnDestroyWidget(nsChild
 
 void
 IMEInputHandler::OnStartIMEComposition()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p IMEInputHandler::OnStartIMEComposition, mView=%p, mWidget=%p"
-     "currentInputManager=%p, mIsIMEComposing=%s",
-     this, mView, mWidget, [NSInputManager currentInputManager],
+     "inputContext=%p, mIsIMEComposing=%s",
+     this, mView, mWidget, mView ? [mView inputContext] : nullptr,
      TrueOrFalse(mIsIMEComposing)));
 
   NS_ASSERTION(!mIsIMEComposing, "There is a composition already");
   mIsIMEComposing = true;
 
   mLastDispatchedCompositionString.Truncate();
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
@@ -3246,18 +3240,18 @@ IMEInputHandler::OnStartIMEComposition()
 
 void
 IMEInputHandler::OnUpdateIMEComposition(NSString* aIMECompositionString)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p IMEInputHandler::OnUpdateIMEComposition, mView=%p, mWidget=%p, "
-     "currentInputManager=%p, mIsIMEComposing=%s, aIMECompositionString=\"%s\"",
-     this, mView, mWidget, [NSInputManager currentInputManager],
+     "inputContext=%p, mIsIMEComposing=%s, aIMECompositionString=\"%s\"",
+     this, mView, mWidget, mView ? [mView inputContext] : nullptr,
      TrueOrFalse(mIsIMEComposing), GetCharacters(aIMECompositionString)));
 
   NS_ASSERTION(mIsIMEComposing, "We're not in composition");
 
   if (mIMECompositionString)
     [mIMECompositionString release];
   mIMECompositionString = [aIMECompositionString retain];
 
@@ -3266,18 +3260,18 @@ IMEInputHandler::OnUpdateIMEComposition(
 
 void
 IMEInputHandler::OnEndIMEComposition()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p IMEInputHandler::OnEndIMEComposition, mView=%p, mWidget=%p, "
-     "currentInputManager=%p, mIsIMEComposing=%s",
-     this, mView, mWidget, [NSInputManager currentInputManager],
+     "inputContext=%p, mIsIMEComposing=%s",
+     this, mView, mWidget, mView ? [mView inputContext] : nullptr,
      TrueOrFalse(mIsIMEComposing)));
 
   NS_ASSERTION(mIsIMEComposing, "We're not in composition");
 
   mIsIMEComposing = false;
 
   if (mIMECompositionString) {
     [mIMECompositionString release];
@@ -3291,18 +3285,18 @@ IMEInputHandler::OnEndIMEComposition()
 
 void
 IMEInputHandler::SendCommittedText(NSString *aString)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p IMEInputHandler::SendCommittedText, mView=%p, mWidget=%p, "
-     "currentInputManager=%p, mIsIMEComposing=%s",
-     this, mView, mWidget, [NSInputManager currentInputManager],
+     "inputContext=%p, mIsIMEComposing=%s",
+     this, mView, mWidget, mView ? [mView inputContext] : nullptr,
      TrueOrFalse(mIsIMEComposing), mWidget));
 
   NS_ENSURE_TRUE(mWidget, );
   // XXX We should send the string without mView.
   if (!mView) {
     return;
   }
 
@@ -3316,28 +3310,31 @@ IMEInputHandler::SendCommittedText(NSStr
 
 void
 IMEInputHandler::KillIMEComposition()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p IMEInputHandler::KillIMEComposition, mView=%p, mWidget=%p, "
-     "currentInputManager=%p, mIsIMEComposing=%s, "
+     "inputContext=%p, mIsIMEComposing=%s, "
      "Destroyed()=%s, IsFocused()=%s",
-     this, mView, mWidget, [NSInputManager currentInputManager],
+     this, mView, mWidget, mView ? [mView inputContext] : nullptr,
      TrueOrFalse(mIsIMEComposing), TrueOrFalse(Destroyed()),
      TrueOrFalse(IsFocused())));
 
   if (Destroyed()) {
     return;
   }
 
   if (IsFocused()) {
-    [[NSInputManager currentInputManager] markedTextAbandoned: mView];
+    NS_ENSURE_TRUE_VOID(mView);
+    NSTextInputContext* inputContext = [mView inputContext];
+    NS_ENSURE_TRUE_VOID(inputContext);
+    [inputContext discardMarkedText];
     return;
   }
 
   PR_LOG(gLog, PR_LOG_ALWAYS,
     ("%p IMEInputHandler::KillIMEComposition, Pending...", this));
 
   // Commit the composition internally.
   SendCommittedText(mIMECompositionString);
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2100,17 +2100,19 @@ nsChildView::MaybeDrawResizeIndicator(GL
 
   if (!mResizerImage) {
     mResizerImage = new RectTextureImage(aManager->gl());
   }
 
   nsIntSize size = mResizeIndicatorRect.Size();
   mResizerImage->UpdateIfNeeded(size, nsIntRegion(), ^(gfx::DrawTarget* drawTarget, const nsIntRegion& updateRegion) {
     ClearRegion(drawTarget, updateRegion);
-    DrawResizer(static_cast<CGContextRef>(drawTarget->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT)));
+    gfx::BorrowedCGContext borrow(drawTarget);
+    DrawResizer(borrow.cg);
+    borrow.Finish();
   });
 
   mResizerImage->Draw(aManager, mResizeIndicatorRect.TopLeft());
 }
 
 // Draw the highlight line at the top of the titlebar.
 // This function draws into the current NSGraphicsContext and assumes flippedness.
 static void
@@ -2160,19 +2162,18 @@ nsChildView::UpdateTitlebarImageBuffer()
                                      gfx::FORMAT_B8G8R8A8);
   }
 
   if (dirtyTitlebarRegion.IsEmpty())
     return;
 
   ClearRegion(mTitlebarImageBuffer, dirtyTitlebarRegion);
 
-  CGContextRef ctx =
-    static_cast<CGContextRef>(mTitlebarImageBuffer->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT));
-  CGContextSaveGState(ctx);
+  gfx::BorrowedCGContext borrow(mTitlebarImageBuffer);
+  CGContextRef ctx = borrow.cg;
 
   double scale = BackingScaleFactor();
   CGContextScaleCTM(ctx, scale, scale);
   NSGraphicsContext* oldContext = [NSGraphicsContext currentContext];
 
   CGContextSaveGState(ctx);
 
   BaseWindow* window = (BaseWindow*)[mView window];
@@ -2228,17 +2229,17 @@ nsChildView::UpdateTitlebarImageBuffer()
   }
 
   CGContextRestoreGState(ctx);
 
   DrawTitlebarHighlight([frameView bounds].size, [(ChildView*)mView cornerRadius],
                         DevPixelsToCocoaPoints(1));
 
   [NSGraphicsContext setCurrentContext:oldContext];
-  CGContextRestoreGState(ctx);
+  borrow.Finish();
 
   mUpdatedTitlebarRegion.Or(mUpdatedTitlebarRegion, dirtyTitlebarRegion);
 }
 
 // This method draws an overlay in the top of the window which contains the
 // titlebar controls (e.g. close, min, zoom, fullscreen) and the titlebar
 // highlight effect.
 // This is necessary because the real titlebar controls are covered by our
@@ -2285,18 +2286,19 @@ nsChildView::MaybeDrawRoundedCorners(GLM
 
   if (!mCornerMaskImage) {
     mCornerMaskImage = new RectTextureImage(aManager->gl());
   }
 
   nsIntSize size(mDevPixelCornerRadius, mDevPixelCornerRadius);
   mCornerMaskImage->UpdateIfNeeded(size, nsIntRegion(), ^(gfx::DrawTarget* drawTarget, const nsIntRegion& updateRegion) {
     ClearRegion(drawTarget, updateRegion);
-    DrawTopLeftCornerMask(static_cast<CGContextRef>(drawTarget->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT)),
-                          mDevPixelCornerRadius);
+    gfx::BorrowedCGContext borrow(drawTarget);
+    DrawTopLeftCornerMask(borrow.cg, mDevPixelCornerRadius);
+    borrow.Finish();
   });
 
   // Use operator destination in: multiply all 4 channels with source alpha.
   aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA,
                                      LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA);
 
   gfx3DMatrix flipX = gfx3DMatrix::ScalingMatrix(-1, 1, 1);
   gfx3DMatrix flipY = gfx3DMatrix::ScalingMatrix(1, -1, 1);
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -28,16 +28,18 @@
 #include "mozilla/dom/Element.h"
 #include "nsLookAndFeel.h"
 
 #include "gfxContext.h"
 #include "gfxQuartzSurface.h"
 #include "gfxQuartzNativeDrawing.h"
 #include <algorithm>
 
+using namespace mozilla::gfx;
+
 #define DRAW_IN_FRAME_DEBUG 0
 #define SCROLLBARS_VISUAL_DEBUG 0
 
 // private Quartz routines needed here
 extern "C" {
   CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform);
 }
 
@@ -2033,17 +2035,25 @@ nsNativeThemeCocoa::DrawWidgetBackground
       // The rounded corners draw outside the frame.
       CGRect deflatedRect = CGRectMake(macRect.origin.x, macRect.origin.y + 4,
                                        macRect.size.width, macRect.size.height - 8);
       HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext, HITHEME_ORIENTATION);
     }
       break;
 
     case NS_THEME_MENUITEM: {
-      if (thebesCtx->OriginalSurface()->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
+      bool isTransparent;
+      if (thebesCtx->IsCairo()) {
+        isTransparent = thebesCtx->OriginalSurface()->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA;
+      } else {
+        SurfaceFormat format  = thebesCtx->GetDrawTarget()->GetFormat();
+        isTransparent = (format == FORMAT_R8G8B8A8) ||
+                        (format == FORMAT_B8G8R8A8);
+      }
+      if (isTransparent) {
         // Clear the background to get correct transparency.
         CGContextClearRect(cgContext, macRect);
       }
 
       // maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain?
       HIThemeMenuItemDrawInfo drawInfo;
       memset(&drawInfo, 0, sizeof(drawInfo));
       drawInfo.version = 0;