Merge m-c to b2ginbound a=merge CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Thu, 26 Feb 2015 18:53:42 -0800
changeset 261473 c4f764ed87952b461ee5a9f6031f5062f29455d0
parent 261472 70580a88611f4be993bea25e7eebfa8f88e625a9 (current diff)
parent 261379 c7968255c1eadfa38a97c69324377cf671e933a5 (diff)
child 261474 314abedc5d96e169d967295f0b437c1dda9cb30c
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to b2ginbound a=merge CLOSED TREE
b2g/installer/package-manifest.in
configure.in
js/src/jsapi-tests/testHashTableInit.cpp
layout/ipc/RenderFrameUtils.h
--- a/Makefile.in
+++ b/Makefile.in
@@ -244,16 +244,19 @@ ifdef MOZ_CRASHREPORTER
 	grep 'sym' $(SYMBOL_INDEX_NAME) > $(SYMBOL_INDEX_NAME).tmp && \
 	  mv $(SYMBOL_INDEX_NAME).tmp $(SYMBOL_INDEX_NAME)
 	cd $(DIST)/crashreporter-symbols && \
           zip -r9D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym' -i '*.txt'  -x '*test*' -x '*Test*'
 endif # MOZ_CRASHREPORTER
 
 uploadsymbols:
 ifdef MOZ_CRASHREPORTER
+ifdef SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE
+	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
+endif
 	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
 endif
 
 # MOZ_SOURCE_STAMP is defined in package-name.mk with a deferred assignment.
 # exporting it makes make run its $(shell) command for each invoked submake,
 # so transform it to an immediate assignment.
 MOZ_SOURCE_STAMP := $(MOZ_SOURCE_STAMP)
 export MOZ_SOURCE_STAMP
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -535,16 +535,27 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::STATUSBAR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kGenericAccType,
     kNoReqStates
   },
+  { // switch
+    &nsGkAtoms::_switch,
+    roles::SWITCH,
+    kUseMapRole,
+    eNoValue,
+    eCheckUncheckAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates,
+    eARIACheckableBool
+  },
   { // tab
     &nsGkAtoms::tab,
     roles::PAGETAB,
     kUseMapRole,
     eNoValue,
     eSwitchAction,
     eNoLiveAttr,
     kGenericAccType,
--- a/accessible/base/AccEvent.cpp
+++ b/accessible/base/AccEvent.cpp
@@ -134,17 +134,17 @@ AccTextSelChangeEvent::AccTextSelChangeE
            eAutoDetect, eCoalesceTextSelChange),
   mSel(aSelection), mReason(aReason) {}
 
 AccTextSelChangeEvent::~AccTextSelChangeEvent() { }
 
 bool
 AccTextSelChangeEvent::IsCaretMoveOnly() const
 {
-  return mSel->GetRangeCount() == 1 && mSel->IsCollapsed() &&
+  return mSel->RangeCount() == 1 && mSel->IsCollapsed() &&
     ((mReason & (nsISelectionListener::COLLAPSETOSTART_REASON |
                  nsISelectionListener::COLLAPSETOEND_REASON)) == 0);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccSelChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
--- a/accessible/base/Role.h
+++ b/accessible/base/Role.h
@@ -780,17 +780,22 @@ enum Role {
    */
   DEFINITION = 128,
 
   /**
    * Represent a keyboard or keypad key (ARIA role "key").
    */
   KEY = 129,
 
-  LAST_ROLE = KEY
+  /**
+   * Represent a switch control widget (ARIA role "switch").
+   */
+  SWITCH = 130,
+
+  LAST_ROLE = SWITCH
 };
 
 } // namespace role
 
 typedef enum mozilla::a11y::roles::Role role;
 
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/base/RoleMap.h
+++ b/accessible/base/RoleMap.h
@@ -1050,8 +1050,16 @@ ROLE(DEFINITION,
 
 ROLE(KEY,
      "key",
      ATK_ROLE_PUSH_BUTTON,
      NSAccessibilityButtonRole,
      ROLE_SYSTEM_PUSHBUTTON,
      ROLE_SYSTEM_PUSHBUTTON,
      eNameFromSubtreeRule)
+
+ROLE(SWITCH,
+     "switch",
+     ATK_ROLE_TOGGLE_BUTTON,
+     NSAccessibilityCheckBoxRole,
+     ROLE_SYSTEM_CHECKBUTTON,
+     IA2_ROLE_TOGGLE_BUTTON,
+     eNameFromSubtreeRule)
--- a/accessible/generic/HyperTextAccessible-inl.h
+++ b/accessible/generic/HyperTextAccessible-inl.h
@@ -44,17 +44,17 @@ HyperTextAccessible::SetCaretOffset(int3
   SelectionMgr()->UpdateCaretOffset(this, aOffset);
 }
 
 inline bool
 HyperTextAccessible::AddToSelection(int32_t aStartOffset, int32_t aEndOffset)
 {
   dom::Selection* domSel = DOMSelection();
   return domSel &&
-    SetSelectionBoundsAt(domSel->GetRangeCount(), aStartOffset, aEndOffset);
+    SetSelectionBoundsAt(domSel->RangeCount(), aStartOffset, aEndOffset);
 }
 
 inline void
 HyperTextAccessible::ReplaceText(const nsAString& aText)
 {
   int32_t numChars = CharacterCount();
   if (numChars != 0)
     DeleteText(0, numChars);
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -1164,17 +1164,17 @@ HyperTextAccessible::SetSelectionRange(i
   // some input controls
   if (isFocusable)
     TakeFocus();
 
   dom::Selection* domSel = DOMSelection();
   NS_ENSURE_STATE(domSel);
 
   // Set up the selection.
-  for (int32_t idx = domSel->GetRangeCount() - 1; idx > 0; idx--)
+  for (int32_t idx = domSel->RangeCount() - 1; idx > 0; idx--)
     domSel->RemoveRange(domSel->GetRangeAt(idx));
   SetSelectionBoundsAt(0, aStartPos, aEndPos);
 
   // When selection is done, move the focus to the selection if accessible is
   // not focusable. That happens when selection is set within hypertext
   // accessible.
   if (isFocusable)
     return NS_OK;
@@ -1469,17 +1469,17 @@ HyperTextAccessible::SetSelectionBoundsA
     return false;
   }
 
   dom::Selection* domSel = DOMSelection();
   if (!domSel)
     return false;
 
   nsRefPtr<nsRange> range;
-  uint32_t rangeCount = domSel->GetRangeCount();
+  uint32_t rangeCount = domSel->RangeCount();
   if (aSelectionNum == static_cast<int32_t>(rangeCount))
     range = new nsRange(mContent);
   else
     range = domSel->GetRangeAt(aSelectionNum);
 
   if (!range)
     return false;
 
@@ -1497,17 +1497,17 @@ HyperTextAccessible::SetSelectionBoundsA
 
 bool
 HyperTextAccessible::RemoveFromSelection(int32_t aSelectionNum)
 {
   dom::Selection* domSel = DOMSelection();
   if (!domSel)
     return false;
 
-  if (aSelectionNum < 0 || aSelectionNum >= domSel->GetRangeCount())
+  if (aSelectionNum < 0 || aSelectionNum >= static_cast<int32_t>(domSel->RangeCount()))
     return false;
 
   domSel->RemoveRange(domSel->GetRangeAt(aSelectionNum));
   return true;
 }
 
 void
 HyperTextAccessible::ScrollSubstringTo(int32_t aStartOffset, int32_t aEndOffset,
@@ -1943,17 +1943,17 @@ HyperTextAccessible::GetSpellTextAttr(ns
   nsRefPtr<nsFrameSelection> fs = FrameSelection();
   if (!fs)
     return;
 
   dom::Selection* domSel = fs->GetSelection(nsISelectionController::SELECTION_SPELLCHECK);
   if (!domSel)
     return;
 
-  int32_t rangeCount = domSel->GetRangeCount();
+  int32_t rangeCount = domSel->RangeCount();
   if (rangeCount <= 0)
     return;
 
   uint32_t startOffset = 0, endOffset = 0;
   for (int32_t idx = 0; idx < rangeCount; idx++) {
     nsRange* range = domSel->GetRangeAt(idx);
     if (range->Collapsed())
       continue;
--- a/accessible/interfaces/nsIAccessibleRole.idl
+++ b/accessible/interfaces/nsIAccessibleRole.idl
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 /**
  * Defines cross platform (Gecko) roles.
  */
-[scriptable, uuid(50db5e86-9a45-4637-a5c3-4ff148c33270)]
+[scriptable, uuid(76ce835f-ef86-47c0-ac7b-e871417f1b6e)]
 interface nsIAccessibleRole : nsISupports
 {
   /**
    * Used when accessible hans't strong defined role.
    */
   const unsigned long ROLE_NOTHING = 0;
 
   /**
@@ -773,9 +773,14 @@ interface nsIAccessibleRole : nsISupport
    * An HTML definition <dd>
    */
   const unsigned long ROLE_DEFINITION = 128;
 
   /**
    * A keyboard or keypad key.
    */
   const unsigned long ROLE_KEY = 129;
+
+  /**
+   * A switch control widget.
+   */
+  const unsigned long ROLE_SWITCH = 130;
 };
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -470,16 +470,19 @@ GetClosestInterestingAccessible(id anObj
       return @"AXDefinitionList"; // 10.6+ NSAccessibilityDefinitionListSubrole;
 
     case roles::TERM:
       return @"AXTerm";
 
     case roles::DEFINITION:
       return @"AXDefinition";
 
+    case roles::SWITCH:
+      return @"AXSwitch";
+
     default:
       break;
   }
 
   return nil;
 }
 
 - (NSString*)roleDescription
--- a/accessible/tests/mochitest/actions/test_aria.html
+++ b/accessible/tests/mochitest/actions/test_aria.html
@@ -81,16 +81,26 @@
           events: CLICK_EVENTS
         },
         {
           ID: "radio",
           actionName: "select",
           events: CLICK_EVENTS
         },
         {
+          ID: "switch_unchecked",
+          actionName: "check",
+          events: CLICK_EVENTS
+        },
+        {
+          ID: "switch_checked",
+          actionName: "uncheck",
+          events: CLICK_EVENTS
+        },
+        {
           ID: "tab",
           actionName: "switch",
           events: CLICK_EVENTS
         },
         {
           ID: "textbox",
           actionName: "activate",
           events: CLICK_EVENTS
@@ -161,16 +171,20 @@
     <div id="menuitemcheckbox" role="menuitemcheckbox">Menuitem checkbox</div>
     <div id="menuitemradio" role="menuitemradio">Menuitem radio</div>
   </div>
 
   <div role="radiogroup">
     <div id="radio" role="radio">Radio</div>
   </div>
 
+  <div id="switch_unchecked" role="switch">Switch</div>
+
+  <div id="switch_checked" role="switch" aria-checked="true">Switch</div>
+
   <div role="tablist">
     <div id="tab" role="tab">Tab</div>
   </div>
 
   <div id="textbox" role="textbox">Textbox</div>
 
   <div role="tree">
     <div id="treeitem" role="treeitem">Treeitem</div>
--- a/accessible/tests/mochitest/events/test_aria_statechange.html
+++ b/accessible/tests/mochitest/events/test_aria_statechange.html
@@ -102,27 +102,38 @@
     }
 
     function setChecked(aID, aValue)
     {
       this.__proto__ =
         new setAttrOfMixedType(aID, "aria-checked", STATE_CHECKED, aValue);
     }
 
+    function buildQueueForAttr(aList, aQueue, aID, aInvokerFunc)
+    {
+      for (var i = 0; i < aList.length; i++) {
+        for (var j = i + 1; j < aList.length; j++) {
+          // XXX: changes from/to "undefined"/"" shouldn't fire state change
+          // events, bug 472142.
+          aQueue.push(new aInvokerFunc(aID, aList[i]));
+          aQueue.push(new aInvokerFunc(aID, aList[j]));
+        }
+      }
+    }
+
     function buildQueueForAttrOfMixedType(aQueue, aID, aInvokerFunc)
     {
       var list = [ "", "undefined", "false", "true", "mixed" ];
-      for (var i = 0; i < list.length; i++) {
-        for (var j = i + 1; j < list.length; j++) {
-          // XXX: changes from/to "undefined"/"" shouldn't fire state change
-          // events, bug 472142.
-          aQueue.push(new aInvokerFunc(aID, list[i]));
-          aQueue.push(new aInvokerFunc(aID, list[j]));
-        }
-      }
+      buildQueueForAttr(list, aQueue, aID, aInvokerFunc);
+    }
+
+    function buildQueueForAttrOfBoolType(aQueue, aID, aInvokerFunc)
+    {
+      var list = [ "", "undefined", "false", "true" ];
+      buildQueueForAttr(list, aQueue, aID, aInvokerFunc);
     }
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new expandNode("section", true));
       gQueue.push(new expandNode("section", false));
@@ -130,16 +141,17 @@
       gQueue.push(new expandNode("div", false));
 
       gQueue.push(new busyify("aria_doc", true));
       gQueue.push(new busyify("aria_doc", false));
 
       buildQueueForAttrOfMixedType(gQueue, "pressable", setPressed);
       buildQueueForAttrOfMixedType(gQueue, "pressable_native", setPressed);
       buildQueueForAttrOfMixedType(gQueue, "checkable", setChecked);
+      buildQueueForAttrOfBoolType(gQueue, "checkableBool", setChecked);
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
@@ -161,16 +173,21 @@
      title="mixed state change event is fired for focused accessible only"
     Mozilla Bug 467143
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
      title="Pressed state is not exposed on a button element with aria-pressed attribute"
     Mozilla Bug 989958
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
+     title="Support ARIA 1.1 switch role"
+    Mozilla Bug 1136563
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- aria-expanded -->
@@ -181,10 +198,11 @@
   <div id="aria_doc" role="document" tabindex="0">A document</div>
 
   <!-- aria-pressed -->
   <div id="pressable" role="button"></div>
   <button id="pressable_native"></button>
 
   <!-- aria-checked -->
   <div id="checkable" role="checkbox"></div>
+  <div id="checkableBool" role="switch"></div>
 </body>
 </html>
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -65,16 +65,17 @@ const ROLE_ROW = nsIAccessibleRole.ROLE_
 const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
 const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
 const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_SPINBUTTON = nsIAccessibleRole.ROLE_SPINBUTTON;
 const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
 const ROLE_STATUSBAR = nsIAccessibleRole.ROLE_STATUSBAR;
+const ROLE_SWITCH = nsIAccessibleRole.ROLE_SWITCH;
 const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
 const ROLE_TERM = nsIAccessibleRole.ROLE_TERM;
 const ROLE_TEXT_CONTAINER = nsIAccessibleRole.ROLE_TEXT_CONTAINER;
 const ROLE_TEXT_LEAF = nsIAccessibleRole.ROLE_TEXT_LEAF;
 const ROLE_TOGGLE_BUTTON = nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
 const ROLE_TOOLBAR = nsIAccessibleRole.ROLE_TOOLBAR;
 const ROLE_TOOLTIP = nsIAccessibleRole.ROLE_TOOLTIP;
 const ROLE_TREE_TABLE = nsIAccessibleRole.ROLE_TREE_TABLE;
--- a/accessible/tests/mochitest/role/test_aria.html
+++ b/accessible/tests/mochitest/role/test_aria.html
@@ -55,16 +55,17 @@
       testRole("aria_region", ROLE_PANE);
       testRole("aria_row", ROLE_ROW);
       testRole("aria_rowheader", ROLE_ROWHEADER);
       testRole("aria_scrollbar", ROLE_SCROLLBAR);
       testRole("aria_separator", ROLE_SEPARATOR);
       testRole("aria_slider", ROLE_SLIDER);
       testRole("aria_spinbutton", ROLE_SPINBUTTON);
       testRole("aria_status", ROLE_STATUSBAR);
+      testRole("aria_switch", ROLE_SWITCH);
       testRole("aria_tab", ROLE_PAGETAB);
       testRole("aria_tablist", ROLE_PAGETABLIST);
       testRole("aria_tabpanel", ROLE_PROPERTYPAGE);
       testRole("aria_textbox", ROLE_ENTRY);
       testRole("aria_timer", ROLE_TEXT_CONTAINER); // weak role
       testRole("aria_toolbar", ROLE_TOOLBAR);
       testRole("aria_tooltip", ROLE_TOOLTIP);
       testRole("aria_tree", ROLE_OUTLINE);
@@ -173,16 +174,21 @@
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=725432">
     Bug 725432
   </a>
   <a target="_blank"
      title="Map ARIA role FORM"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=735645">
     Bug 735645
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
+     title="Support ARIA 1.1 switch role"
+    Bug 1136563
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <span id="aria_alert" role="alert"/>
   <span id="aria_alertdialog" role="alertdialog"/>
   <span id="aria_application" role="application"/>
@@ -220,16 +226,17 @@
   <span id="aria_region" role="region"/>
   <span id="aria_row" role="row"/>
   <span id="aria_rowheader" role="rowheader"/>
   <span id="aria_scrollbar" role="scrollbar"/>
   <span id="aria_separator" role="separator"/>
   <span id="aria_slider" role="slider"/>
   <span id="aria_spinbutton" role="spinbutton"/>
   <span id="aria_status" role="status"/>
+  <span id="aria_switch" role="switch"/>
   <span id="aria_tab" role="tab"/>
   <span id="aria_tablist" role="tablist"/>
   <span id="aria_tabpanel" role="tabpanel"/>
   <span id="aria_textbox" role="textbox"/>
   <span id="aria_timer" role="timer"/>
   <span id="aria_toolbar" role="toolbar"/>
   <span id="aria_tooltip" role="tooltip"/>
   <span id="aria_tree" role="tree"/>
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -87,16 +87,18 @@
         testStates(checkboxElem, 0, 0, STATE_CHECKED);
         checkboxElem.indeterminate = true;
         testStates(checkboxElem, STATE_MIXED, 0);
       }
 
       // aria-checked
       testStates("aria_checked_checkbox", STATE_CHECKED);
       testStates("aria_mixed_checkbox", STATE_MIXED);
+      testStates("aria_checked_switch", STATE_CHECKED);
+      testStates("aria_mixed_switch", 0, 0, STATE_MIXED); // unsupported
 
       // test disabled group and all its descendants to see if they are
       // disabled, too. See bug 429285.
       testAriaDisabledTree("group");
 
       // aria-modal
       testStates("aria_modal", 0, EXT_STATE_MODAL);
       testStates("aria_modal_false", 0, 0, 0, EXT_STATE_MODAL);
@@ -345,16 +347,21 @@
      title="ARIA grid should be editable by default">
     Mozilla Bug 835121
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
      title="Pressed state is not exposed on a button element with aria-pressed attribute"
     Mozilla Bug 989958
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
+     title="Support ARIA 1.1 switch role"
+    Mozilla Bug 1136563
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="textbox_autocomplete_inline" role="textbox" aria-autocomplete="inline"></div>
   <div id="textbox_autocomplete_list" role="textbox" aria-autocomplete="list"></div>
@@ -378,16 +385,25 @@
 
   <div id="aria_checked_checkbox" role="checkbox" aria-checked="true">
     I agree
   </div>
 
   <div id="aria_mixed_checkbox" role="checkbox" aria-checked="mixed">
     I might agree
   </div>
+
+  <div id="aria_checked_switch" role="switch" aria-checked="true">
+    I am switched on
+  </div>
+
+  <div id="aria_mixed_switch" role="switch" aria-checked="mixed">
+    I am unsupported
+  </div>
+
   <div id="aria_modal" aria-modal="true">modal stuff</div>
   <div id="aria_modal_false" aria-modal="false">non modal stuff</div>div>
   <div id="aria_multiline_textbox" role="textbox" aria-multiline="true"></div>
   <div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
   <div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>
   <button id="aria_pressed_native_button" aria-pressed="true">Button</button>
 
   <div id="aria_readonly_textbox"
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -532,16 +532,18 @@
 @BINPATH@/components/satchel.manifest
 @BINPATH@/components/nsFormAutoComplete.js
 @BINPATH@/components/nsFormHistory.js
 @BINPATH@/components/FormHistoryStartup.js
 @BINPATH@/components/nsInputListAutoComplete.js
 @BINPATH@/components/formautofill.manifest
 @BINPATH@/components/FormAutofillContentService.js
 @BINPATH@/components/FormAutofillStartup.js
+@BINPATH@/components/CSSUnprefixingService.js
+@BINPATH@/components/CSSUnprefixingService.manifest
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
 @BINPATH@/components/SettingsManager.js
 @BINPATH@/components/SettingsManager.manifest
 @BINPATH@/components/SettingsService.js
 @BINPATH@/components/SettingsService.manifest
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1572,16 +1572,19 @@ pref("devtools.browserconsole.filter.war
 pref("devtools.browserconsole.filter.info", true);
 pref("devtools.browserconsole.filter.log", true);
 pref("devtools.browserconsole.filter.secerror", true);
 pref("devtools.browserconsole.filter.secwarn", true);
 
 // Text size in the Web Console. Use 0 for the system default size.
 pref("devtools.webconsole.fontSize", 0);
 
+// Max number of inputs to store in web console history.
+pref("devtools.webconsole.inputHistoryCount", 50);
+
 // Persistent logging: |true| if you want the Web Console to keep all of the
 // logged messages after reloading the page, |false| if you want the output to
 // be cleared each time page navigation happens.
 pref("devtools.webconsole.persistlog", false);
 
 // Web Console timestamp: |true| if you want the logs and instructions
 // in the Web Console to display a timestamp, or |false| to not display
 // any timestamps.
--- a/browser/base/content/browser-syncui.js
+++ b/browser/base/content/browser-syncui.js
@@ -6,33 +6,45 @@ Cu.import("resource://gre/modules/XPCOMU
 
 #ifdef MOZ_SERVICES_CLOUDSYNC
 XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
                                   "resource://gre/modules/CloudSync.jsm");
 #else
 let CloudSync = null;
 #endif
 
+XPCOMUtils.defineLazyModuleGetter(this, "ReadingListScheduler",
+                                  "resource:///modules/readinglist/Scheduler.jsm");
+
 // gSyncUI handles updating the tools menu and displaying notifications.
 let gSyncUI = {
   _obs: ["weave:service:sync:start",
+         "weave:service:sync:finish",
+         "weave:service:sync:error",
          "weave:service:quota:remaining",
          "weave:service:setup-complete",
          "weave:service:login:start",
          "weave:service:login:finish",
+         "weave:service:login:error",
          "weave:service:logout:finish",
          "weave:service:start-over",
          "weave:service:start-over:finish",
          "weave:ui:login:error",
          "weave:ui:sync:error",
          "weave:ui:sync:finish",
          "weave:ui:clear-error",
+
+         "readinglist:sync:start",
+         "readinglist:sync:finish",
+         "readinglist:sync:error",
   ],
 
   _unloaded: false,
+  // The number of "active" syncs - while this is non-zero, our button will spin
+  _numActiveSyncTasks: 0,
 
   init: function () {
     Cu.import("resource://services-common/stringbundle.js");
 
     // Proceed to set up the UI if Sync has already started up.
     // Otherwise we'll do it when Sync is firing up.
     let xps = Components.classes["@mozilla.org/weave/service;1"]
                                 .getService(Components.interfaces.nsISupports)
@@ -90,148 +102,182 @@ let gSyncUI = {
     // notificationbox will listen to observers from now on.
     Services.obs.removeObserver(this, "weave:notification:added");
     let idx = this._obs.indexOf("weave:notification:added");
     if (idx >= 0) {
       this._obs.splice(idx, 1);
     }
   },
 
-  _needsSetup: function SUI__needsSetup() {
+  _needsSetup() {
     // We want to treat "account needs verification" as "needs setup". So
     // "reach in" to Weave.Status._authManager to check whether we the signed-in
     // user is verified.
     // Referencing Weave.Status spins a nested event loop to initialize the
     // authManager, so this should always return a value directly.
     // This only applies to fxAccounts-based Sync.
-    if (Weave.Status._authManager._signedInUser) {
-      // If we have a signed in user already, and that user is not verified,
-      // revert to the "needs setup" state.
-      if (!Weave.Status._authManager._signedInUser.verified) {
-        return true;
-      }
+    if (Weave.Status._authManager._signedInUser !== undefined) {
+      // So we are using Firefox accounts - in this world, checking Sync isn't
+      // enough as reading list may be configured but not Sync.
+      // We consider ourselves setup if we have a verified user.
+      // XXX - later we should consider checking preferences to ensure at least
+      // one engine is enabled?
+      return !Weave.Status._authManager._signedInUser ||
+             !Weave.Status._authManager._signedInUser.verified;
     }
 
+    // So we are using legacy sync, and reading-list isn't supported for such
+    // users, so check sync itself.
     let firstSync = "";
     try {
       firstSync = Services.prefs.getCharPref("services.sync.firstSync");
     } catch (e) { }
 
     return Weave.Status.checkSetup() == Weave.CLIENT_NOT_CONFIGURED ||
            firstSync == "notReady";
   },
 
   _loginFailed: function () {
-    return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
+    return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED ||
+           ReadingListScheduler.state == ReadingListScheduler.STATE_ERROR_AUTHENTICATION;
   },
 
   updateUI: function SUI_updateUI() {
     let needsSetup = this._needsSetup();
     let loginFailed = this._loginFailed();
 
     // Start off with a clean slate
     document.getElementById("sync-reauth-state").hidden = true;
     document.getElementById("sync-setup-state").hidden = true;
     document.getElementById("sync-syncnow-state").hidden = true;
 
     if (CloudSync && CloudSync.ready && CloudSync().adapters.count) {
       document.getElementById("sync-syncnow-state").hidden = false;
     } else if (loginFailed) {
       document.getElementById("sync-reauth-state").hidden = false;
+      this.showLoginError();
     } else if (needsSetup) {
       document.getElementById("sync-setup-state").hidden = false;
     } else {
       document.getElementById("sync-syncnow-state").hidden = false;
     }
 
     if (!gBrowser)
       return;
 
     let syncButton = document.getElementById("sync-button");
-    if (syncButton) {
-      syncButton.removeAttribute("status");
-    }
-    let panelHorizontalButton = document.getElementById("PanelUI-fxa-status");
-    if (panelHorizontalButton) {
-      panelHorizontalButton.removeAttribute("syncstatus");
-    }
-
     if (needsSetup && syncButton)
       syncButton.removeAttribute("tooltiptext");
 
     this._updateLastSyncTime();
   },
 
 
   // Functions called by observers
-  onActivityStart: function SUI_onActivityStart() {
+  onActivityStart() {
     if (!gBrowser)
       return;
 
-    let button = document.getElementById("sync-button");
-    if (button) {
-      button.setAttribute("status", "active");
+    this.log.debug("onActivityStart with numActive", this._numActiveSyncTasks);
+    if (++this._numActiveSyncTasks == 1) {
+      let button = document.getElementById("sync-button");
+      if (button) {
+        button.setAttribute("status", "active");
+      }
+      button = document.getElementById("PanelUI-fxa-status");
+      if (button) {
+        button.setAttribute("syncstatus", "active");
+      }
     }
-    button = document.getElementById("PanelUI-fxa-status");
-    if (button) {
-      button.setAttribute("syncstatus", "active");
+  },
+
+  onActivityStop() {
+    if (!gBrowser)
+      return;
+    this.log.debug("onActivityStop with numActive", this._numActiveSyncTasks);
+    if (--this._numActiveSyncTasks) {
+      if (this._numActiveSyncTasks < 0) {
+        // This isn't particularly useful (it seems more likely we'll set a
+        // "start" without a "stop" meaning it forever remains > 0) but it
+        // might offer some value...
+        this.log.error("mismatched onActivityStart/Stop calls",
+                       new Error("active=" + this._numActiveSyncTasks));
+      }
+      return; // active tasks are still ongoing...
+    }
+
+    let syncButton = document.getElementById("sync-button");
+    if (syncButton) {
+      syncButton.removeAttribute("status");
+    }
+    let panelHorizontalButton = document.getElementById("PanelUI-fxa-status");
+    if (panelHorizontalButton) {
+      panelHorizontalButton.removeAttribute("syncstatus");
     }
   },
 
   onLoginFinish: function SUI_onLoginFinish() {
     // Clear out any login failure notifications
     let title = this._stringBundle.GetStringFromName("error.login.title");
     this.clearError(title);
   },
 
   onSetupComplete: function SUI_onSetupComplete() {
     this.onLoginFinish();
   },
 
   onLoginError: function SUI_onLoginError() {
+    // Note: This is used for *both* Sync and ReadingList login errors.
     // if login fails, any other notifications are essentially moot
     Weave.Notifications.removeAll();
 
     // if we haven't set up the client, don't show errors
     if (this._needsSetup()) {
       this.updateUI();
       return;
     }
     // if we are still waiting for the identity manager to initialize, don't show errors
     if (Weave.Status.login == Weave.LOGIN_FAILED_NOT_READY) {
       this.updateUI();
       return;
     }
+    this.showLoginError();
+    this.updateUI();
+  },
 
+  showLoginError() {
+    // Note: This is used for *both* Sync and ReadingList login errors.
     let title = this._stringBundle.GetStringFromName("error.login.title");
 
     let description;
-    if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) {
+    if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE ||
+        this.isProlongedReadingListError()) {
+      this.log.debug("showLoginError has a prolonged login error");
       // Convert to days
       let lastSync =
         Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
       description =
         this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1);
     } else {
       let reason = Weave.Utils.getErrorString(Weave.Status.login);
       description =
         this._stringBundle.formatStringFromName("error.sync.description", [reason], 1);
+      this.log.debug("showLoginError has a non-prolonged error", reason);
     }
 
     let buttons = [];
     buttons.push(new Weave.NotificationButton(
       this._stringBundle.GetStringFromName("error.login.prefs.label"),
       this._stringBundle.GetStringFromName("error.login.prefs.accesskey"),
       function() { gSyncUI.openPrefs(); return true; }
     ));
 
     let notification = new Weave.Notification(title, description, null,
                                               Weave.Notifications.PRIORITY_WARNING, buttons);
     Weave.Notifications.replaceTitle(notification);
-    this.updateUI();
   },
 
   onLogout: function SUI_onLogout() {
     this.updateUI();
   },
 
   onStartOver: function SUI_onStartOver() {
     this.clearError();
@@ -266,16 +312,17 @@ let gSyncUI = {
   doSync: function SUI_doSync() {
     let needsSetup = this._needsSetup();
 
     if (!needsSetup) {
       setTimeout(function () Weave.Service.errorHandler.syncAndReportErrors(), 0);
     }
 
     Services.obs.notifyObservers(null, "cloudsync:user-sync", null);
+    Services.obs.notifyObservers(null, "readinglist:user-sync", null);
   },
 
   handleToolbarButton: function SUI_handleStatusbarButton() {
     if (this._needsSetup())
       this.openSetup();
     else
       this.doSync();
   },
@@ -362,45 +409,115 @@ let gSyncUI = {
       return;
 
     let syncButton = document.getElementById("sync-button");
     if (!syncButton)
       return;
 
     let lastSync;
     try {
-      lastSync = Services.prefs.getCharPref("services.sync.lastSync");
+      lastSync = new Date(Services.prefs.getCharPref("services.sync.lastSync"));
+    }
+    catch (e) { };
+    // and reading-list time - we want whatever one is the most recent.
+    try {
+      let lastRLSync = new Date(Services.prefs.getCharPref("readinglist.scheduler.lastSync"));
+      if (!lastSync || lastRLSync > lastSync) {
+        lastSync = lastRLSync;
+      }
     }
     catch (e) { };
     if (!lastSync || this._needsSetup()) {
       syncButton.removeAttribute("tooltiptext");
       return;
     }
 
     // Show the day-of-week and time (HH:MM) of last sync
-    let lastSyncDate = new Date(lastSync).toLocaleFormat("%a %H:%M");
+    let lastSyncDateString = lastSync.toLocaleFormat("%a %H:%M");
     let lastSyncLabel =
-      this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDate], 1);
+      this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
 
     syncButton.setAttribute("tooltiptext", lastSyncLabel);
   },
 
   clearError: function SUI_clearError(errorString) {
     Weave.Notifications.removeAll(errorString);
     this.updateUI();
   },
 
   onSyncFinish: function SUI_onSyncFinish() {
     let title = this._stringBundle.GetStringFromName("error.sync.title");
 
     // Clear out sync failures on a successful sync
     this.clearError(title);
   },
 
+  // Return true if the reading-list is in a "prolonged" error state. That
+  // engine doesn't impose what that means, so calculate it here. For
+  // consistency, we just use the sync prefs.
+  isProlongedReadingListError() {
+    let lastSync, threshold, prolonged;
+    try {
+      lastSync = new Date(Services.prefs.getCharPref("readinglist.scheduler.lastSync"));
+      threshold = new Date(Date.now() - Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout"));
+      prolonged = lastSync <= threshold;
+    } catch (ex) {
+      // no pref, assume not prolonged.
+      prolonged = false;
+    }
+    this.log.debug("isProlongedReadingListError has last successful sync at ${lastSync}, threshold is ${threshold}, prolonged=${prolonged}",
+                   {lastSync, threshold, prolonged});
+    return prolonged;
+  },
+
+  onRLSyncError() {
+    // Like onSyncError, but from the reading-list engine.
+    // However, the current UX around Sync is that error notifications should
+    // generally *not* be seen as they typically aren't actionable - so only
+    // authentication errors (which require user action) and "prolonged" errors
+    // (which technically aren't actionable, but user really should know anyway)
+    // are shown.
+    this.log.debug("onRLSyncError with readingList state", ReadingListScheduler.state);
+    if (ReadingListScheduler.state == ReadingListScheduler.STATE_ERROR_AUTHENTICATION) {
+      this.onLoginError();
+      return;
+    }
+    // If it's not prolonged there's nothing to do.
+    if (!this.isProlongedReadingListError()) {
+      this.log.debug("onRLSyncError has a non-authentication, non-prolonged error, so not showing any error UI");
+      return;
+    }
+    // So it's a prolonged error.
+    // Unfortunate duplication from below...
+    this.log.debug("onRLSyncError has a prolonged error");
+    let title = this._stringBundle.GetStringFromName("error.sync.title");
+    // XXX - this is somewhat wrong - we are reporting the threshold we consider
+    // to be prolonged, not how long it actually has been. (ie, lastSync below
+    // is effectively constant) - bit it too is copied from below.
+    let lastSync =
+      Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
+    let description =
+      this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1);
+    let priority = Weave.Notifications.PRIORITY_INFO;
+    let buttons = [
+      new Weave.NotificationButton(
+        this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"),
+        this._stringBundle.GetStringFromName("error.sync.tryAgainButton.accesskey"),
+        function() { gSyncUI.doSync(); return true; }
+      ),
+    ];
+    let notification =
+      new Weave.Notification(title, description, null, priority, buttons);
+    Weave.Notifications.replaceTitle(notification);
+
+    this.updateUI();
+  },
+
   onSyncError: function SUI_onSyncError() {
+    this.log.debug("onSyncError");
     let title = this._stringBundle.GetStringFromName("error.sync.title");
 
     if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
       this.onLoginError();
       return;
     }
 
     let description;
@@ -413,17 +530,19 @@ let gSyncUI = {
     } else {
       let error = Weave.Utils.getErrorString(Weave.Status.sync);
       description =
         this._stringBundle.formatStringFromName("error.sync.description", [error], 1);
     }
     let priority = Weave.Notifications.PRIORITY_WARNING;
     let buttons = [];
 
-    // Check if the client is outdated in some way
+    // Check if the client is outdated in some way (but note: we've never in the
+    // past, and probably never will, bump the relevent version numbers, so
+    // this is effectively dead code!)
     let outdated = Weave.Status.sync == Weave.VERSION_OUT_OF_DATE;
     for (let [engine, reason] in Iterator(Weave.Status.engines))
       outdated = outdated || reason == Weave.VERSION_OUT_OF_DATE;
 
     if (outdated) {
       description = this._stringBundle.GetStringFromName(
         "error.sync.needUpdate.description");
       buttons.push(new Weave.NotificationButton(
@@ -463,47 +582,61 @@ let gSyncUI = {
     let notification =
       new Weave.Notification(title, description, null, priority, buttons);
     Weave.Notifications.replaceTitle(notification);
 
     this.updateUI();
   },
 
   observe: function SUI_observe(subject, topic, data) {
+    this.log.debug("observed", topic);
     if (this._unloaded) {
       Cu.reportError("SyncUI observer called after unload: " + topic);
       return;
     }
 
     // Unwrap, just like Svc.Obs, but without pulling in that dependency.
     if (subject && typeof subject == "object" &&
         ("wrappedJSObject" in subject) &&
         ("observersModuleSubjectWrapper" in subject.wrappedJSObject)) {
       subject = subject.wrappedJSObject.object;
     }
 
+    // First handle "activity" only.
     switch (topic) {
       case "weave:service:sync:start":
+      case "weave:service:login:start":
+      case "readinglist:sync:start":
         this.onActivityStart();
         break;
+      case "weave:service:sync:finish":
+      case "weave:service:sync:error":
+      case "weave:service:login:finish":
+      case "weave:service:login:error":
+      case "readinglist:sync:finish":
+      case "readinglist:sync:error":
+        this.onActivityStop();
+        break;
+    }
+    // Now non-activity state (eg, enabled, errors, etc)
+    // Note that sync uses the ":ui:" notifications for errors because sync.
+    // ReadingList has no such concept (yet?; hopefully the :error is enough!)
+    switch (topic) {
       case "weave:ui:sync:finish":
         this.onSyncFinish();
         break;
       case "weave:ui:sync:error":
         this.onSyncError();
         break;
       case "weave:service:quota:remaining":
         this.onQuotaNotice();
         break;
       case "weave:service:setup-complete":
         this.onSetupComplete();
         break;
-      case "weave:service:login:start":
-        this.onActivityStart();
-        break;
       case "weave:service:login:finish":
         this.onLoginFinish();
         break;
       case "weave:ui:login:error":
         this.onLoginError();
         break;
       case "weave:service:logout:finish":
         this.onLogout();
@@ -518,16 +651,23 @@ let gSyncUI = {
         this.initUI();
         break;
       case "weave:notification:added":
         this.initNotifications();
         break;
       case "weave:ui:clear-error":
         this.clearError();
         break;
+
+      case "readinglist:sync:error":
+        this.onRLSyncError();
+        break;
+      case "readinglist:sync:finish":
+        this.clearError();
+        break;
     }
   },
 
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsIObserver,
     Ci.nsISupportsWeakReference
   ])
 };
@@ -535,8 +675,11 @@ let gSyncUI = {
 XPCOMUtils.defineLazyGetter(gSyncUI, "_stringBundle", function() {
   //XXXzpao these strings should probably be moved from /services to /browser... (bug 583381)
   //        but for now just make it work
   return Cc["@mozilla.org/intl/stringbundle;1"].
          getService(Ci.nsIStringBundleService).
          createBundle("chrome://weave/locale/services/sync.properties");
 });
 
+XPCOMUtils.defineLazyGetter(gSyncUI, "log", function() {
+  return Log.repository.getLogger("browserwindow.syncui");
+});
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -32,16 +32,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
                                   "resource://gre/modules/GMPInstallManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
                                   "resource://gre/modules/NewTabUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
                                   "resource:///modules/ContentSearch.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
                                   "resource:///modules/AboutHome.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Log",
+                                  "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
                                    "@mozilla.org/browser/favicon-service;1",
                                    "mozIAsyncFavicons");
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 
 const nsIWebNavigation = Ci.nsIWebNavigation;
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -398,16 +398,18 @@ skip-if = buildapp == 'mulet' || e10s # 
 skip-if = e10s
 support-files =
   searchSuggestionUI.html
   searchSuggestionUI.js
 [browser_selectTabAtIndex.js]
 [browser_ssl_error_reports.js]
 [browser_star_hsts.js]
 [browser_subframe_favicons_not_used.js]
+[browser_syncui.js]
+skip-if = e10s # Bug 1137087 - browser_tabopen_reflows.js fails if this was previously run with e10s
 [browser_tabDrop.js]
 skip-if = buildapp == 'mulet' || e10s
 [browser_tabMatchesInAwesomebar.js]
 [browser_tabMatchesInAwesomebar_perwindowpb.js]
 skip-if = e10s || os == 'linux' # Bug 1093373, bug 1104755
 [browser_tab_drag_drop_perwindow.js]
 skip-if = buildapp == 'mulet'
 [browser_tab_dragdrop.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_syncui.js
@@ -0,0 +1,244 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let {Log} = Cu.import("resource://gre/modules/Log.jsm", {});
+let {Weave} = Cu.import("resource://services-sync/main.js", {});
+let {Notifications} = Cu.import("resource://services-sync/notifications.js", {});
+// The BackStagePass allows us to get this test-only non-exported function.
+let {getInternalScheduler} = Cu.import("resource:///modules/readinglist/Scheduler.jsm", {});
+
+let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"]
+                   .getService(Ci.nsIStringBundleService)
+                   .createBundle("chrome://weave/locale/services/sync.properties");
+
+// ensure test output sees log messages.
+Log.repository.getLogger("browserwindow.syncui").addAppender(new Log.DumpAppender());
+
+function promiseObserver(topic) {
+  return new Promise(resolve => {
+    let obs = (subject, topic, data) => {
+      Services.obs.removeObserver(obs, topic);
+      resolve(subject);
+    }
+    Services.obs.addObserver(obs, topic, false);
+  });
+}
+
+add_task(function* prepare() {
+  let xps = Components.classes["@mozilla.org/weave/service;1"]
+                              .getService(Components.interfaces.nsISupports)
+                              .wrappedJSObject;
+  yield xps.whenLoaded();
+  // mock out the "_needsSetup()" function so we don't short-circuit.
+  let oldNeedsSetup = window.gSyncUI._needsSetup;
+  window.gSyncUI._needsSetup = () => false;
+  registerCleanupFunction(() => {
+    window.gSyncUI._needsSetup = oldNeedsSetup;
+  });
+});
+
+add_task(function* testProlongedSyncError() {
+  let promiseNotificationAdded = promiseObserver("weave:notification:added");
+  Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
+
+  // Pretend we are in the "prolonged error" state.
+  Weave.Status.sync = Weave.PROLONGED_SYNC_FAILURE;
+  Weave.Status.login = Weave.LOGIN_SUCCEEDED;
+  Services.obs.notifyObservers(null, "weave:ui:sync:error", null);
+
+  let subject = yield promiseNotificationAdded;
+  let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
+  Assert.equal(notification.title, stringBundle.GetStringFromName("error.sync.title"));
+  Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
+
+  // Now pretend we just had a successful sync - the error notification should go away.
+  let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
+  Weave.Status.sync = Weave.STATUS_OK;
+  Services.obs.notifyObservers(null, "weave:ui:sync:finish", null);
+  yield promiseNotificationRemoved;
+  Assert.equal(Notifications.notifications.length, 0, "no notifications left");
+});
+
+add_task(function* testProlongedRLError() {
+  let promiseNotificationAdded = promiseObserver("weave:notification:added");
+  Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
+
+  // Pretend the reading-list is in the "prolonged error" state.
+  let longAgo = new Date(Date.now() - 100 * 24 * 60 * 60 * 1000); // 100 days ago.
+  Services.prefs.setCharPref("readinglist.scheduler.lastSync", longAgo.toString());
+  getInternalScheduler().state = ReadingListScheduler.STATE_ERROR_OTHER;
+  Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+  Services.obs.notifyObservers(null, "readinglist:sync:error", null);
+
+  let subject = yield promiseNotificationAdded;
+  let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
+  Assert.equal(notification.title, stringBundle.GetStringFromName("error.sync.title"));
+  Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
+
+  // Now pretend we just had a successful sync - the error notification should go away.
+  let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
+  Services.prefs.setCharPref("readinglist.scheduler.lastSync", Date.now().toString());
+  Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+  Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
+  yield promiseNotificationRemoved;
+  Assert.equal(Notifications.notifications.length, 0, "no notifications left");
+});
+
+add_task(function* testSyncLoginError() {
+  let promiseNotificationAdded = promiseObserver("weave:notification:added");
+  Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
+
+  // Pretend we are in the "prolonged error" state.
+  Weave.Status.sync = Weave.LOGIN_FAILED;
+  Weave.Status.login = Weave.LOGIN_FAILED_LOGIN_REJECTED;
+  Services.obs.notifyObservers(null, "weave:ui:sync:error", null);
+
+  let subject = yield promiseNotificationAdded;
+  let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
+  Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
+  Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
+
+  // Now pretend we just had a successful login - the error notification should go away.
+  Weave.Status.sync = Weave.STATUS_OK;
+  Weave.Status.login = Weave.LOGIN_SUCCEEDED;
+  let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
+  Services.obs.notifyObservers(null, "weave:service:login:start", null);
+  Services.obs.notifyObservers(null, "weave:service:login:finish", null);
+  yield promiseNotificationRemoved;
+  Assert.equal(Notifications.notifications.length, 0, "no notifications left");
+});
+
+add_task(function* testRLLoginError() {
+  let promiseNotificationAdded = promiseObserver("weave:notification:added");
+  Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
+
+  // Pretend RL is in an auth error state
+  getInternalScheduler().state = ReadingListScheduler.STATE_ERROR_AUTHENTICATION;
+  Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+  Services.obs.notifyObservers(null, "readinglist:sync:error", null);
+
+  let subject = yield promiseNotificationAdded;
+  let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
+  Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
+  Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
+
+  // Now pretend we just had a successful sync - the error notification should go away.
+  getInternalScheduler().state = ReadingListScheduler.STATE_OK;
+  let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
+  Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+  Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
+  yield promiseNotificationRemoved;
+  Assert.equal(Notifications.notifications.length, 0, "no notifications left");
+});
+
+// Here we put readinglist into an "authentication error" state (should see
+// the error bar reflecting this), then report a prolonged error from Sync (an
+// infobar to reflect the sync error should replace it), then resolve the sync
+// error - the authentication error from readinglist should remain.
+add_task(function* testRLLoginErrorRemains() {
+  let promiseNotificationAdded = promiseObserver("weave:notification:added");
+  Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
+
+  // Pretend RL is in an auth error state
+  getInternalScheduler().state = ReadingListScheduler.STATE_ERROR_AUTHENTICATION;
+  Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+  Services.obs.notifyObservers(null, "readinglist:sync:error", null);
+
+  let subject = yield promiseNotificationAdded;
+  let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
+  Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
+  Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
+
+  // Now Sync into a prolonged auth error state.
+  promiseNotificationAdded = promiseObserver("weave:notification:added");
+  Weave.Status.sync = Weave.PROLONGED_SYNC_FAILURE;
+  Weave.Status.login = Weave.LOGIN_FAILED_LOGIN_REJECTED;
+  Services.obs.notifyObservers(null, "weave:ui:sync:error", null);
+  subject = yield promiseNotificationAdded;
+  // still exactly 1 notification with the "login" title.
+  notification = subject.wrappedJSObject.object;
+  Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
+  Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
+
+  // Resolve the sync problem.
+  promiseNotificationAdded = promiseObserver("weave:notification:added");
+  Weave.Status.sync = Weave.STATUS_OK;
+  Weave.Status.login = Weave.LOGIN_SUCCEEDED;
+  Services.obs.notifyObservers(null, "weave:ui:sync:finish", null);
+
+  // Expect one notification - the RL login problem.
+  subject = yield promiseNotificationAdded;
+  // still exactly 1 notification with the "login" title.
+  notification = subject.wrappedJSObject.object;
+  Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
+  Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
+
+  // and cleanup - resolve the readinglist error.
+  getInternalScheduler().state = ReadingListScheduler.STATE_OK;
+  let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
+  Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+  Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
+  yield promiseNotificationRemoved;
+  Assert.equal(Notifications.notifications.length, 0, "no notifications left");
+});
+
+function checkButtonsStatus(shouldBeActive) {
+  let button = document.getElementById("sync-button");
+  let panelbutton = document.getElementById("PanelUI-fxa-status");
+  if (shouldBeActive) {
+    Assert.equal(button.getAttribute("status"), "active");
+    Assert.equal(panelbutton.getAttribute("syncstatus"), "active");
+  } else {
+    Assert.ok(!button.hasAttribute("status"));
+    Assert.ok(!panelbutton.hasAttribute("syncstatus"));
+  }
+}
+
+function testButtonActions(startNotification, endNotification) {
+  checkButtonsStatus(false);
+  // pretend a sync is starting.
+  Services.obs.notifyObservers(null, startNotification, null);
+  checkButtonsStatus(true);
+  // and has stopped
+  Services.obs.notifyObservers(null, endNotification, null);
+  checkButtonsStatus(false);
+}
+
+add_task(function* testButtonActivities() {
+  // add the Sync button to the panel so we can get it!
+  CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_PANEL);
+  // check the button's functionality
+  yield PanelUI.show();
+  try {
+    testButtonActions("weave:service:login:start", "weave:service:login:finish");
+    testButtonActions("weave:service:login:start", "weave:service:login:error");
+
+    testButtonActions("weave:service:sync:start", "weave:service:sync:finish");
+    testButtonActions("weave:service:sync:start", "weave:service:sync:error");
+
+    testButtonActions("readinglist:sync:start", "readinglist:sync:finish");
+    testButtonActions("readinglist:sync:start", "readinglist:sync:error");
+
+    // and ensure the counters correctly handle multiple in-flight syncs
+    Services.obs.notifyObservers(null, "weave:service:sync:start", null);
+    checkButtonsStatus(true);
+    Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+    checkButtonsStatus(true);
+    Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
+    // sync is still going...
+    checkButtonsStatus(true);
+    // another reading list starts
+    Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+    checkButtonsStatus(true);
+    // The initial sync stops.
+    Services.obs.notifyObservers(null, "weave:service:sync:finish", null);
+    // RL is still going...
+    checkButtonsStatus(true);
+    // RL finishes with an error, so no longer active.
+    Services.obs.notifyObservers(null, "readinglist:sync:error", null);
+    checkButtonsStatus(false);
+  } finally {
+    PanelUI.hide();
+    CustomizableUI.removeWidgetFromArea("sync-button");
+  }
+});
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -1,14 +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/. */
 
 let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
                                   "resource://gre/modules/DownloadUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
                                   "resource:///modules/DownloadsCommon.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadsViewUI",
                                   "resource:///modules/DownloadsViewUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -61,16 +61,18 @@
  * us to draw a ring around the currently focused element. If the panel is
  * closed or the mouse moves over the panel, we remove the attribute.
  */
 
 "use strict";
 
 let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
                                   "resource:///modules/DownloadsCommon.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadsViewUI",
                                   "resource:///modules/DownloadsViewUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
new file mode 100644
--- /dev/null
+++ b/browser/components/readinglist/Scheduler.jsm
@@ -0,0 +1,338 @@
+/* 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");
+
+
+XPCOMUtils.defineLazyModuleGetter(this, 'LogManager',
+  'resource://services-common/logmanager.js');
+
+XPCOMUtils.defineLazyModuleGetter(this, 'Log',
+  'resource://gre/modules/Log.jsm');
+
+XPCOMUtils.defineLazyModuleGetter(this, 'Preferences',
+  'resource://gre/modules/Preferences.jsm');
+
+XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout',
+  'resource://gre/modules/Timer.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'clearTimeout',
+  'resource://gre/modules/Timer.jsm');
+
+Cu.import('resource://gre/modules/Task.jsm');
+
+this.EXPORTED_SYMBOLS = ["ReadingListScheduler"];
+
+// A list of "external" observer topics that may cause us to change when we
+// sync.
+const OBSERVERS = [
+  // We don't sync when offline and restart when online.
+  "network:offline-status-changed",
+  // FxA notifications also cause us to check if we should sync.
+  "fxaccounts:onverified",
+  // When something notices a local change to an item.
+  "readinglist:item-changed",
+  // some notifications the engine might send if we have been requested to backoff.
+  "readinglist:backoff-requested",
+  // request to sync now
+  "readinglist:user-sync",
+
+];
+
+///////// A temp object until we get our "engine"
+let engine = {
+  ERROR_AUTHENTICATION: "authentication error",
+  sync: Task.async(function* () {
+  }),
+}
+
+let prefs = new Preferences("readinglist.scheduler.");
+
+// A helper to manage our interval values.
+let intervals = {
+  // Getters for our intervals.
+  _fixupIntervalPref(prefName, def) {
+    // All pref values are seconds, but we return ms.
+    return prefs.get(prefName, def) * 1000;
+  },
+
+  // How long after startup do we do an initial sync?
+  get initial() this._fixupIntervalPref("initial", 20), // 20 seconds.
+  // Every interval after the first.
+  get schedule() this._fixupIntervalPref("schedule", 2 * 60 * 60), // 2 hours
+  // After we've been told an item has changed
+  get dirty() this._fixupIntervalPref("dirty", 2 * 60), // 2 mins
+  // After an error
+  get retry() this._fixupIntervalPref("retry", 2 * 60), // 2 mins
+};
+
+// This is the implementation, but it's not exposed directly.
+function InternalScheduler() {
+  // oh, I don't know what logs yet - let's guess!
+  let logs = ["readinglist", "FirefoxAccounts", "browserwindow.syncui"];
+  this._logManager = new LogManager("readinglist.", logs, "readinglist");
+  this.log = Log.repository.getLogger("readinglist.scheduler");
+  this.log.info("readinglist scheduler created.")
+  this.state = this.STATE_OK;
+
+  // don't this.init() here, but instead at the module level - tests want to
+  // add hooks before it is called.
+}
+
+InternalScheduler.prototype = {
+  // When the next scheduled sync should happen.  If we can sync, there will
+  // be a timer set to fire then. If we can't sync there will not be a timer,
+  // but it will be set to fire then as soon as we can.
+  _nextScheduledSync: null,
+  // The time when the most-recent "backoff request" expires - we will never
+  // schedule a new timer before this.
+  _backoffUntil: 0,
+  // Our current timer.
+  _timer: null,
+  // Our timer fires a promise - _timerRunning is true until it resolves or
+  // rejects.
+  _timerRunning: false,
+  // Our sync engine - XXX - maybe just a callback?
+  _engine: engine,
+
+  // Our state variable and constants.
+  state: null,
+  STATE_OK: "ok",
+  STATE_ERROR_AUTHENTICATION: "authentication error",
+  STATE_ERROR_OTHER: "other error",
+
+  init() {
+    this.log.info("scheduler initialzing");
+    this._observe = this.observe.bind(this);
+    for (let notification of OBSERVERS) {
+      Services.obs.addObserver(this._observe, notification, false);
+    }
+    this._nextScheduledSync = Date.now() + intervals.initial;
+    this._setupTimer();
+  },
+
+  // Note: only called by tests.
+  finalize() {
+    this.log.info("scheduler finalizing");
+    this._clearTimer();
+    for (let notification of OBSERVERS) {
+      Services.obs.removeObserver(this._observe, notification);
+    }
+    this._observe = null;
+  },
+
+  observe(subject, topic, data) {
+    this.log.debug("observed ${}", topic);
+    switch (topic) {
+      case "readinglist:backoff-requested": {
+        // The subject comes in as a string, a number of seconds.
+        let interval = parseInt(data, 10);
+        if (isNaN(interval)) {
+          this.log.warn("Backoff request had non-numeric value", data);
+          return;
+        }
+        this.log.info("Received a request to backoff for ${} seconds", interval);
+        this._backoffUntil = Date.now() + interval * 1000;
+        this._maybeReschedule(0);
+        break;
+      }
+      case "readinglist:local:dirty":
+        this._maybeReschedule(intervals.dirty);
+        break;
+      case "readinglist:user-sync":
+        this._syncNow();
+        break;
+      case "fxaccounts:onverified":
+        // If we were in an authentication error state, reset that now.
+        if (this.state == this.STATE_ERROR_AUTHENTICATION) {
+          this.state = this.STATE_OK;
+        }
+        break;
+
+      // The rest just indicate that now is probably a good time to check if
+      // we can sync as normal using whatever schedule was previously set.
+      default:
+        break;
+    }
+    // When observers fire we ignore the current sync error state as the
+    // notification may indicate it's been resolved.
+    this._setupTimer(true);
+  },
+
+  // Is the current error state such that we shouldn't schedule a new sync.
+  _isBlockedOnError() {
+    // this needs more thought...
+    return this.state == this.STATE_ERROR_AUTHENTICATION;
+  },
+
+  // canSync indicates if we can currently sync.
+  _canSync(ignoreBlockingErrors = false) {
+    if (Services.io.offline) {
+      this.log.info("canSync=false - we are offline");
+      return false;
+    }
+    if (!ignoreBlockingErrors && this._isBlockedOnError()) {
+      this.log.info("canSync=false - we are in a blocked error state", this.state);
+      return false;
+    }
+    this.log.info("canSync=true");
+    return true;
+  },
+
+  // _setupTimer checks the current state and the environment to see when
+  // we should next sync and creates the timer with the appropriate delay.
+  _setupTimer(ignoreBlockingErrors = false) {
+    if (!this._canSync(ignoreBlockingErrors)) {
+      this._clearTimer();
+      return;
+    }
+    if (this._timer) {
+      let when = new Date(this._nextScheduledSync);
+      let delay = this._nextScheduledSync - Date.now();
+      this.log.info("checkStatus - already have a timer - will fire in ${delay}ms at ${when}",
+                    {delay, when});
+      return;
+    }
+    if (this._timerRunning) {
+      this.log.info("checkStatus - currently syncing");
+      return;
+    }
+    // no timer and we can sync, so start a new one.
+    let now = Date.now();
+    let delay = Math.max(0, this._nextScheduledSync - now);
+    let when = new Date(now + delay);
+    this.log.info("next scheduled sync is in ${delay}ms (at ${when})", {delay, when})
+    this._timer = this._setTimeout(delay);
+  },
+
+  // Something (possibly naively) thinks the next sync should happen in
+  // delay-ms. If there's a backoff in progress, ignore the requested delay
+  // and use the back-off. If there's already a timer scheduled for earlier
+  // than delay, let the earlier timer remain. Otherwise, use the requested
+  // delay.
+  _maybeReschedule(delay) {
+    // If there's no delay specified and there's nothing currently scheduled,
+    // it means a backoff request while the sync is actually running - there's
+    // no need to do anything here - the next reschedule after the sync
+    // completes will take the backoff into account.
+    if (!delay && !this._nextScheduledSync) {
+      this.log.debug("_maybeReschedule ignoring a backoff request while running");
+      return;
+    }
+    let now = Date.now();
+    if (!this._nextScheduledSync) {
+      this._nextScheduledSync = now + delay;
+    }
+    // If there is something currently scheduled before the requested delay,
+    // keep the existing value (eg, if we have a timer firing in 1 second, and
+    // get a "dirty" notification that says we should sync in 2 seconds, we
+    // keep the 1 second value)
+    this._nextScheduledSync = Math.min(this._nextScheduledSync, now + delay);
+    // But we still need to honor a backoff.
+    this._nextScheduledSync = Math.max(this._nextScheduledSync, this._backoffUntil);
+    // And always create a new timer next time _setupTimer is called.
+    this._clearTimer();
+  },
+
+  // callback for when the timer fires.
+  _doSync() {
+    this.log.debug("starting sync");
+    this._timer = null;
+    this._timerRunning = true;
+    // flag that there's no new schedule yet, so a request coming in while
+    // we are running does the right thing.
+    this._nextScheduledSync = 0;
+    Services.obs.notifyObservers(null, "readinglist:sync:start", null);
+    this._engine.sync().then(() => {
+      this.log.info("Sync completed successfully");
+      // Write a pref in the same format used to services/sync to indicate
+      // the last success.
+      prefs.set("lastSync", new Date().toString());
+      this.state = this.STATE_OK;
+      this._logManager.resetFileLog(this._logManager.REASON_SUCCESS);
+      Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
+      return intervals.schedule;
+    }).catch(err => {
+      this.log.error("Sync failed", err);
+      // XXX - how to detect an auth error?
+      this.state = err == this._engine.ERROR_AUTHENTICATION ?
+                   this.STATE_ERROR_AUTHENTICATION : this.STATE_ERROR_OTHER;
+      this._logManager.resetFileLog(this._logManager.REASON_ERROR);
+      Services.obs.notifyObservers(null, "readinglist:sync:error", null);
+      return intervals.retry;
+    }).then(nextDelay => {
+      this._timerRunning = false;
+      // ensure a new timer is setup for the appropriate next time.
+      this._maybeReschedule(nextDelay);
+      this._setupTimer();
+      this._onAutoReschedule(); // just for tests...
+    }).catch(err => {
+      // We should never get here, but better safe than sorry...
+      this.log.error("Failed to reschedule after sync completed", err);
+    });
+  },
+
+  _clearTimer() {
+    if (this._timer) {
+      clearTimeout(this._timer);
+      this._timer = null;
+    }
+  },
+
+  // A function to "sync now", but not allowing it to start if one is
+  // already running, and rescheduling the timer.
+  // To call this, just send a "readinglist:user-sync" notification.
+  _syncNow() {
+    if (this._timerRunning) {
+      this.log.info("syncNow() but a sync is already in progress - ignoring");
+      return;
+    }
+    this._clearTimer();
+    this._doSync();
+  },
+
+  // A couple of hook-points for testing.
+  // xpcshell tests hook this so (a) it can check the expected delay is set
+  // and (b) to ignore the delay and set a timeout of 0 so the test is fast.
+  _setTimeout(delay) {
+    return setTimeout(() => this._doSync(), delay);
+  },
+  // xpcshell tests hook this to make sure that the correct state etc exist
+  // after a sync has been completed and a new timer created (or not).
+  _onAutoReschedule() {},
+};
+
+let internalScheduler = new InternalScheduler();
+internalScheduler.init();
+
+// The public interface into this module is tiny, so a simple object that
+// delegates to the implementation.
+let ReadingListScheduler = {
+  get STATE_OK() internalScheduler.STATE_OK,
+  get STATE_ERROR_AUTHENTICATION() internalScheduler.STATE_ERROR_AUTHENTICATION,
+  get STATE_ERROR_OTHER() internalScheduler.STATE_ERROR_OTHER,
+
+  get state() internalScheduler.state,
+};
+
+// These functions are exposed purely for tests, which manage to grab them
+// via a BackstagePass.
+function createTestableScheduler() {
+  // kill the "real" scheduler as we don't want it listening to notifications etc.
+  if (internalScheduler) {
+    internalScheduler.finalize();
+    internalScheduler = null;
+  }
+  // No .init() call - that's up to the tests after hooking.
+  return new InternalScheduler();
+}
+
+// mochitests want the internal state of the real scheduler for various things.
+function getInternalScheduler() {
+  return internalScheduler;
+}
--- a/browser/components/readinglist/moz.build
+++ b/browser/components/readinglist/moz.build
@@ -8,8 +8,14 @@ EXTRA_JS_MODULES.readinglist += [
     'ReadingList.jsm',
 ]
 
 TESTING_JS_MODULES += [
     'test/ReadingListTestUtils.jsm',
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
+
+XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
+
+EXTRA_JS_MODULES.readinglist += [
+    'Scheduler.jsm',
+]
new file mode 100644
--- /dev/null
+++ b/browser/components/readinglist/test/xpcshell/head.js
@@ -0,0 +1,7 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
new file mode 100644
--- /dev/null
+++ b/browser/components/readinglist/test/xpcshell/test_scheduler.js
@@ -0,0 +1,146 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout',
+  'resource://gre/modules/Timer.jsm');
+
+// Setup logging prefs before importing the scheduler module.
+Services.prefs.setCharPref("readinglist.log.appender.dump", "Trace");
+
+let {createTestableScheduler} = Cu.import("resource:///modules/readinglist/Scheduler.jsm", {});
+Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/Timer.jsm");
+
+// Log rotation needs a profile dir.
+do_get_profile();
+
+let prefs = new Preferences("readinglist.scheduler.");
+
+function promiseObserver(topic) {
+  return new Promise(resolve => {
+    let obs = (subject, topic, data) => {
+      Services.obs.removeObserver(obs, topic);
+      resolve(data);
+    }
+    Services.obs.addObserver(obs, topic, false);
+  });
+}
+
+function createScheduler(options) {
+  // avoid typos in the test and other footguns in the options.
+  let allowedOptions = ["expectedDelay", "expectNewTimer", "syncFunction"];
+  for (let key of Object.keys(options)) {
+    if (!allowedOptions.includes(key)) {
+      throw new Error("Invalid option " + key);
+    }
+  }
+  let scheduler = createTestableScheduler();
+  // make our hooks
+  let syncFunction = options.syncFunction || Promise.resolve;
+  scheduler._engine.sync = syncFunction;
+  // we expect _setTimeout to be called *twice* - first is the initial sync,
+  // and there's no need to test the delay used for that. options.expectedDelay
+  // is to check the *subsequent* timer.
+  let numCalls = 0;
+  scheduler._setTimeout = function(delay) {
+    ++numCalls;
+    print("Test scheduler _setTimeout call number " + numCalls + " with delay=" + delay);
+    switch (numCalls) {
+      case 1:
+        // this is the first and boring schedule as it initializes - do nothing
+        // other than return a timer that fires immediately.
+        return setTimeout(() => scheduler._doSync(), 0);
+        break;
+      case 2:
+        // This is the one we are interested in, so check things.
+        if (options.expectedDelay) {
+          // a little slop is OK as it takes a few ms to actually set the timer
+          ok(Math.abs(options.expectedDelay * 1000 - delay) < 500, [options.expectedDelay * 1000, delay]);
+        }
+        // and return a timeout that "never" fires
+        return setTimeout(() => scheduler._doSync(), 10000000);
+        break;
+      default:
+        // This is unexpected!
+        ok(false, numCalls);
+    }
+  };
+  // And a callback made once we've determined the next delay. This is always
+  // called even if _setTimeout isn't (due to no timer being created)
+  scheduler._onAutoReschedule = () => {
+    // Most tests expect a new timer, so this is "opt out"
+    let expectNewTimer = options.expectNewTimer === undefined ? true : options.expectNewTimer;
+    ok(expectNewTimer ? scheduler._timer : !scheduler._timer);
+  }
+  // calling .init fires things off...
+  scheduler.init();
+  return scheduler;
+}
+
+add_task(function* testSuccess() {
+  // promises which resolve once we've got all the expected notifications.
+  let allNotifications = [
+    promiseObserver("readinglist:sync:start"),
+    promiseObserver("readinglist:sync:finish"),
+  ];
+  // New delay should be "as regularly scheduled".
+  prefs.set("schedule", 100);
+  let scheduler = createScheduler({expectedDelay: 100});
+  yield Promise.all(allNotifications);
+  scheduler.finalize();
+});
+
+add_task(function* testOffline() {
+  let scheduler = createScheduler({expectNewTimer: false});
+  Services.io.offline = true;
+  ok(!scheduler._canSync(), "_canSync is false when offline.")
+  ok(!scheduler._timer, "there is no current timer while offline.")
+  Services.io.offline = false;
+  ok(scheduler._canSync(), "_canSync is true when online.")
+  ok(scheduler._timer, "there is a new timer when back online.")
+  scheduler.finalize();
+});
+
+add_task(function* testRetryableError() {
+  let allNotifications = [
+    promiseObserver("readinglist:sync:start"),
+    promiseObserver("readinglist:sync:error"),
+  ];
+  prefs.set("retry", 10);
+  let scheduler = createScheduler({
+    expectedDelay: 10,
+    syncFunction: () => Promise.reject("transient"),
+  });
+  yield Promise.all(allNotifications);
+  scheduler.finalize();
+});
+
+add_task(function* testAuthError() {
+  prefs.set("retry", 10);
+  // We expect an auth error to result in no new timer (as it's waiting for
+  // some indication it can proceed), but with the next delay being a normal
+  // "retry" interval (so when we can proceed it is probably already stale, so
+  // is effectively "immediate")
+  let scheduler = createScheduler({
+    expectedDelay: 10,
+    syncFunction:  () => {
+      return Promise.reject(ReadingListScheduler._engine.ERROR_AUTHENTICATION);
+    },
+    expectNewTimer: false
+  });
+  // XXX - TODO - send an observer that "unblocks" us and ensure we actually
+  // do unblock.
+  scheduler.finalize();
+});
+
+add_task(function* testBackoff() {
+  let scheduler = createScheduler({expectedDelay: 1000});
+  Services.obs.notifyObservers(null, "readinglist:backoff-requested", 1000);
+  // XXX - this needs a little love as nothing checks createScheduler actually
+  // made the checks we think it does.
+  scheduler.finalize();
+});
+
+function run_test() {
+  run_next_test();
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/readinglist/test/xpcshell/xpcshell.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+head = head.js
+firefox-appdir = browser
+
+[test_scheduler.js]
--- a/browser/components/search/test/browser_searchbar_openpopup.js
+++ b/browser/components/search/test/browser_searchbar_openpopup.js
@@ -447,16 +447,38 @@ add_task(function* dont_rollup_oncaretmo
   is(textbox.selectionEnd, 8, "Should have moved the caret (selectionEnd after left)");
   is(searchPopup.state, "open", "Popup should still be open");
 
   EventUtils.synthesizeKey("VK_RIGHT", {});
   is(textbox.selectionStart, 9, "Should have moved the caret (selectionStart after right)");
   is(textbox.selectionEnd, 9, "Should have moved the caret (selectionEnd after right)");
   is(searchPopup.state, "open", "Popup should still be open");
 
+  // Ensure caret movement works while a suggestion is selected.
+  is(textbox.popup.selectedIndex, -1, "No selected item in list");
+  EventUtils.synthesizeKey("VK_DOWN", {});
+  is(textbox.popup.selectedIndex, 0, "Selected item in list");
+  is(textbox.selectionStart, 9, "Should have moved the caret to the end (selectionStart after selection)");
+  is(textbox.selectionEnd, 9, "Should have moved the caret to the end (selectionEnd after selection)");
+
+  EventUtils.synthesizeKey("VK_LEFT", {});
+  is(textbox.selectionStart, 8, "Should have moved the caret again (selectionStart after left)");
+  is(textbox.selectionEnd, 8, "Should have moved the caret again (selectionEnd after left)");
+  is(searchPopup.state, "open", "Popup should still be open");
+
+  EventUtils.synthesizeKey("VK_LEFT", {});
+  is(textbox.selectionStart, 7, "Should have moved the caret (selectionStart after left)");
+  is(textbox.selectionEnd, 7, "Should have moved the caret (selectionEnd after left)");
+  is(searchPopup.state, "open", "Popup should still be open");
+
+  EventUtils.synthesizeKey("VK_RIGHT", {});
+  is(textbox.selectionStart, 8, "Should have moved the caret (selectionStart after right)");
+  is(textbox.selectionEnd, 8, "Should have moved the caret (selectionEnd after right)");
+  is(searchPopup.state, "open", "Popup should still be open");
+
   if (navigator.platform.indexOf("Mac") == -1) {
     EventUtils.synthesizeKey("VK_HOME", {});
     is(textbox.selectionStart, 0, "Should have moved the caret (selectionStart after home)");
     is(textbox.selectionEnd, 0, "Should have moved the caret (selectionEnd after home)");
     is(searchPopup.state, "open", "Popup should still be open");
   }
 
   // Close the popup again
--- a/browser/devtools/netmonitor/test/browser_net_content-type.js
+++ b/browser/devtools/netmonitor/test/browser_net_content-type.js
@@ -43,17 +43,17 @@ function test() {
           time: true
         });
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(3),
         "GET", CONTENT_TYPE_SJS + "?fmt=json", {
           status: 200,
           statusText: "OK",
           type: "json",
           fullMimeType: "application/json; charset=utf-8",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
+          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
           time: true
         });
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
         "GET", CONTENT_TYPE_SJS + "?fmt=bogus", {
           status: 404,
           statusText: "Not Found",
           type: "html",
           fullMimeType: "text/html; charset=utf-8",
@@ -62,17 +62,17 @@ function test() {
         });
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(5),
         "GET", TEST_IMAGE, {
           fuzzyUrl: true,
           status: 200,
           statusText: "OK",
           type: "png",
           fullMimeType: "image/png",
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.75),
+          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.76),
           time: true
         });
 
       EventUtils.sendMouseEvent({ type: "mousedown" },
         document.getElementById("details-pane-toggle"));
       EventUtils.sendMouseEvent({ type: "mousedown" },
         document.querySelectorAll("#details-pane tab")[3]);
 
--- a/browser/devtools/netmonitor/test/browser_net_sort-02.js
+++ b/browser/devtools/netmonitor/test/browser_net_sort-02.js
@@ -223,51 +223,51 @@ function test() {
         });
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(b),
         "GET2", SORTING_SJS + "?index=2", {
           fuzzyUrl: true,
           status: 200,
           statusText: "Meh",
           type: "2",
           fullMimeType: "text/2",
-          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
+          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
+          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
           time: true
         });
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(c),
         "GET3", SORTING_SJS + "?index=3", {
           fuzzyUrl: true,
           status: 300,
           statusText: "Meh",
           type: "3",
           fullMimeType: "text/3",
-          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
+          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
+          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
           time: true
         });
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(d),
         "GET4", SORTING_SJS + "?index=4", {
           fuzzyUrl: true,
           status: 400,
           statusText: "Meh",
           type: "4",
           fullMimeType: "text/4",
-          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
+          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
+          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
           time: true
         });
       verifyRequestItemTarget(RequestsMenu.getItemAtIndex(e),
         "GET5", SORTING_SJS + "?index=5", {
           fuzzyUrl: true,
           status: 500,
           statusText: "Meh",
           type: "5",
           fullMimeType: "text/5",
-          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
-          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
+          transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
+          size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
           time: true
         });
 
       return promise.resolve(null);
     }
 
     aDebuggee.performRequests();
   });
--- a/browser/devtools/netmonitor/test/browser_net_sort-03.js
+++ b/browser/devtools/netmonitor/test/browser_net_sort-03.js
@@ -138,57 +138,57 @@ function test() {
       for (let i = 0, len = aOrder.length / 5; i < len; i++) {
         verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len]),
           "GET2", SORTING_SJS + "?index=2", {
             fuzzyUrl: true,
             status: 200,
             statusText: "Meh",
             type: "2",
             fullMimeType: "text/2",
-            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
-            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
+            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
+            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
             time: true
           });
       }
       for (let i = 0, len = aOrder.length / 5; i < len; i++) {
         verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 2]),
           "GET3", SORTING_SJS + "?index=3", {
             fuzzyUrl: true,
             status: 300,
             statusText: "Meh",
             type: "3",
             fullMimeType: "text/3",
-            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
-            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
+            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
+            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
             time: true
           });
       }
       for (let i = 0, len = aOrder.length / 5; i < len; i++) {
         verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 3]),
           "GET4", SORTING_SJS + "?index=4", {
             fuzzyUrl: true,
             status: 400,
             statusText: "Meh",
             type: "4",
             fullMimeType: "text/4",
-            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
-            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
+            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
+            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
             time: true
           });
       }
       for (let i = 0, len = aOrder.length / 5; i < len; i++) {
         verifyRequestItemTarget(RequestsMenu.getItemAtIndex(aOrder[i + len * 4]),
           "GET5", SORTING_SJS + "?index=5", {
             fuzzyUrl: true,
             status: 500,
             statusText: "Meh",
             type: "5",
             fullMimeType: "text/5",
-            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
-            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
+            transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
+            size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
             time: true
           });
       }
 
       return promise.resolve(null);
     }
 
     aDebuggee.performRequests();
--- a/browser/devtools/projecteditor/lib/stores/resource.js
+++ b/browser/devtools/projecteditor/lib/stores/resource.js
@@ -43,21 +43,16 @@ var Resource = Class({
   setURI: function(uri) {
     if (typeof(uri) === "string") {
       uri = URL.URL(uri);
     }
     this.uri = uri;
   },
 
   /**
-   * Return the trailing name component of this.uri.
-   */
-  get basename() { return this.uri.path.replace(/\/+$/, '').replace(/\\/g,'/').replace( /.*\//, '' ); },
-
-  /**
    * Is there more than 1 child Resource?
    */
   get hasChildren() { return this.children && this.children.size > 0; },
 
   /**
    * Is this Resource the root (top level for the store)?
    */
   get isRoot() {
@@ -234,16 +229,23 @@ var FileResource = Class({
         this._refreshDeferred.resolve(this);
         this._refreshDeferred = null;
       }
     });
     return this._refreshDeferred.promise;
   },
 
   /**
+   * Return the trailing name component of this Resource
+   */
+  get basename() {
+    return this.path.replace(/\/+$/, '').replace(/\\/g,'/').replace( /.*\//, '' );
+  },
+
+  /**
    * A string to be used when displaying this Resource in views
    */
   get displayName() {
     return this.basename + (this.isDir ? "/" : "")
   },
 
   /**
    * Is this FileResource a directory?  Rather than checking children
--- a/browser/devtools/projecteditor/test/browser_projecteditor_rename_file.js
+++ b/browser/devtools/projecteditor/test/browser_projecteditor_rename_file.js
@@ -8,52 +8,75 @@
 
 add_task(function*() {
   let projecteditor = yield addProjectEditorTabForTempDirectory();
   ok(true, "ProjectEditor has loaded");
 
   let root = [...projecteditor.project.allStores()][0].root;
   is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
   for (let child of root.children) {
-    yield renameWithContextMenu(projecteditor, projecteditor.projectTree.getViewContainer(child));
+    yield renameWithContextMenu(projecteditor,
+                                projecteditor.projectTree.getViewContainer(child),
+                                ".renamed");
+  }
+});
+
+add_task(function*() {
+  let projecteditor = yield addProjectEditorTabForTempDirectory();
+  ok(true, "ProjectEditor has loaded");
+
+  let root = [...projecteditor.project.allStores()][0].root;
+  is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
+
+  let childrenList = new Array();
+  for (let child of root.children) {
+    yield renameWithContextMenu(projecteditor,
+                                projecteditor.projectTree.getViewContainer(child),
+                                ".ren\u0061\u0308med");
+    childrenList.push(child.basename + ".ren\u0061\u0308med");
+  }
+  for (let child of root.children) {
+    is (childrenList.indexOf(child.basename) == -1, false,
+        "Failed to update tree with non-ascii character");
   }
 });
 
 function openContextMenuOn(node) {
   EventUtils.synthesizeMouseAtCenter(
     node,
     {button: 2, type: "contextmenu"},
     node.ownerDocument.defaultView
   );
 }
 
-function renameWithContextMenu(projecteditor, container) {
+function renameWithContextMenu(projecteditor, container, newName) {
   let defer = promise.defer();
   let popup = projecteditor.contextMenuPopup;
   let resource = container.resource;
   info ("Going to attempt renaming for: " + resource.path);
 
   onPopupShow(popup).then(function () {
     let renameCommand = popup.querySelector("[command=cmd-rename]");
     ok (renameCommand, "Rename command exists in popup");
     is (renameCommand.getAttribute("hidden"), "", "Rename command is visible");
     is (renameCommand.getAttribute("disabled"), "", "Rename command is enabled");
 
     projecteditor.project.on("refresh-complete", function refreshComplete() {
       projecteditor.project.off("refresh-complete", refreshComplete);
-      OS.File.stat(resource.path + ".renamed").then(() => {
+      OS.File.stat(resource.path + newName).then(() => {
         ok (true, "File is renamed");
         defer.resolve();
       }, (ex) => {
         ok (false, "Failed to rename file");
         defer.resolve();
       });
     });
 
     renameCommand.click();
     popup.hidePopup();
-    EventUtils.sendString(resource.basename + ".renamed", projecteditor.window);
+    let input = container.elt.previousElementSibling;
+    input.value = resource.basename + newName;
     EventUtils.synthesizeKey("VK_RETURN", {}, projecteditor.window);
   });
 
   openContextMenuOn(container.label);
   return defer.promise;
 }
--- a/browser/devtools/shared/test/browser_graphs-09a.js
+++ b/browser/devtools/shared/test/browser_graphs-09a.js
@@ -49,17 +49,17 @@ function* testGraph(graph) {
     "The maximum tooltip displays the correct info.");
   is(graph._avgTooltip.querySelector("[text=info]").textContent, "avg",
     "The average tooltip displays the correct info.");
   is(graph._minTooltip.querySelector("[text=info]").textContent, "min",
     "The minimum tooltip displays the correct info.");
 
   is(graph._maxTooltip.querySelector("[text=value]").textContent, "60",
     "The maximum tooltip displays the correct value.");
-  is(graph._avgTooltip.querySelector("[text=value]").textContent, "41.71",
+  is(graph._avgTooltip.querySelector("[text=value]").textContent, "41.72",
     "The average tooltip displays the correct value.");
   is(graph._minTooltip.querySelector("[text=value]").textContent, "10",
     "The minimum tooltip displays the correct value.");
 
   is(graph._maxTooltip.querySelector("[text=metric]").textContent, "fps",
     "The maximum tooltip displays the correct metric.");
   is(graph._avgTooltip.querySelector("[text=metric]").textContent, "fps",
     "The average tooltip displays the correct metric.");
--- a/browser/devtools/shared/test/browser_num-l10n.js
+++ b/browser/devtools/shared/test/browser_num-l10n.js
@@ -3,17 +3,17 @@
 
 // Tests that ViewHelpers.Prefs work properly.
 
 let {ViewHelpers} = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
 
 function test() {
   let l10n = new ViewHelpers.L10N();
 
-  is(l10n.numberWithDecimals(1234.56789, 2), "1,234.56",
+  is(l10n.numberWithDecimals(1234.56789, 2), "1,234.57",
     "The first number was properly localized.");
   is(l10n.numberWithDecimals(0.0001, 2), "0",
     "The second number was properly localized.");
   is(l10n.numberWithDecimals(1.0001, 2), "1",
     "The third number was properly localized.");
   is(l10n.numberWithDecimals(NaN, 2), "0",
     "NaN was properly localized.");
   is(l10n.numberWithDecimals(null, 2), "0",
--- a/browser/devtools/shared/widgets/ViewHelpers.jsm
+++ b/browser/devtools/shared/widgets/ViewHelpers.jsm
@@ -364,31 +364,28 @@ ViewHelpers.L10N.prototype = {
   numberWithDecimals: function(aNumber, aDecimals = 0) {
     // If this is an integer, don't do anything special.
     if (aNumber == (aNumber | 0)) {
       return aNumber;
     }
     if (isNaN(aNumber) || aNumber == null) {
       return "0";
     }
-    // Remove {n} trailing decimals. Can't use toFixed(n) because
-    // toLocaleString converts the number to a string. Also can't use
-    // toLocaleString(, { maximumFractionDigits: n }) because it's not
-    // implemented on OS X (bug 368838). Gross.
     let localized = aNumber.toLocaleString(); // localize
 
     // If no grouping or decimal separators are available, bail out, because
     // padding with zeros at the end of the string won't make sense anymore.
     if (!localized.match(/[^\d]/)) {
       return localized;
     }
 
-    let padded = localized + new Array(aDecimals).join("0"); // pad with zeros
-    let match = padded.match("([^]*?\\d{" + aDecimals + "})\\d*$");
-    return match.pop();
+    return aNumber.toLocaleString(undefined, {
+      maximumFractionDigits: aDecimals,
+      minimumFractionDigits: aDecimals
+    });
   }
 };
 
 /**
  * Shortcuts for lazily accessing and setting various preferences.
  * Usage:
  *   let prefs = new ViewHelpers.Prefs("root.path.to.branch", {
  *     myIntPref: ["Int", "leaf.path.to.my-int-pref"],
--- a/browser/devtools/styleeditor/StyleEditorUI.jsm
+++ b/browser/devtools/styleeditor/StyleEditorUI.jsm
@@ -442,23 +442,25 @@ StyleEditorUI.prototype = {
   /**
    * Called when a StyleSheetEditor's source has been fetched. Create a
    * summary UI for the editor.
    *
    * @param  {StyleSheetEditor} editor
    *         Editor to create UI for.
    */
   _sourceLoaded: function(editor) {
+    let ordinal = editor.styleSheet.styleSheetIndex;
+    ordinal = ordinal == -1 ? Number.MAX_SAFE_INTEGER : ordinal;
     // add new sidebar item and editor to the UI
     this._view.appendTemplatedItem(STYLE_EDITOR_TEMPLATE, {
       data: {
         editor: editor
       },
       disableAnimations: this._alwaysDisableAnimations,
-      ordinal: editor.styleSheet.styleSheetIndex,
+      ordinal: ordinal,
       onCreate: function(summary, details, data) {
         let editor = data.editor;
         editor.summary = summary;
         editor.details = details;
 
         wire(summary, ".stylesheet-enabled", function onToggleDisabled(event) {
           event.stopPropagation();
           event.target.blur();
--- a/browser/devtools/styleeditor/StyleSheetEditor.jsm
+++ b/browser/devtools/styleeditor/StyleSheetEditor.jsm
@@ -10,16 +10,17 @@ this.EXPORTED_SYMBOLS = ["StyleSheetEdit
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
 const Editor  = require("devtools/sourceeditor/editor");
 const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
 const {CssLogic} = require("devtools/styleinspector/css-logic");
+const {console} = require("resource://gre/modules/devtools/Console.jsm");
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/devtools/event-emitter.js");
 Cu.import("resource:///modules/devtools/StyleEditorUtil.jsm");
@@ -246,21 +247,37 @@ StyleSheetEditor.prototype = {
         }
         this._state.text = source;
         this.sourceLoaded = true;
 
         if (callback) {
           callback(source);
         }
         return source;
+      }, e => {
+        if (this._isDestroyed) {
+          console.warn("Could not fetch the source for " +
+                       this.styleSheet.href +
+                       ", the editor was destroyed");
+          Cu.reportError(e);
+        } else {
+          throw e;
+        }
       });
     }, e => {
-      this.emit("error", { key: LOAD_ERROR, append: this.styleSheet.href });
-      throw e;
-    })
+      if (this._isDestroyed) {
+        console.warn("Could not fetch the source for " +
+                     this.styleSheet.href +
+                     ", the editor was destroyed");
+        Cu.reportError(e);
+      } else {
+        this.emit("error", { key: LOAD_ERROR, append: this.styleSheet.href });
+        throw e;
+      }
+    });
   },
 
   /**
    * Add markup to a region. UNUSED_CLASS is added to specified lines
    * @param region An object shaped like
    *   {
    *     start: { line: L1, column: C1 },
    *     end: { line: L2, column: C2 }    // optional
@@ -707,16 +724,17 @@ StyleSheetEditor.prototype = {
         this._sourceEditor.container.removeEventListener("mousemove",
           this._onMouseMove);
       }
       this._sourceEditor.destroy();
     }
     this.cssSheet.off("property-change", this._onPropertyChange);
     this.cssSheet.off("media-rules-changed", this._onMediaRulesChanged);
     this.styleSheet.off("error", this._onError);
+    this._isDestroyed = true;
   }
 }
 
 /**
  * Find a path on disk for a file given it's hosted uri, the uri of the
  * original resource that generated it (e.g. Sass file), and the location of the
  * local file for that source.
  *
--- a/browser/devtools/styleeditor/test/browser_styleeditor_autocomplete.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_autocomplete.js
@@ -4,17 +4,17 @@
 
 ///////////////////
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed. 
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
 
-const TESTCASE_URI = TEST_BASE + "autocomplete.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "autocomplete.html";
 const MAX_SUGGESTIONS = 15;
 
 // Pref which decides if CSS autocompletion is enabled in Style Editor or not.
 const AUTOCOMPLETION_PREF = "devtools.styleeditor.autocompletion-enabled";
 
 const {CSSProperties, CSSValues} = getCSSKeywords();
 
 // Test cases to test that autocompletion works correctly when enabled.
--- a/browser/devtools/styleeditor/test/browser_styleeditor_bug_851132_middle_click.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_bug_851132_middle_click.js
@@ -3,17 +3,17 @@
 
 ///////////////////
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed. 
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
 
-const TESTCASE_URI = TEST_BASE + "four.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "four.html";
 
 let gUI;
 
 function test() {
   waitForExplicitFinish();
 
   addTabAndOpenStyleEditors(4, runTests);
 
--- a/browser/devtools/styleeditor/test/browser_styleeditor_filesave.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_filesave.js
@@ -1,14 +1,14 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const TESTCASE_URI_HTML = TEST_BASE + "simple.html";
-const TESTCASE_URI_CSS = TEST_BASE + "simple.css";
+const TESTCASE_URI_HTML = TEST_BASE_HTTP + "simple.html";
+const TESTCASE_URI_CSS = TEST_BASE_HTTP + "simple.css";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let tempScope = {};
 Components.utils.import("resource://gre/modules/FileUtils.jsm", tempScope);
 Components.utils.import("resource://gre/modules/NetUtil.jsm", tempScope);
 let FileUtils = tempScope.FileUtils;
--- a/browser/devtools/styleeditor/test/browser_styleeditor_init.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_init.js
@@ -4,17 +4,17 @@
 
 ///////////////////
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed.
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: summary is undefined");
 
-const TESTCASE_URI = TEST_BASE + "simple.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
 
 let gUI;
 
 function test()
 {
   waitForExplicitFinish();
 
   addTabAndCheckOnStyleEditorAdded(panel => gUI = panel.UI, testEditorAdded);
--- a/browser/devtools/styleeditor/test/browser_styleeditor_inline_friendly_names.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_inline_friendly_names.js
@@ -6,18 +6,18 @@
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed. 
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
 
 let gUI;
 
-const FIRST_TEST_PAGE = TEST_BASE + "inline-1.html"
-const SECOND_TEST_PAGE = TEST_BASE + "inline-2.html"
+const FIRST_TEST_PAGE = TEST_BASE_HTTP + "inline-1.html"
+const SECOND_TEST_PAGE = TEST_BASE_HTTP + "inline-2.html"
 const SAVE_PATH = "test.css";
 
 function test()
 {
   waitForExplicitFinish();
 
   addTabAndOpenStyleEditors(2, function(panel) {
     gUI = panel.UI;
--- a/browser/devtools/styleeditor/test/browser_styleeditor_new.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_new.js
@@ -4,17 +4,17 @@
 
 ///////////////////
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed. 
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
 
-const TESTCASE_URI = TEST_BASE + "simple.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
 
 let TESTCASE_CSS_SOURCE = "body{background-color:red;";
 
 let gOriginalHref;
 let gUI;
 
 waitForExplicitFinish();
 
--- a/browser/devtools/styleeditor/test/browser_styleeditor_nostyle.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_nostyle.js
@@ -1,13 +1,13 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const TESTCASE_URI = TEST_BASE + "nostyle.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "nostyle.html";
 
 
 function test()
 {
   waitForExplicitFinish();
 
   // launch Style Editor right when the tab is created (before load)
   // this checks that the Style Editor still launches correctly when it is opened
--- a/browser/devtools/styleeditor/test/browser_styleeditor_pretty.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_pretty.js
@@ -4,17 +4,17 @@
 
 ///////////////////
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed. 
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
 
-const TESTCASE_URI = TEST_BASE + "minified.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "minified.html";
 
 let gUI;
 
 function test()
 {
   waitForExplicitFinish();
 
   addTabAndCheckOnStyleEditorAdded(panel => gUI = panel.UI, editor => {
--- a/browser/devtools/styleeditor/test/browser_styleeditor_sourcemap_watching.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_sourcemap_watching.js
@@ -1,21 +1,21 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Components.utils.import("resource://gre/modules/Task.jsm");
 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
 
-const TESTCASE_URI_HTML = TEST_BASE + "sourcemaps-watching.html";
-const TESTCASE_URI_CSS = TEST_BASE + "sourcemap-css/sourcemaps.css";
-const TESTCASE_URI_REG_CSS = TEST_BASE + "simple.css";
-const TESTCASE_URI_SCSS = TEST_BASE + "sourcemap-sass/sourcemaps.scss";
-const TESTCASE_URI_MAP = TEST_BASE + "sourcemap-css/sourcemaps.css.map";
+const TESTCASE_URI_HTML = TEST_BASE_HTTP + "sourcemaps-watching.html";
+const TESTCASE_URI_CSS = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css";
+const TESTCASE_URI_REG_CSS = TEST_BASE_HTTP + "simple.css";
+const TESTCASE_URI_SCSS = TEST_BASE_HTTP + "sourcemap-sass/sourcemaps.scss";
+const TESTCASE_URI_MAP = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css.map";
 const TESTCASE_SCSS_NAME = "sourcemaps.scss";
 
 const TRANSITIONS_PREF = "devtools.styleeditor.transitions";
 
 const CSS_TEXT = "* { color: blue }";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
--- a/browser/devtools/styleeditor/test/browser_styleeditor_sv_keynav.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_sv_keynav.js
@@ -4,17 +4,17 @@
 
 ///////////////////
 //
 // Whitelisting this test.
 // As part of bug 1077403, the leaking uncaught rejection should be fixed. 
 //
 thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
 
-const TESTCASE_URI = TEST_BASE + "four.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "four.html";
 
 let gUI;
 
 function test()
 {
   waitForExplicitFinish();
 
   addTabAndOpenStyleEditors(4, runTests);
--- a/browser/devtools/styleeditor/test/browser_styleeditor_sv_resize.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_sv_resize.js
@@ -1,13 +1,13 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const TESTCASE_URI = TEST_BASE + "simple.html";
+const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
 
 let gOriginalWidth; // these are set by runTests()
 let gOriginalHeight;
 
 function test()
 {
   waitForExplicitFinish();
 
--- a/browser/devtools/webconsole/test/browser.ini
+++ b/browser/devtools/webconsole/test/browser.ini
@@ -349,16 +349,17 @@ skip-if = e10s # Bug 1042253 - webconsol
 [browser_webconsole_log_file_filter.js]
 [browser_webconsole_expandable_timestamps.js]
 [browser_webconsole_autocomplete_in_debugger_stackframe.js]
 skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
 [browser_webconsole_autocomplete_popup_close_on_tab_switch.js]
 skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
 [browser_webconsole_autocomplete-properties-with-non-alphanumeric-names.js]
 [browser_console_hide_jsterm_when_devtools_chrome_enabled_false.js]
+[browser_console_history_persist.js]
 [browser_webconsole_output_01.js]
 skip-if = e10s # Bug 1042253 - webconsole e10s tests
 [browser_webconsole_output_02.js]
 [browser_webconsole_output_03.js]
 [browser_webconsole_output_04.js]
 [browser_webconsole_output_05.js]
 [browser_webconsole_output_06.js]
 [browser_webconsole_output_dom_elements_01.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_console_history_persist.js
@@ -0,0 +1,96 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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/. */
+
+// Test that console command input is persisted across toolbox loads.
+// See Bug 943306.
+
+"use strict";
+
+const TEST_URI = "data:text/html;charset=utf-8,Web Console test for persisting history - bug 943306";
+const INPUT_HISTORY_COUNT = 10;
+
+let test = asyncTest(function* () {
+  info ("Setting custom input history pref to " + INPUT_HISTORY_COUNT);
+  Services.prefs.setIntPref("devtools.webconsole.inputHistoryCount", INPUT_HISTORY_COUNT);
+
+  // First tab: run a bunch of commands and then make sure that you can
+  // navigate through their history.
+  yield loadTab(TEST_URI);
+  let hud1 = yield openConsole();
+  is (JSON.stringify(hud1.jsterm.history), "[]", "No history on first tab initially");
+  yield populateInputHistory(hud1);
+  is (JSON.stringify(hud1.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
+    "First tab has populated history");
+
+  // Second tab: Just make sure that you can navigate through the history
+  // generated by the first tab.
+  yield loadTab(TEST_URI);
+  let hud2 = yield openConsole();
+  is (JSON.stringify(hud2.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
+    "Second tab has populated history");
+  yield testNaviatingHistoryInUI(hud2);
+  is (JSON.stringify(hud2.jsterm.history), '["0","1","2","3","4","5","6","7","8","9",""]',
+    "An empty entry has been added in the second tab due to history perusal");
+
+  // Third tab: Should have the same history as first tab, but if we run a
+  // command, then the history of the first and second shouldn't be affected
+  yield loadTab(TEST_URI);
+  let hud3 = yield openConsole();
+  is (JSON.stringify(hud3.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
+    "Third tab has populated history");
+
+  // Set input value separately from execute so UP arrow accurately navigates history.
+  hud3.jsterm.setInputValue('"hello from third tab"');
+  hud3.jsterm.execute();
+
+  is (JSON.stringify(hud1.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
+    "First tab history hasn't changed due to command in third tab");
+  is (JSON.stringify(hud2.jsterm.history), '["0","1","2","3","4","5","6","7","8","9",""]',
+    "Second tab history hasn't changed due to command in third tab");
+  is (JSON.stringify(hud3.jsterm.history), '["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
+    "Third tab has updated history (and purged the first result) after running a command");
+
+  // Fourth tab: Should have the latest command from the third tab, followed
+  // by the rest of the history from the first tab.
+  yield loadTab(TEST_URI);
+  let hud4 = yield openConsole();
+  is (JSON.stringify(hud4.jsterm.history), '["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
+    "Fourth tab has most recent history");
+
+  info ("Clearing custom input history pref");
+  Services.prefs.clearUserPref("devtools.webconsole.inputHistoryCount");
+});
+
+/**
+ * Populate the history by running the following commands:
+ *  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ */
+function* populateInputHistory(hud) {
+  let jsterm = hud.jsterm;
+  let {inputNode} = jsterm;
+
+  for (let i = 0; i < INPUT_HISTORY_COUNT; i++) {
+    // Set input value separately from execute so UP arrow accurately navigates history.
+    jsterm.setInputValue(i);
+    jsterm.execute();
+  }
+}
+
+/**
+ * Check pressing up results in history traversal like:
+ *  [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
+ */
+function* testNaviatingHistoryInUI(hud) {
+  let jsterm = hud.jsterm;
+  let {inputNode} = jsterm;
+  inputNode.focus();
+
+  // Count backwards from original input and make sure that pressing up
+  // restores this.
+  for (let i = INPUT_HISTORY_COUNT - 1; i >= 0; i--) {
+    EventUtils.synthesizeKey("VK_UP", {});
+    is(inputNode.value, i, "Pressing up restores last input");
+  }
+}
--- a/browser/devtools/webconsole/test/head.js
+++ b/browser/devtools/webconsole/test/head.js
@@ -8,16 +8,17 @@
 let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
 let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
 let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
 let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let {require, TargetFactory} = devtools;
 let {Utils: WebConsoleUtils} = require("devtools/toolkit/webconsole/utils");
 let {Messages} = require("devtools/webconsole/console-output");
+const asyncStorage = require("devtools/toolkit/shared/async-storage");
 
 // promise._reportErrors = true; // please never leave me.
 //Services.prefs.setBoolPref("devtools.debugger.log", true);
 
 let gPendingOutputTest = 0;
 
 // The various categories of messages.
 const CATEGORY_NETWORK = 0;
@@ -317,16 +318,19 @@ let finishTest = Task.async(function* ()
   yield gDevTools.closeToolbox(target);
 
   finish();
 });
 
 registerCleanupFunction(function*() {
   gDevTools.testing = false;
 
+  // Remove stored console commands in between tests
+  yield asyncStorage.removeItem("webConsoleHistory");
+
   dumpConsoles();
 
   if (HUDService.getBrowserConsole()) {
     HUDService.toggleBrowserConsole();
   }
 
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   yield gDevTools.closeToolbox(target);
--- a/browser/devtools/webconsole/webconsole.js
+++ b/browser/devtools/webconsole/webconsole.js
@@ -21,16 +21,18 @@ loader.lazyGetter(this, "AutocompletePop
 loader.lazyGetter(this, "ToolSidebar",
                   () => require("devtools/framework/sidebar").ToolSidebar);
 loader.lazyGetter(this, "NetworkPanel",
                   () => require("devtools/webconsole/network-panel").NetworkPanel);
 loader.lazyGetter(this, "ConsoleOutput",
                   () => require("devtools/webconsole/console-output").ConsoleOutput);
 loader.lazyGetter(this, "Messages",
                   () => require("devtools/webconsole/console-output").Messages);
+loader.lazyGetter(this, "asyncStorage",
+                  () => require("devtools/toolkit/shared/async-storage"));
 loader.lazyImporter(this, "EnvironmentClient", "resource://gre/modules/devtools/dbg-client.jsm");
 loader.lazyImporter(this, "ObjectClient", "resource://gre/modules/devtools/dbg-client.jsm");
 loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
 loader.lazyImporter(this, "VariablesViewController", "resource:///modules/devtools/VariablesViewController.jsm");
 loader.lazyImporter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
 loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
 
 const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
@@ -171,16 +173,17 @@ const THROTTLE_UPDATES = 1000; // millis
 const FILTER_PREFS_PREFIX = "devtools.webconsole.filter.";
 
 // The minimum font size.
 const MIN_FONT_SIZE = 10;
 
 const PREF_CONNECTION_TIMEOUT = "devtools.debugger.remote-timeout";
 const PREF_PERSISTLOG = "devtools.webconsole.persistlog";
 const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
+const PREF_INPUT_HISTORY_COUNT = "devtools.webconsole.inputHistoryCount";
 
 /**
  * A WebConsoleFrame instance is an interactive console initialized *per target*
  * that displays console log data as well as provides an interactive terminal to
  * manipulate the target's document content.
  *
  * The WebConsoleFrame is responsible for the actual Web Console UI
  * implementation.
@@ -438,22 +441,39 @@ WebConsoleFrame.prototype = {
    */
   get persistLog() {
     return Services.prefs.getBoolPref(PREF_PERSISTLOG);
   },
 
   /**
    * Initialize the WebConsoleFrame instance.
    * @return object
-   *         A promise object for the initialization.
+   *         A promise object that resolves once the frame is ready to use.
    */
-  init: function WCF_init()
+  init: function()
   {
     this._initUI();
-    return this._initConnection();
+    let connectionInited = this._initConnection();
+
+    // Don't reject if the history fails to load for some reason.
+    // This would be fine, the panel will just start with empty history.
+    let allReady = this.jsterm.historyLoaded.catch(() => {}).then(() => {
+      return connectionInited;
+    });
+
+    // This notification is only used in tests. Don't chain it onto
+    // the returned promise because the console panel needs to be attached
+    // to the toolbox before the web-console-created event is receieved.
+    let notifyObservers = () => {
+      let id = WebConsoleUtils.supportsString(this.hudId);
+      Services.obs.notifyObservers(id, "web-console-created", null);
+    };
+    allReady.then(notifyObservers, notifyObservers);
+
+    return allReady;
   },
 
   /**
    * Connect to the server using the remote debugging protocol.
    *
    * @private
    * @return object
    *         A promise object that is resolved/reject based on the connection
@@ -470,19 +490,16 @@ WebConsoleFrame.prototype = {
 
     this.proxy.connect().then(() => { // on success
       this._initDefer.resolve(this);
     }, (aReason) => { // on failure
       let node = this.createMessageNode(CATEGORY_JS, SEVERITY_ERROR,
                                         aReason.error + ": " + aReason.message);
       this.outputMessage(CATEGORY_JS, node, [aReason]);
       this._initDefer.reject(aReason);
-    }).then(() => {
-      let id = WebConsoleUtils.supportsString(this.hudId);
-      Services.obs.notifyObservers(id, "web-console-created", null);
     });
 
     return this._initDefer.promise;
   },
 
   /**
    * Find the Web Console UI elements and setup event listeners as needed.
    * @private
@@ -3049,42 +3066,68 @@ function getterOrSetterEvalMacro(aItem, 
  * @constructor
  * @param object aWebConsoleFrame
  *        The WebConsoleFrame object that owns this JSTerm instance.
  */
 function JSTerm(aWebConsoleFrame)
 {
   this.hud = aWebConsoleFrame;
   this.hudId = this.hud.hudId;
+  this.inputHistoryCount = Services.prefs.getIntPref(PREF_INPUT_HISTORY_COUNT);
 
   this.lastCompletion = { value: null };
-  this.history = [];
-
-  // Holds the number of entries in history. This value is incremented in
-  // this.execute().
-  this.historyIndex = 0; // incremented on this.execute()
-
-  // Holds the index of the history entry that the user is currently viewing.
-  // This is reset to this.history.length when this.execute() is invoked.
-  this.historyPlaceHolder = 0;
+  this._loadHistory();
+
   this._objectActorsInVariablesViews = new Map();
 
   this._keyPress = this._keyPress.bind(this);
   this._inputEventHandler = this._inputEventHandler.bind(this);
   this._focusEventHandler = this._focusEventHandler.bind(this);
   this._onKeypressInVariablesView = this._onKeypressInVariablesView.bind(this);
   this._blurEventHandler = this._blurEventHandler.bind(this);
 
   EventEmitter.decorate(this);
 }
 
 JSTerm.prototype = {
   SELECTED_FRAME: -1,
 
   /**
+   * Load the console history from previous sessions.
+   * @private
+   */
+  _loadHistory: function() {
+    this.history = [];
+    this.historyIndex = this.historyPlaceHolder = 0;
+
+    this.historyLoaded = asyncStorage.getItem("webConsoleHistory").then(value => {
+      if (Array.isArray(value)) {
+        // Since it was gotten asynchronously, there could be items already in
+        // the history.  It's not likely but stick them onto the end anyway.
+        this.history = value.concat(this.history);
+
+        // Holds the number of entries in history. This value is incremented in
+        // this.execute().
+        this.historyIndex = this.history.length;
+
+        // Holds the index of the history entry that the user is currently viewing.
+        // This is reset to this.history.length when this.execute() is invoked.
+        this.historyPlaceHolder = this.history.length;
+      }
+    }, console.error);
+  },
+
+  /**
+   * Stores the console history for future sessions.
+   */
+  storeHistory: function() {
+    asyncStorage.setItem("webConsoleHistory", this.history);
+  },
+
+  /**
    * Stores the data for the last completion.
    * @type object
    */
   lastCompletion: null,
 
   /**
    * Array that caches the user input suggestions received from the server.
    * @private
@@ -3383,16 +3426,22 @@ JSTerm.prototype = {
 
     this.requestEvaluation(aExecuteString, options).then(onResult, onResult);
 
     // Append a new value in the history of executed code, or overwrite the most
     // recent entry. The most recent entry may contain the last edited input
     // value that was not evaluated yet.
     this.history[this.historyIndex++] = aExecuteString;
     this.historyPlaceHolder = this.history.length;
+
+    if (this.history.length > this.inputHistoryCount) {
+      this.history.splice(0, this.history.length - this.inputHistoryCount);
+      this.historyIndex = this.historyPlaceHolder = this.history.length;
+    }
+    this.storeHistory();
     WebConsoleUtils.usageCount++;
     this.setInputValue("");
     this.clearCompletion();
     return deferred.promise;
   },
 
   /**
    * Request a JavaScript string evaluation from the server.
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -471,16 +471,18 @@
 @RESPATH@/components/satchel.manifest
 @RESPATH@/components/nsFormAutoComplete.js
 @RESPATH@/components/nsFormHistory.js
 @RESPATH@/components/FormHistoryStartup.js
 @RESPATH@/components/nsInputListAutoComplete.js
 @RESPATH@/components/formautofill.manifest
 @RESPATH@/components/FormAutofillContentService.js
 @RESPATH@/components/FormAutofillStartup.js
+@RESPATH@/components/CSSUnprefixingService.js
+@RESPATH@/components/CSSUnprefixingService.manifest
 @RESPATH@/components/contentAreaDropListener.manifest
 @RESPATH@/components/contentAreaDropListener.js
 @RESPATH@/browser/components/BrowserProfileMigrators.manifest
 @RESPATH@/browser/components/ProfileMigrator.js
 @RESPATH@/browser/components/ChromeProfileMigrator.js
 @RESPATH@/browser/components/FirefoxProfileMigrator.js
 #ifdef XP_WIN
 @RESPATH@/browser/components/IEProfileMigrator.js
--- a/browser/themes/shared/devtools/netmonitor.inc.css
+++ b/browser/themes/shared/devtools/netmonitor.inc.css
@@ -490,19 +490,24 @@ label.requests-menu-status-code {
 
 .tabpanel-summary-label {
   -moz-padding-start: 4px;
   -moz-padding-end: 3px;
   font-weight: 600;
 }
 
 .tabpanel-summary-value {
+  color: inherit;
   -moz-padding-start: 3px;
 }
 
+.theme-dark .tabpanel-summary-value {
+  color: var(--theme-selection-color);
+}
+
 /* Headers tabpanel */
 
 #headers-summary-status,
 #headers-summary-version {
   padding-bottom: 2px;
 }
 
 #headers-summary-size {
--- a/build/virtualenv_packages.txt
+++ b/build/virtualenv_packages.txt
@@ -21,8 +21,9 @@ mozilla.pth:layout/tools/reftest
 moztreedocs.pth:tools/docs
 copy:build/buildconfig.py
 packages.txt:testing/mozbase/packages.txt
 objdir:build
 gyp.pth:media/webrtc/trunk/tools/gyp/pylib
 pyasn1.pth:python/pyasn1
 bitstring.pth:python/bitstring
 redo.pth:python/redo
+requests.pth:python/requests
--- a/configure.in
+++ b/configure.in
@@ -8887,16 +8887,17 @@ AC_SUBST(LIBJPEG_TURBO_ASFLAGS)
 AC_SUBST(LIBJPEG_TURBO_X86_ASM)
 AC_SUBST(LIBJPEG_TURBO_X64_ASM)
 AC_SUBST(LIBJPEG_TURBO_ARM_ASM)
 AC_SUBST(LIBJPEG_TURBO_ARM64_ASM)
 AC_SUBST(LIBJPEG_TURBO_MIPS_ASM)
 
 AC_SUBST(MOZ_PACKAGE_JSSHELL)
 AC_SUBST(MOZ_FOLD_LIBS)
+AC_SUBST(SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE)
 
 AC_SUBST(MOZ_ENABLE_SZIP)
 AC_SUBST(MOZ_SZIP_FLAGS)
 
 dnl Host JavaScript runtime, if any, to use during cross compiles.
 AC_SUBST(JS_BINARY)
 
 if test "$MOZ_DEBUG"; then
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -13813,20 +13813,16 @@ nsDocShell::GetAppManifestURL(nsAString&
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetAsyncPanZoomEnabled(bool* aOut)
 {
-  if (TabChild* tabChild = TabChild::GetFrom(this)) {
-    *aOut = tabChild->IsAsyncPanZoomEnabled();
-    return NS_OK;
-  }
   *aOut = Preferences::GetBool("layers.async-pan-zoom.enabled", false);
   return NS_OK;
 }
 
 bool
 nsDocShell::HasUnloadedParent()
 {
   nsRefPtr<nsDocShell> parent = GetParentDocshell();
--- a/docshell/test/navigation/mochitest.ini
+++ b/docshell/test/navigation/mochitest.ini
@@ -17,19 +17,19 @@ support-files =
   frame3.html
   goback.html
   iframe.html
   navigate.html
   open.html
   parent.html
 
 [test_bug13871.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #RANDOM
+skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' || e10s #RANDOM # Bug 1136180 disabled on B2G Desktop and Mulet for intermittent failures
 [test_bug270414.html]
-skip-if = buildapp == 'b2g' || toolkit == "android" || e10s
+skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == "android" || e10s # Bug 1136180 disabled on B2G Desktop and Mulet for intermittent failures
 [test_bug278916.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug279495.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug344861.html]
 skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s
 [test_bug386782.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6767,17 +6767,17 @@ nsContentUtils::GetAdjustedOffsetInTextC
 void
 nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
                                           Element* aRoot,
                                           int32_t& aOutStartOffset,
                                           int32_t& aOutEndOffset)
 {
   MOZ_ASSERT(aSelection && aRoot);
 
-  if (!aSelection->GetRangeCount()) {
+  if (!aSelection->RangeCount()) {
     // Nothing selected
     aOutStartOffset = aOutEndOffset = 0;
     return;
   }
 
   nsCOMPtr<nsINode> anchorNode = aSelection->GetAnchorNode();
   uint32_t anchorOffset = aSelection->AnchorOffset();
   nsCOMPtr<nsINode> focusNode = aSelection->GetFocusNode();
@@ -6828,17 +6828,17 @@ nsContentUtils::GetSelectionBoundingRect
   if (aSel->IsCollapsed()) {
     nsIFrame* frame = nsCaret::GetGeometry(aSel, &res);
     if (frame) {
       nsIFrame* relativeTo =
         nsLayoutUtils::GetContainingBlockForClientRect(frame);
       res = nsLayoutUtils::TransformFrameRectToAncestor(frame, res, relativeTo);
     }
   } else {
-    int32_t rangeCount = aSel->GetRangeCount();
+    int32_t rangeCount = aSel->RangeCount();
     nsLayoutUtils::RectAccumulator accumulator;
     for (int32_t idx = 0; idx < rangeCount; ++idx) {
       nsRange* range = aSel->GetRangeAt(idx);
       nsRange::CollectClientRects(&accumulator, range,
                                   range->GetStartParent(), range->StartOffset(),
                                   range->GetEndParent(), range->EndOffset(),
                                   true, false);
     }
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -6194,17 +6194,17 @@ nsDocument::RegisterElement(JSContext* a
     JS::Handle<JSObject*> htmlProto(
       HTMLElementBinding::GetProtoObjectHandle(aCx, global));
     if (!htmlProto) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
 
     if (!aOptions.mPrototype) {
-      protoObject = JS_NewObjectWithGivenProto(aCx, nullptr, htmlProto, JS::NullPtr());
+      protoObject = JS_NewObjectWithGivenProto(aCx, nullptr, htmlProto);
       if (!protoObject) {
         rv.Throw(NS_ERROR_UNEXPECTED);
         return;
       }
     } else {
       protoObject = aOptions.mPrototype;
 
       // We are already operating on the document's (/global's) compartment. Let's
@@ -6343,25 +6343,22 @@ nsDocument::RegisterElement(JSContext* a
     for (size_t i = 0; i < candidates->Length(); ++i) {
       Element *elem = candidates->ElementAt(i);
 
       elem->RemoveStates(NS_EVENT_STATE_UNRESOLVED);
 
       // Make sure that the element name matches the name in the definition.
       // (e.g. a definition for x-button extending button should match
       // <button is="x-button"> but not <x-button>.
-      // Note: we also check the tag name, because if it's not the above
-      // mentioned case, it can be that only the |is| property has been
-      // changed, which we should ignore by the spec.
-      if (elem->NodeInfo()->NameAtom() != nameAtom &&
-          elem->Tag() == nameAtom) {
+      if (elem->Tag() != nameAtom) {
         //Skip over this element because definition does not apply.
         continue;
       }
 
+      MOZ_ASSERT(elem->IsHTML(nameAtom));
       nsWrapperCache* cache;
       CallQueryInterface(elem, &cache);
       MOZ_ASSERT(cache, "Element doesn't support wrapper cache?");
 
       JS::RootedObject wrapper(aCx);
       if ((wrapper = cache->GetWrapper())) {
         if (!JS_SetPrototype(aCx, wrapper, protoObject)) {
           continue;
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -1349,17 +1349,17 @@ nsHTMLCopyEncoder::SetSelection(nsISelec
   // div that ender-lite text widgets are embedded in.
   
   if (!aSelection) 
     return NS_ERROR_NULL_POINTER;
   
   nsCOMPtr<nsIDOMRange> range;
   nsCOMPtr<nsIDOMNode> commonParent;
   Selection* selection = static_cast<Selection*>(aSelection);
-  uint32_t rangeCount = selection->GetRangeCount();
+  uint32_t rangeCount = selection->RangeCount();
 
   // if selection is uninitialized return
   if (!rangeCount)
     return NS_ERROR_FAILURE;
   
   // we'll just use the common parent of the first range.  Implicit assumption
   // here that multi-range selections are table cell selections, in which case
   // the common parent is somewhere in the table and we don't really care where.
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2141,34 +2141,25 @@ nsFrameLoader::TryRemoteBrowser()
   }
 
   PROFILER_LABEL("nsFrameLoader", "CreateRemoteBrowser",
     js::ProfileEntry::Category::OTHER);
 
   MutableTabContext context;
   nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
   nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
-  ScrollingBehavior scrollingBehavior = DEFAULT_SCROLLING;
-
-  if (Preferences::GetBool("layers.async-pan-zoom.enabled", false) ||
-      mOwnerContent->AttrValueIs(kNameSpaceID_None,
-                                 nsGkAtoms::mozasyncpanzoom,
-                                 nsGkAtoms::_true,
-                                 eCaseMatters)) {
-    scrollingBehavior = ASYNC_PAN_ZOOM;
-  }
 
   bool rv = true;
   if (ownApp) {
-    rv = context.SetTabContextForAppFrame(ownApp, containingApp, scrollingBehavior);
+    rv = context.SetTabContextForAppFrame(ownApp, containingApp);
   } else if (OwnerIsBrowserFrame()) {
     // The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp.
-    rv = context.SetTabContextForBrowserFrame(containingApp, scrollingBehavior);
+    rv = context.SetTabContextForBrowserFrame(containingApp);
   } else {
-    rv = context.SetTabContextForNormalFrame(scrollingBehavior);
+    rv = context.SetTabContextForNormalFrame();
   }
   NS_ENSURE_TRUE(rv, false);
 
   nsCOMPtr<Element> ownerElement = mOwnerContent;
   mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement, openerContentParent);
   if (mRemoteBrowser) {
     mChildID = mRemoteBrowser->Manager()->ChildID();
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -600,17 +600,16 @@ GK_ATOM(modifiers, "modifiers")
 GK_ATOM(monochrome, "monochrome")
 GK_ATOM(mousedown, "mousedown")
 GK_ATOM(mousemove, "mousemove")
 GK_ATOM(mouseout, "mouseout")
 GK_ATOM(mouseover, "mouseover")
 GK_ATOM(mousethrough, "mousethrough")
 GK_ATOM(mouseup, "mouseup")
 GK_ATOM(mozaudiochannel, "mozaudiochannel")
-GK_ATOM(mozasyncpanzoom, "mozasyncpanzoom")
 GK_ATOM(mozfullscreenchange, "mozfullscreenchange")
 GK_ATOM(mozfullscreenerror, "mozfullscreenerror")
 GK_ATOM(mozpasspointerevents, "mozpasspointerevents")
 GK_ATOM(mozpointerlockchange, "mozpointerlockchange")
 GK_ATOM(mozpointerlockerror, "mozpointerlockerror")
 GK_ATOM(mozprivatebrowsing, "mozprivatebrowsing")
 GK_ATOM(moz_opaque, "moz-opaque")
 GK_ATOM(moz_action_hint, "mozactionhint")
@@ -2292,16 +2291,17 @@ GK_ATOM(progressbar, "progressbar")
 GK_ATOM(region, "region")
 GK_ATOM(rowgroup, "rowgroup")
 GK_ATOM(rowheader, "rowheader")
 GK_ATOM(select1, "select1")
 GK_ATOM(setsize, "setsize")
 GK_ATOM(spelling, "spelling")
 GK_ATOM(spinbutton, "spinbutton")
 GK_ATOM(status, "status")
+GK_ATOM(_switch, "switch")
 GK_ATOM(tableCellIndex, "table-cell-index")
 GK_ATOM(tablist, "tablist")
 GK_ATOM(textIndent, "text-indent")
 GK_ATOM(textInputType, "text-input-type")
 GK_ATOM(textLineThroughColor, "text-line-through-color")
 GK_ATOM(textLineThroughStyle, "text-line-through-style")
 GK_ATOM(textPosition, "text-position")
 GK_ATOM(textUnderlineColor, "text-underline-color")
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -102,16 +102,20 @@ const size_t gStackSize = 8192;
 #define NS_SHRINK_GC_BUFFERS_DELAY  4000 // ms
 
 // The amount of time we wait from the first request to GC to actually
 // doing the first GC.
 #define NS_FIRST_GC_DELAY           10000 // ms
 
 #define NS_FULL_GC_DELAY            60000 // ms
 
+// The amount of time to wait from the user being idle to starting a shrinking
+// GC.
+#define NS_SHRINKING_GC_DELAY       15000 // ms
+
 // Maximum amount of time that should elapse between incremental GC slices
 #define NS_INTERSLICE_GC_DELAY      100 // ms
 
 // If we haven't painted in 100ms, we allow for a longer GC budget
 #define NS_INTERSLICE_GC_BUDGET     40 // ms
 
 // The amount of time we wait between a request to CC (after GC ran)
 // and doing the actual CC.
@@ -143,16 +147,17 @@ static const uint32_t kMaxICCDuration = 
 
 // Large value used to specify that a script should run essentially forever
 #define NS_UNLIMITED_SCRIPT_RUNTIME (0x40000000LL << 32)
 
 // if you add statics here, add them to the list in StartupJSEnvironment
 
 static nsITimer *sGCTimer;
 static nsITimer *sShrinkGCBuffersTimer;
+static nsITimer *sShrinkingGCTimer;
 static nsITimer *sCCTimer;
 static nsITimer *sICCTimer;
 static nsITimer *sFullGCTimer;
 static nsITimer *sInterSliceGCTimer;
 
 static TimeStamp sLastCCEndTime;
 
 static bool sCCLockedOut;
@@ -207,16 +212,17 @@ static int32_t sContextCount;
 
 static nsIScriptSecurityManager *sSecurityManager;
 
 // nsJSEnvironmentObserver observes the memory-pressure notifications
 // and forces a garbage collection and cycle collection when it happens, if
 // the appropriate pref is set.
 
 static bool sGCOnMemoryPressure;
+static bool sCompactOnUserInactive;
 
 // In testing, we call RunNextCollectorTimer() to ensure that the collectors are run more
 // aggressively than they would be in regular browsing. sExpensiveCollectorPokes keeps
 // us from triggering expensive full collections too frequently.
 static int32_t sExpensiveCollectorPokes = 0;
 static const int32_t kPokesBetweenExpensiveCollectorTriggers = 5;
 
 static PRTime
@@ -229,16 +235,17 @@ GetCollectionTimeDelta()
   sFirstCollectionTime = now;
   return 0;
 }
 
 static void
 KillTimers()
 {
   nsJSContext::KillGCTimer();
+  nsJSContext::KillShrinkingGCTimer();
   nsJSContext::KillShrinkGCBuffersTimer();
   nsJSContext::KillCCTimer();
   nsJSContext::KillICCTimer();
   nsJSContext::KillFullGCTimer();
   nsJSContext::KillInterSliceGCTimer();
 }
 
 // If we collected a substantial amount of cycles, poke the GC since more objects
@@ -261,32 +268,40 @@ public:
 };
 
 NS_IMPL_ISUPPORTS(nsJSEnvironmentObserver, nsIObserver)
 
 NS_IMETHODIMP
 nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
                                  const char16_t* aData)
 {
-  if (sGCOnMemoryPressure && !nsCRT::strcmp(aTopic, "memory-pressure")) {
-    if(StringBeginsWith(nsDependentString(aData),
-                        NS_LITERAL_STRING("low-memory-ongoing"))) {
-      // Don't GC/CC if we are in an ongoing low-memory state since its very
-      // slow and it likely won't help us anyway.
-      return NS_OK;
-    }
-    nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
-                                   nsJSContext::NonIncrementalGC,
-                                   nsJSContext::ShrinkingGC);
-    nsJSContext::CycleCollectNow();
-    if (NeedsGCAfterCC()) {
+  if (!nsCRT::strcmp(aTopic, "memory-pressure")) {
+    if (sGCOnMemoryPressure) {
+      if(StringBeginsWith(nsDependentString(aData),
+                          NS_LITERAL_STRING("low-memory-ongoing"))) {
+        // Don't GC/CC if we are in an ongoing low-memory state since its very
+        // slow and it likely won't help us anyway.
+        return NS_OK;
+      }
       nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
                                      nsJSContext::NonIncrementalGC,
                                      nsJSContext::ShrinkingGC);
+      nsJSContext::CycleCollectNow();
+      if (NeedsGCAfterCC()) {
+        nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
+                                       nsJSContext::NonIncrementalGC,
+                                       nsJSContext::ShrinkingGC);
+      }
     }
+  } else if (!nsCRT::strcmp(aTopic, "user-interaction-inactive")) {
+    if (sCompactOnUserInactive) {
+      nsJSContext::PokeShrinkingGC();
+    }
+  } else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) {
+    nsJSContext::KillShrinkingGCTimer();
   } else if (!nsCRT::strcmp(aTopic, "quit-application") ||
              !nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     sShuttingDown = true;
     KillTimers();
   }
 
   return NS_OK;
 }
@@ -1279,22 +1294,21 @@ nsJSContext::GarbageCollectNow(JS::gcrea
 
   if (sCCLockedOut && aIncremental == IncrementalGC) {
     // We're in the middle of incremental GC. Do another slice.
     JS::PrepareForIncrementalGC(sRuntime);
     JS::IncrementalGCSlice(sRuntime, aReason, aSliceMillis);
     return;
   }
 
+  JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL;
   JS::PrepareForFullGC(sRuntime);
   if (aIncremental == IncrementalGC) {
-    MOZ_ASSERT(aShrinking == NonShrinkingGC);
-    JS::StartIncrementalGC(sRuntime, GC_NORMAL, aReason, aSliceMillis);
+    JS::StartIncrementalGC(sRuntime, gckind, aReason, aSliceMillis);
   } else {
-    JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL;
     JS::GCForReason(sRuntime, gckind, aReason);
   }
 }
 
 //static
 void
 nsJSContext::ShrinkGCBuffersNow()
 {
@@ -1793,16 +1807,26 @@ GCTimerFired(nsITimer *aTimer, void *aCl
 
 void
 ShrinkGCBuffersTimerFired(nsITimer *aTimer, void *aClosure)
 {
   nsJSContext::KillShrinkGCBuffersTimer();
   nsJSContext::ShrinkGCBuffersNow();
 }
 
+// static
+void
+ShrinkingGCTimerFired(nsITimer* aTimer, void* aClosure)
+{
+  nsJSContext::KillShrinkingGCTimer();
+  nsJSContext::GarbageCollectNow(JS::gcreason::USER_INACTIVE,
+                                 nsJSContext::IncrementalGC,
+                                 nsJSContext::ShrinkingGC);
+}
+
 static bool
 ShouldTriggerCC(uint32_t aSuspected)
 {
   return sNeedsFullCC ||
          aSuspected > NS_CC_PURPLE_LIMIT ||
          (aSuspected > NS_CC_FORCED_PURPLE_LIMIT &&
           TimeUntilNow(sLastCCEndTime) > NS_CC_FORCED);
 }
@@ -2027,16 +2051,36 @@ nsJSContext::PokeShrinkGCBuffers()
 
   sShrinkGCBuffersTimer->InitWithFuncCallback(ShrinkGCBuffersTimerFired, nullptr,
                                               NS_SHRINK_GC_BUFFERS_DELAY,
                                               nsITimer::TYPE_ONE_SHOT);
 }
 
 // static
 void
+nsJSContext::PokeShrinkingGC()
+{
+  if (sShrinkingGCTimer || sShuttingDown) {
+    return;
+  }
+
+  CallCreateInstance("@mozilla.org/timer;1", &sShrinkingGCTimer);
+
+  if (!sShrinkingGCTimer) {
+    // Failed to create timer (probably because we're in XPCOM shutdown)
+    return;
+  }
+
+  sShrinkingGCTimer->InitWithFuncCallback(ShrinkingGCTimerFired, nullptr,
+                                          NS_SHRINKING_GC_DELAY,
+                                          nsITimer::TYPE_ONE_SHOT);
+}
+
+// static
+void
 nsJSContext::MaybePokeCC()
 {
   if (sCCTimer || sICCTimer || sShuttingDown || !sHasRunGC) {
     return;
   }
 
   if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
     sCCTimerFireCount = 0;
@@ -2088,16 +2132,26 @@ nsJSContext::KillShrinkGCBuffersTimer()
   if (sShrinkGCBuffersTimer) {
     sShrinkGCBuffersTimer->Cancel();
     NS_RELEASE(sShrinkGCBuffersTimer);
   }
 }
 
 //static
 void
+nsJSContext::KillShrinkingGCTimer()
+{
+  if (sShrinkingGCTimer) {
+    sShrinkingGCTimer->Cancel();
+    NS_RELEASE(sShrinkingGCTimer);
+  }
+}
+
+//static
+void
 nsJSContext::KillCCTimer()
 {
   sCCLockedOutTime = 0;
   if (sCCTimer) {
     sCCTimer->Cancel();
     NS_RELEASE(sCCTimer);
   }
 }
@@ -2277,17 +2331,17 @@ nsJSContext::LikelyShortLivingObjectCrea
 {
   ++sLikelyShortLivingObjectsNeedingGC;
 }
 
 void
 mozilla::dom::StartupJSEnvironment()
 {
   // initialize all our statics, so that we can restart XPCOM
-  sGCTimer = sFullGCTimer = sCCTimer = sICCTimer = nullptr;
+  sGCTimer = sShrinkingGCTimer = sFullGCTimer = sCCTimer = sICCTimer = nullptr;
   sCCLockedOut = false;
   sCCLockedOutTime = 0;
   sLastCCEndTime = TimeStamp();
   sHasRunGC = false;
   sPendingLoadCount = 0;
   sLoadingInProgress = false;
   sCCollectedWaitingForGC = 0;
   sCCollectedZonesWaitingForGC = 0;
@@ -2682,18 +2736,24 @@ nsJSContext::EnsureStatics()
   if (!obs) {
     MOZ_CRASH();
   }
 
   Preferences::AddBoolVarCache(&sGCOnMemoryPressure,
                                "javascript.options.gc_on_memory_pressure",
                                true);
 
+  Preferences::AddBoolVarCache(&sCompactOnUserInactive,
+                               "javascript.options.compact_on_user_inactive",
+                               true);
+
   nsIObserver* observer = new nsJSEnvironmentObserver();
   obs->AddObserver(observer, "memory-pressure", false);
+  obs->AddObserver(observer, "user-interaction-inactive", false);
+  obs->AddObserver(observer, "user-interaction-active", false);
   obs->AddObserver(observer, "quit-application", false);
   obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   // Bug 907848 - We need to explicitly get the nsIDOMScriptObjectFactory
   // service in order to force its constructor to run, which registers a
   // shutdown observer. It would be nice to make this more explicit and less
   // side-effect-y.
   nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(kDOMScriptObjectFactoryCID);
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -111,16 +111,19 @@ public:
   static void RunNextCollectorTimer();
 
   static void PokeGC(JS::gcreason::Reason aReason, int aDelay = 0);
   static void KillGCTimer();
 
   static void PokeShrinkGCBuffers();
   static void KillShrinkGCBuffersTimer();
 
+  static void PokeShrinkingGC();
+  static void KillShrinkingGCTimer();
+
   static void MaybePokeCC();
   static void KillCCTimer();
   static void KillICCTimer();
   static void KillFullGCTimer();
   static void KillInterSliceGCTimer();
 
   // Calling LikelyShortLivingObjectCreated() makes a GC more likely.
   static void LikelyShortLivingObjectCreated();
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -492,17 +492,17 @@ CreateInterfaceObject(JSContext* cx, JS:
                       const NativeProperties* properties,
                       const NativeProperties* chromeOnlyProperties,
                       const char* name, bool defineOnGlobal)
 {
   JS::Rooted<JSObject*> constructor(cx);
   if (constructorClass) {
     MOZ_ASSERT(constructorProto);
     constructor = JS_NewObjectWithGivenProto(cx, Jsvalify(constructorClass),
-                                             constructorProto, global);
+                                             constructorProto);
   } else {
     MOZ_ASSERT(constructorNative);
     MOZ_ASSERT(constructorProto == JS_GetFunctionPrototype(cx, global));
     constructor = CreateConstructor(cx, global, name, constructorNative,
                                     ctorNargs);
   }
   if (!constructor) {
     return nullptr;
@@ -1610,17 +1610,17 @@ XrayOwnPropertyKeys(JSContext* cx, JS::H
     }
   }
 
   return (type == eGlobalInterfacePrototype && GlobalPropertiesAreOwn()) ||
          XrayOwnNativePropertyKeys(cx, wrapper, nativePropertyHooks, type,
                                    obj, flags, props);
 }
 
-NativePropertyHooks sWorkerNativePropertyHooks = {
+NativePropertyHooks sEmptyNativePropertyHooks = {
   nullptr,
   nullptr,
   {
     nullptr,
     nullptr
   },
   prototypes::id::_ID_Count,
   constructors::id::_ID_Count,
@@ -1769,27 +1769,29 @@ ReparentWrapper(JSContext* aCx, JS::Hand
   // transplanting code, since it has no good way to handle errors. This uses
   // the untrusted script limit, which is not strictly necessary since no
   // actual script should run.
   JS_CHECK_RECURSION_CONSERVATIVE(aCx, return NS_ERROR_FAILURE);
 
   JS::Rooted<JSObject*> aObj(aCx, aObjArg);
   const DOMJSClass* domClass = GetDOMClass(aObj);
 
+  // DOM things are always parented to globals.
   JS::Rooted<JSObject*> oldParent(aCx, JS_GetParent(aObj));
+  MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(oldParent) == oldParent);
+
   JS::Rooted<JSObject*> newParent(aCx, domClass->mGetParent(aCx, aObj));
+  MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(newParent) == newParent);
 
   JSAutoCompartment oldAc(aCx, oldParent);
 
   JSCompartment* oldCompartment = js::GetObjectCompartment(oldParent);
   JSCompartment* newCompartment = js::GetObjectCompartment(newParent);
   if (oldCompartment == newCompartment) {
-    if (!JS_SetParent(aCx, aObj, newParent)) {
-      MOZ_CRASH();
-    }
+    MOZ_ASSERT(oldParent == newParent);
     return NS_OK;
   }
 
   nsISupports* native = UnwrapDOMObjectToISupports(aObj);
   if (!native) {
     return NS_OK;
   }
 
@@ -1801,19 +1803,17 @@ ReparentWrapper(JSContext* aCx, JS::Hand
 
   JSAutoCompartment newAc(aCx, newParent);
 
   // First we clone the reflector. We get a copy of its properties and clone its
   // expando chain. The only part that is dangerous here is that if we have to
   // return early we must avoid ending up with two reflectors pointing to the
   // same native. Other than that, the objects we create will just go away.
 
-  JS::Rooted<JSObject*> global(aCx,
-                               js::GetGlobalForObjectCrossCompartment(newParent));
-  JS::Handle<JSObject*> proto = (domClass->mGetProto)(aCx, global);
+  JS::Handle<JSObject*> proto = (domClass->mGetProto)(aCx, newParent);
   if (!proto) {
     return NS_ERROR_FAILURE;
   }
 
   JS::Rooted<JSObject*> newobj(aCx, JS_CloneObject(aCx, aObj, proto, newParent));
   if (!newobj) {
     return NS_ERROR_FAILURE;
   }
@@ -1828,18 +1828,17 @@ ReparentWrapper(JSContext* aCx, JS::Hand
   // set to null. |aObj| will go away soon, because we swap it with
   // another object during the transplant and let that object die.
   JS::Rooted<JSObject*> propertyHolder(aCx);
   {
     AutoCloneDOMObjectSlotGuard cloneGuard(aCx, aObj, newobj);
 
     JS::Rooted<JSObject*> copyFrom(aCx, isProxy ? expandoObject : aObj);
     if (copyFrom) {
-      propertyHolder = JS_NewObjectWithGivenProto(aCx, nullptr, JS::NullPtr(),
-                                                  newParent);
+      propertyHolder = JS_NewObjectWithGivenProto(aCx, nullptr, JS::NullPtr());
       if (!propertyHolder) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
 
       if (!JS_CopyPropertiesFrom(aCx, propertyHolder, copyFrom)) {
         return NS_ERROR_FAILURE;
       }
     } else {
@@ -1898,22 +1897,17 @@ ReparentWrapper(JSContext* aCx, JS::Hand
         htmlobject = nullptr;
       }
     }
   }
   if (htmlobject) {
     htmlobject->SetupProtoChain(aCx, aObj);
   }
 
-  // Now we can just fix up the parent and return the wrapper
-
-  if (newParent && !JS_SetParent(aCx, aObj, newParent)) {
-    MOZ_CRASH();
-  }
-
+  // Now we can just return the wrapper
   return NS_OK;
 }
 
 GlobalObject::GlobalObject(JSContext* aCx, JSObject* aObject)
   : mGlobalJSObject(aCx),
     mCx(aCx),
     mGlobalObject(nullptr)
 {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2497,17 +2497,17 @@ XrayGetNativeProto(JSContext* cx, JS::Ha
         DOMIfaceAndProtoJSClass::FromJSClass(clasp)->mGetParentProto;
       protop.set(protoGetter(cx, global));
     }
   }
 
   return JS_WrapObject(cx, protop);
 }
 
-extern NativePropertyHooks sWorkerNativePropertyHooks;
+extern NativePropertyHooks sEmptyNativePropertyHooks;
 
 // We use one constructor JSNative to represent all DOM interface objects (so
 // we can easily detect when we need to wrap them in an Xray wrapper). We store
 // the real JSNative in the mNative member of a JSNativeHolder in the
 // CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
 // specific interface object. We also store the NativeProperties in the
 // JSNativeHolder.
 // Note that some interface objects are not yet a JSFunction but a normal
@@ -2790,37 +2790,36 @@ public:
       js::SetReservedOrProxyPrivateSlot(mReflector, DOM_OBJECT_SLOT,
                                         JS::UndefinedValue());
     }
   }
 
   void
   CreateProxyObject(JSContext* aCx, const js::Class* aClass,
                     const DOMProxyHandler* aHandler,
-                    JS::Handle<JSObject*> aProto,
-                    JS::Handle<JSObject*> aParent, T* aNative,
+                    JS::Handle<JSObject*> aProto, T* aNative,
                     JS::MutableHandle<JSObject*> aReflector)
   {
     js::ProxyOptions options;
     options.setClass(aClass);
     JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aNative));
     aReflector.set(js::NewProxyObject(aCx, aHandler, proxyPrivateVal, aProto,
-                                      aParent, options));
+                                      /* parent= */nullptr, options));
     if (aReflector) {
       mNative = aNative;
       mReflector = aReflector;
     }
   }
 
   void
   CreateObject(JSContext* aCx, const JSClass* aClass,
-               JS::Handle<JSObject*> aProto, JS::Handle<JSObject*> aParent,
+               JS::Handle<JSObject*> aProto,
                T* aNative, JS::MutableHandle<JSObject*> aReflector)
   {
-    aReflector.set(JS_NewObjectWithGivenProto(aCx, aClass, aProto, aParent));
+    aReflector.set(JS_NewObjectWithGivenProto(aCx, aClass, aProto));
     if (aReflector) {
       js::SetReservedSlot(aReflector, DOM_OBJECT_SLOT, JS::PrivateValue(aNative));
       mNative = aNative;
       mReflector = aReflector;
     }
   }
 
   void
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -39,19 +39,23 @@
 #   * wrapperCache: True if this object is a wrapper cache.  Objects that are
 #                   not can only be returned from a limited set of methods,
 #                   cannot be prefable, and must ensure that they disallow
 #                   XPConnect wrapping.  Always false for callback interfaces.
 #                   Always true for worker descriptors for non-callback
 #                   interfaces.  Defaults to true for non-worker non-callback
 #                   descriptors.
 #
-#   The following fields are either a string, an array (defaults to an empty
-#   array) or a dictionary with three possible keys (all, getterOnly and
-#   setterOnly) each having such an array as the value
+# A non-worker descriptor can have 'wantsXrays': False specified if it
+# should not have Xray hooks generated.  Make sure to have someone
+# familiar with Xrays review any use of this!
+#
+# The following fields are either a string, an array (defaults to an empty
+# array) or a dictionary with three possible keys (all, getterOnly and
+# setterOnly) each having such an array as the value
 #
 #   * implicitJSContext - attributes and methods specified in the .webidl file
 #                         that require a JSContext as the first argument
 #
 # A descriptor can also have 'skipGen': True specified if it should be skipped
 # when deciding what header includes to generate and should never have an
 # implementation generated for it.  This is only needed in special cases like
 # worker descriptors for objects that will never actually appear in workers.
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -250,31 +250,31 @@ class CGNativePropertyHooks(CGThing):
     Generate a NativePropertyHooks for a given descriptor
     """
     def __init__(self, descriptor, properties):
         CGThing.__init__(self)
         self.descriptor = descriptor
         self.properties = properties
 
     def declare(self):
-        if self.descriptor.workers:
+        if not self.descriptor.wantsXrays:
             return ""
         return dedent("""
             // We declare this as an array so that retrieving a pointer to this
             // binding's property hooks only requires compile/link-time resolvable
             // address arithmetic.  Declaring it as a pointer instead would require
             // doing a run-time load to fetch a pointer to this binding's property
             // hooks.  And then structures which embedded a pointer to this structure
             // would require a run-time load for proper initialization, which would
             // then induce static constructors.  Lots of static constructors.
             extern const NativePropertyHooks sNativePropertyHooks[];
             """)
 
     def define(self):
-        if self.descriptor.workers:
+        if not self.descriptor.wantsXrays:
             return ""
         if self.descriptor.concrete and self.descriptor.proxy:
             resolveOwnProperty = "ResolveOwnProperty"
             enumerateOwnProperties = "EnumerateOwnProperties"
         elif self.descriptor.needsXrayResolveHooks():
             resolveOwnProperty = "ResolveOwnPropertyViaResolve"
             enumerateOwnProperties = "EnumerateOwnPropertiesViaGetOwnPropertyNames"
         else:
@@ -318,17 +318,17 @@ class CGNativePropertyHooks(CGThing):
             regular=regular,
             chrome=chrome,
             prototypeID=prototypeID,
             constructorID=constructorID,
             parentHooks=parentHooks)
 
 
 def NativePropertyHooks(descriptor):
-    return "&sWorkerNativePropertyHooks" if descriptor.workers else "sNativePropertyHooks"
+    return "&sEmptyNativePropertyHooks" if not descriptor.wantsXrays else "sNativePropertyHooks"
 
 
 def DOMClass(descriptor):
     protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeNameChain]
     # Pad out the list to the right length with _ID_Count so we
     # guarantee that all the lists are the same length.  _ID_Count
     # is never the ID of any prototype, so it's safe to use as
     # padding.
@@ -518,79 +518,19 @@ def MemberIsUnforgeable(member, descript
     # method, because callers will compare its return value to
     # booleans.
     return bool((member.isAttr() or member.isMethod()) and
                 not member.isStatic() and
                 (member.isUnforgeable() or
                  descriptor.interface.getExtendedAttribute("Unforgeable")))
 
 
-def UseHolderForUnforgeable(descriptor):
-    return (descriptor.concrete and
-            descriptor.proxy and
-            any(m for m in descriptor.interface.members
-                if MemberIsUnforgeable(m, descriptor)))
-
-
-def CallOnUnforgeableHolder(descriptor, code, isXrayCheck=None,
-                            useSharedRoot=False):
-    """
-    Generate the code to execute the code in "code" on an unforgeable holder if
-    needed. code should be a string containing the code to execute. If it
-    contains a ${holder} string parameter it will be replaced with the
-    unforgeable holder object.
-
-    If isXrayCheck is not None it should be a string that contains a statement
-    returning whether proxy is an Xray. If isXrayCheck is None the generated
-    code won't try to unwrap Xrays.
-
-    If useSharedRoot is true, we will use an existing
-    JS::Rooted<JSObject*> sharedRoot for storing our unforgeable holder instead
-    of declaring a new Rooted.
-    """
-    if isXrayCheck is not None:
-        pre = fill(
-            """
-            // Scope for 'global', 'ac' and 'unforgeableHolder'
-            {
-              JS::Rooted<JSObject*> global(cx);
-              Maybe<JSAutoCompartment> ac;
-              if (${isXrayCheck}) {
-                global = js::GetGlobalForObjectCrossCompartment(js::UncheckedUnwrap(proxy));
-                ac.emplace(cx, global);
-              } else {
-                global = js::GetGlobalForObjectCrossCompartment(proxy);
-              }
-            """,
-            isXrayCheck=isXrayCheck)
-    else:
-        pre = dedent("""
-            // Scope for 'global' and 'unforgeableHolder'
-            {
-              JSObject* global = js::GetGlobalForObjectCrossCompartment(proxy);
-            """)
-
-    if useSharedRoot:
-        holderDecl = "JS::Rooted<JSObject*>& unforgeableHolder(sharedRoot);\n"
-    else:
-        holderDecl = "JS::Rooted<JSObject*> unforgeableHolder(cx);\n"
-
-    code = string.Template(code).substitute({"holder": "unforgeableHolder"})
-    return fill(
-        """
-        $*{pre}
-          $*{holderDecl}
-          unforgeableHolder = GetUnforgeableHolder(global, prototypes::id::${name});
-          $*{code}
-        }
-        """,
-        pre=pre,
-        holderDecl=holderDecl,
-        name=descriptor.name,
-        code=code)
+def HasUnforgeableMembers(descriptor):
+    return any(MemberIsUnforgeable(m, descriptor) for m in
+               descriptor.interface.members)
 
 
 def InterfacePrototypeObjectProtoGetter(descriptor):
     """
     Returns a tuple with two elements:
 
         1) The name of the function to call to get the prototype to use for the
            interface prototype object as a JSObject*.
@@ -626,18 +566,16 @@ class CGPrototypeJSClass(CGThing):
 
     def declare(self):
         # We're purely for internal consumption
         return ""
 
     def define(self):
         prototypeID, depth = PrototypeIDAndDepth(self.descriptor)
         slotCount = "DOM_INTERFACE_PROTO_SLOTS_BASE"
-        if UseHolderForUnforgeable(self.descriptor):
-            slotCount += " + 1 /* slot for the JSObject holding the unforgeable properties */"
         (protoGetter, _) = InterfacePrototypeObjectProtoGetter(self.descriptor)
         type = "eGlobalInterfacePrototype" if self.descriptor.isGlobal() else "eInterfacePrototype"
         return fill(
             """
             static const DOMIfaceAndProtoJSClass PrototypeClass = {
               {
                 "${name}Prototype",
                 JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(${slotCount}),
@@ -1953,18 +1891,17 @@ class PropertyDefiner:
             if self.hasChromeOnly():
                 return "sChrome" + self.name
         else:
             if self.hasNonChromeOnly():
                 return "s" + self.name
         return "nullptr"
 
     def usedForXrays(self):
-        # No Xrays in workers.
-        return not self.descriptor.workers
+        return self.descriptor.wantsXrays
 
     def __str__(self):
         # We only need to generate id arrays for things that will end
         # up used via ResolveProperty or EnumerateProperties.
         str = self.generateArray(self.regular, self.variableName(False),
                                  self.usedForXrays())
         if self.hasChromeOnly():
             str += self.generateArray(self.chrome, self.variableName(True),
@@ -2614,19 +2551,18 @@ class CGCreateInterfaceObjectsMethod(CGA
 
         needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
         needInterfacePrototypeObject = self.descriptor.interface.hasInterfacePrototypeObject()
 
         # if we don't need to create anything, why are we generating this?
         assert needInterfaceObject or needInterfacePrototypeObject
 
         idsToInit = []
-        # There is no need to init any IDs in workers, because worker bindings
-        # don't have Xrays.
-        if not self.descriptor.workers:
+        # There is no need to init any IDs in bindings that don't want Xrays.
+        if self.descriptor.wantsXrays:
             for var in self.properties.arrayNames():
                 props = getattr(self.properties, var)
                 # We only have non-chrome ids to init if we have no chrome ids.
                 if props.hasChromeOnly():
                     idsToInit.append(props.variableName(True))
                 if props.hasNonChromeOnly():
                     idsToInit.append(props.variableName(False))
         if len(idsToInit) > 0:
@@ -2653,32 +2589,16 @@ class CGCreateInterfaceObjectsMethod(CGA
             prefCache = CGWrapper(CGIndenter(CGList(prefCacheData)),
                                   pre=("static bool sPrefCachesInited = false;\n"
                                        "if (!sPrefCachesInited) {\n"
                                        "  sPrefCachesInited = true;\n"),
                                   post="}\n")
         else:
             prefCache = None
 
-        if UseHolderForUnforgeable(self.descriptor):
-            createUnforgeableHolder = CGGeneric(dedent("""
-                JS::Rooted<JSObject*> unforgeableHolder(aCx,
-                  JS_NewObjectWithGivenProto(aCx, nullptr, JS::NullPtr(), JS::NullPtr()));
-                if (!unforgeableHolder) {
-                  return;
-                }
-                """))
-            defineUnforgeables = InitUnforgeablePropertiesOnObject(self.descriptor,
-                                                                   "unforgeableHolder",
-                                                                   self.properties)
-            createUnforgeableHolder = CGList(
-                [createUnforgeableHolder, defineUnforgeables])
-        else:
-            createUnforgeableHolder = None
-
         getParentProto = fill(
             """
             JS::${type}<JSObject*> parentProto(${getParentProto});
             if (!parentProto) {
               return;
             }
             """,
             type=parentProtoType,
@@ -2753,32 +2673,19 @@ class CGCreateInterfaceObjectsMethod(CGA
             constructHookHolder=constructHookHolder,
             constructArgs=constructArgs,
             namedConstructors=namedConstructors,
             interfaceCache=interfaceCache,
             properties=properties,
             chromeProperties=chromeProperties,
             name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr")
 
-        if UseHolderForUnforgeable(self.descriptor):
-            assert needInterfacePrototypeObject
-            setUnforgeableHolder = CGGeneric(fill(
-                """
-                JSObject* proto = aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::${name});
-                if (proto) {
-                  js::SetReservedSlot(proto, DOM_INTERFACE_PROTO_SLOTS_BASE,
-                                      JS::ObjectValue(*unforgeableHolder));
-                }
-                """,
-                name=self.descriptor.name))
-        else:
-            setUnforgeableHolder = None
         return CGList(
             [CGGeneric(getParentProto), CGGeneric(getConstructorProto), initIds,
-             prefCache, createUnforgeableHolder, CGGeneric(call), setUnforgeableHolder],
+             prefCache, CGGeneric(call)],
             "\n").define()
 
 
 class CGGetPerInterfaceObject(CGAbstractMethod):
     """
     A method for getting a per-interface object (a prototype object or interface
     constructor object).
     """
@@ -3048,66 +2955,101 @@ def CreateBindingJSObject(descriptor, pr
     objDecl = "BindingJSObjectCreator<%s> creator(aCx);\n" % descriptor.nativeType
 
     # We don't always need to root obj, but there are a variety
     # of cases where we do, so for simplicity, just always root it.
     if descriptor.proxy:
         create = dedent(
             """
             creator.CreateProxyObject(aCx, &Class.mBase, DOMProxyHandler::getInstance(),
-                                      proto, global, aObject, aReflector);
+                                      proto, aObject, aReflector);
             if (!aReflector) {
               return false;
             }
 
             """)
         if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
             create += dedent("""
                 js::SetProxyExtra(aReflector, JSPROXYSLOT_EXPANDO,
                                   JS::PrivateValue(&aObject->mExpandoAndGeneration));
 
                 """)
     else:
         create = dedent(
             """
-            creator.CreateObject(aCx, Class.ToJSClass(), proto, global, aObject, aReflector);
+            creator.CreateObject(aCx, Class.ToJSClass(), proto, aObject, aReflector);
             if (!aReflector) {
               return false;
             }
             """)
     return objDecl + create
 
 
-def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturnValue=""):
+def InitUnforgeableProperties(descriptor, properties, wrapperCache):
     """
     properties is a PropertyArrays instance
     """
-    unforgeables = []
-
-    if failureReturnValue:
-        failureReturnValue = " " + failureReturnValue
+    unforgeableAttrs = properties.unforgeableAttrs
+    if not unforgeableAttrs.hasNonChromeOnly() and not unforgeableAttrs.hasChromeOnly():
+        return ""
+
+    unforgeables = [
+        CGGeneric(dedent(
+            """
+            // Important: do unforgeable property setup after we have handed
+            // over ownership of the C++ object to obj as needed, so that if
+            // we fail and it ends up GCed it won't have problems in the
+            // finalizer trying to drop its ownership of the C++ object.
+            """))
+    ]
+
+    if wrapperCache:
+        cleanup = dedent(
+            """
+            aCache->ReleaseWrapper(aObject);
+            aCache->ClearWrapper();
+            """)
     else:
-        failureReturnValue = ""
+        cleanup = ""
+
+    # For proxies, we want to define on the expando object, not directly on the
+    # reflector, so we can make sure we don't get confused by named getters.
+    if descriptor.proxy:
+        unforgeables.append(CGGeneric(fill(
+            """
+            JS::Rooted<JSObject*> expando(aCx,
+              DOMProxyHandler::EnsureExpandoObject(aCx, aReflector));
+            if (!expando) {
+              $*{cleanup}
+              return false;
+            }
+            """,
+            cleanup=cleanup)))
+        obj = "expando"
+    else:
+        obj = "aReflector"
 
     defineUnforgeableAttrs = fill(
         """
         if (!DefineUnforgeableAttributes(aCx, ${obj}, %s)) {
-          return${rv};
+          $*{cleanup}
+          return false;
         }
         """,
         obj=obj,
-        rv=failureReturnValue)
+        cleanup=cleanup)
     defineUnforgeableMethods = fill(
         """
         if (!DefineUnforgeableMethods(aCx, ${obj}, %s)) {
-          return${rv};
+          $*{cleanup}
+          return false;
         }
         """,
         obj=obj,
-        rv=failureReturnValue)
+        cleanup=cleanup)
 
     unforgeableMembers = [
         (defineUnforgeableAttrs, properties.unforgeableAttrs),
         (defineUnforgeableMethods, properties.unforgeableMethods)
     ]
     for (template, array) in unforgeableMembers:
         if array.hasNonChromeOnly():
             unforgeables.append(CGGeneric(template % array.variableName(False)))
@@ -3118,46 +3060,24 @@ def InitUnforgeablePropertiesOnObject(de
 
     if descriptor.interface.getExtendedAttribute("Unforgeable"):
         # We do our undefined toJSON here, not as a regular property
         # because we don't have a concept of value props anywhere.
         unforgeables.append(CGGeneric(fill(
             """
             if (!JS_DefineProperty(aCx, ${obj}, "toJSON", JS::UndefinedHandleValue,
                                    JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
-              return${rv};
+              $*{cleanup}
+              return false;
             }
             """,
             obj=obj,
-            rv=failureReturnValue)))
-
-    return CGList(unforgeables)
-
-
-def InitUnforgeableProperties(descriptor, properties):
-    """
-    properties is a PropertyArrays instance
-    """
-    unforgeableAttrs = properties.unforgeableAttrs
-    if not unforgeableAttrs.hasNonChromeOnly() and not unforgeableAttrs.hasChromeOnly():
-        return ""
-
-    if descriptor.proxy:
-        unforgeableProperties = CGGeneric(
-            "// Unforgeable properties on proxy-based bindings are stored in an object held\n"
-            "// by the interface prototype object.\n")
-    else:
-        unforgeableProperties = CGWrapper(
-            InitUnforgeablePropertiesOnObject(descriptor, "aReflector", properties, "false"),
-            pre=(
-                "// Important: do unforgeable property setup after we have handed\n"
-                "// over ownership of the C++ object to obj as needed, so that if\n"
-                "// we fail and it ends up GCed it won't have problems in the\n"
-                "// finalizer trying to drop its ownership of the C++ object.\n"))
-    return CGWrapper(unforgeableProperties, pre="\n").define()
+            cleanup=cleanup)))
+
+    return CGWrapper(CGList(unforgeables), pre="\n").define()
 
 
 def AssertInheritanceChain(descriptor):
     asserts = ""
     iface = descriptor.interface
     while iface:
         desc = descriptor.getDescriptor(iface.identifier.name)
         asserts += (
@@ -3176,23 +3096,31 @@ def InitMemberSlots(descriptor, wrapperC
     Note that this is called after the SetWrapper() call in the
     wrapperCache case, since that can affect how our getters behave
     and we plan to invoke them here.  So if we fail, we need to
     ClearWrapper.
     """
     if not descriptor.interface.hasMembersInSlots():
         return ""
     if wrapperCache:
-        clearWrapper = "  aCache->ClearWrapper();\n"
+        clearWrapper = dedent(
+            """
+            aCache->ReleaseWrapper(aObject);
+            aCache->ClearWrapper();
+            """)
     else:
         clearWrapper = ""
-    return ("if (!UpdateMemberSlots(aCx, aReflector, aObject)) {\n"
-            "%s"
-            "  return false;\n"
-            "}\n" % clearWrapper)
+    return fill(
+        """
+        if (!UpdateMemberSlots(aCx, aReflector, aObject)) {
+          $*{clearWrapper}
+          return false;
+        }
+        """,
+        clearWrapper=clearWrapper)
 
 
 class CGWrapWithCacheMethod(CGAbstractMethod):
     """
     Create a wrapper JSObject for a given native that implements nsWrapperCache.
 
     properties should be a PropertyArrays instance.
     """
@@ -3201,16 +3129,26 @@ class CGWrapWithCacheMethod(CGAbstractMe
         args = [Argument('JSContext*', 'aCx'),
                 Argument(descriptor.nativeType + '*', 'aObject'),
                 Argument('nsWrapperCache*', 'aCache'),
                 Argument('JS::MutableHandle<JSObject*>', 'aReflector')]
         CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'bool', args)
         self.properties = properties
 
     def definition_body(self):
+        # For proxies, we have to SetWrapper() before we init unforgeables.  But
+        # for non-proxies we'd rather do it the other way around, so our
+        # unforgeables don't force preservation of the wrapper.
+        setWrapper = "aCache->SetWrapper(aReflector);\n"
+        if self.descriptor.proxy:
+            setWrapperProxy = setWrapper
+            setWrapperNonProxy = ""
+        else:
+            setWrapperProxy = ""
+            setWrapperNonProxy = setWrapper
         return fill(
             """
             $*{assertion}
 
             MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
                        "nsISupports must be on our primary inheritance chain");
 
             JS::Rooted<JSObject*> parent(aCx, WrapNativeParent(aCx, aObject->GetParentObject()));
@@ -3229,26 +3167,28 @@ class CGWrapWithCacheMethod(CGAbstractMe
             JS::Rooted<JSObject*> global(aCx, js::GetGlobalForObjectCrossCompartment(parent));
             JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, global);
             if (!proto) {
               return false;
             }
 
             $*{createObject}
 
+            $*{setWrapperProxy}
             $*{unforgeable}
-
-            aCache->SetWrapper(aReflector);
+            $*{setWrapperNonProxy}
             $*{slots}
             creator.InitializationSucceeded();
             return true;
             """,
             assertion=AssertInheritanceChain(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
-            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
+            setWrapperProxy=setWrapperProxy,
+            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties, True),
+            setWrapperNonProxy=setWrapperNonProxy,
             slots=InitMemberSlots(self.descriptor, True))
 
 
 class CGWrapMethod(CGAbstractMethod):
     def __init__(self, descriptor):
         # XXX can we wrap if we don't have an interface prototype object?
         assert descriptor.interface.hasInterfacePrototypeObject()
         args = [Argument('JSContext*', 'aCx'),
@@ -3295,17 +3235,17 @@ class CGWrapNonWrapperCacheMethod(CGAbst
             $*{unforgeable}
 
             $*{slots}
             creator.InitializationSucceeded();
             return true;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
-            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
+            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties, False),
             slots=InitMemberSlots(self.descriptor, False))
 
 
 class CGWrapGlobalMethod(CGAbstractMethod):
     """
     Create a wrapper JSObject for a global.  The global must implement
     nsWrapperCache.
 
@@ -3372,17 +3312,17 @@ class CGWrapGlobalMethod(CGAbstractMetho
             $*{fireOnNewGlobal}
 
             return true;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
             nativeType=self.descriptor.nativeType,
             properties=properties,
             chromeProperties=chromeProperties,
-            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
+            unforgeable=InitUnforgeableProperties(self.descriptor, self.properties, True),
             slots=InitMemberSlots(self.descriptor, True),
             fireOnNewGlobal=fireOnNewGlobal)
 
 
 class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'aCx'),
                 Argument('JS::Handle<JSObject*>', 'aWrapper'),
@@ -10074,41 +10014,16 @@ class CGDOMJSProxyHandler_getOwnPropDesc
                   $*{callGetter}
                 }
 
                 """,
                 callGetter=CGProxyIndexedGetter(self.descriptor, templateValues).define())
         else:
             getIndexed = ""
 
-        if UseHolderForUnforgeable(self.descriptor):
-            tryHolder = dedent("""
-                if (!JS_GetPropertyDescriptorById(cx, ${holder}, id, desc)) {
-                  return false;
-                }
-                MOZ_ASSERT_IF(desc.object(), desc.object() == ${holder});
-                """)
-
-            # We don't want to look at the unforgeable holder at all
-            # in the xray case; that part got handled already.
-            getUnforgeable = fill(
-                """
-                if (!isXray) {
-                  $*{callOnUnforgeable}
-                  if (desc.object()) {
-                    desc.object().set(proxy);
-                    return true;
-                  }
-                }
-
-                """,
-                callOnUnforgeable=CallOnUnforgeableHolder(self.descriptor, tryHolder))
-        else:
-            getUnforgeable = ""
-
         if self.descriptor.supportsNamedProperties():
             operations = self.descriptor.operations
             readonly = toStringBool(operations['NamedSetter'] is None)
             enumerable = (
                 "self->NameIsEnumerable(Constify(%s))" %
                 # First [0] means first (and only) signature, [1] means
                 # "arguments" as opposed to return type, [0] means first (and
                 # only) argument.
@@ -10155,17 +10070,16 @@ class CGDOMJSProxyHandler_getOwnPropDesc
             namedGet += "\n"
         else:
             namedGet = ""
 
         return fill(
             """
             bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
             $*{getIndexed}
-            $*{getUnforgeable}
             JS::Rooted<JSObject*> expando(cx);
             if (!isXray && (expando = GetExpandoObject(proxy))) {
               if (!JS_GetPropertyDescriptorById(cx, expando, id, desc)) {
                 return false;
               }
               if (desc.object()) {
                 // Pretend the property lives on the wrapper.
                 desc.object().set(proxy);
@@ -10173,17 +10087,16 @@ class CGDOMJSProxyHandler_getOwnPropDesc
               }
             }
 
             $*{namedGet}
             desc.object().set(nullptr);
             return true;
             """,
             getIndexed=getIndexed,
-            getUnforgeable=getUnforgeable,
             namedGet=namedGet)
 
 
 class CGDOMJSProxyHandler_defineProperty(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<jsid>', 'id'),
@@ -10218,35 +10131,22 @@ class CGDOMJSProxyHandler_defineProperty
             set += fill(
                 """
                 if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
                   return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, "${name}");
                 }
                 """,
                 name=self.descriptor.name)
 
-        if UseHolderForUnforgeable(self.descriptor):
-            # It's OK to do the defineOnUnforgeable thing even in the Xray case,
-            # since in practice it won't let us change anything; we just want
-            # the js_DefineOwnProperty call for error reporting purposes.
-            defineOnUnforgeable = ("bool hasUnforgeable;\n"
-                                   "if (!JS_HasPropertyById(cx, ${holder}, id, &hasUnforgeable)) {\n"
-                                   "  return false;\n"
-                                   "}\n"
-                                   "if (hasUnforgeable) {\n"
-                                   "  *defined = true;\n"
-                                   "  bool unused;\n"
-                                   "  return js_DefineOwnProperty(cx, ${holder}, id, desc, &unused);\n"
-                                   "}\n")
-            set += CallOnUnforgeableHolder(self.descriptor,
-                                           defineOnUnforgeable,
-                                           "xpc::WrapperFactory::IsXrayWrapper(proxy)")
-
         namedSetter = self.descriptor.operations['NamedSetter']
         if namedSetter:
+            if HasUnforgeableMembers(self.descriptor):
+                raise TypeError("Can't handle a named setter on an interface "
+                                "that has unforgeables.  Figure out how that "
+                                "should work!")
             if self.descriptor.operations['NamedCreator'] is not namedSetter:
                 raise TypeError("Can't handle creator that's different from the setter")
             # If we support indexed properties, we won't get down here for
             # indices, so we can just do our setter unconditionally here.
             set += fill(
                 """
                 *defined = true;
                 $*{callSetter}
@@ -10290,16 +10190,20 @@ class CGDOMJSProxyHandler_delete(ClassMe
     def getBody(self):
         def getDeleterBody(type, foundVar=None):
             """
             type should be "Named" or "Indexed"
             """
             assert type in ("Named", "Indexed")
             deleter = self.descriptor.operations[type + 'Deleter']
             if deleter:
+                if HasUnforgeableMembers(self.descriptor):
+                    raise TypeError("Can't handle a deleter on an interface "
+                                    "that has unforgeables.  Figure out how "
+                                    "that should work!")
                 decls = ""
                 if (not deleter.signatures()[0][0].isPrimitive() or
                     deleter.signatures()[0][0].nullable() or
                     deleter.signatures()[0][0].tag() != IDLType.Tags.bool):
                     setBp = "*bp = true;\n"
                 else:
                     decls += "bool result;\n"
                     if foundVar is None:
@@ -10351,30 +10255,16 @@ class CGDOMJSProxyHandler_delete(ClassMe
                 if (IsArrayIndex(index)) {
                   $*{indexedBody}
                   // We always return here, even if the property was not found
                   return true;
                 }
                 """,
                 indexedBody=indexedBody)
 
-        if UseHolderForUnforgeable(self.descriptor):
-            unforgeable = dedent("""
-                bool hasUnforgeable;
-                if (!JS_HasPropertyById(cx, ${holder}, id, &hasUnforgeable)) {
-                  return false;
-                }
-                if (hasUnforgeable) {
-                  *bp = false;
-                  return true;
-                }
-                """)
-            delete += CallOnUnforgeableHolder(self.descriptor, unforgeable)
-            delete += "\n"
-
         namedBody = getDeleterBody("Named", foundVar="found")
         if namedBody is not None:
             # We always return above for an index id in the case when we support
             # indexed properties, so we can just treat the id as a name
             # unconditionally here.
             delete += fill(
                 """
                 bool found = false;
@@ -10425,28 +10315,16 @@ class CGDOMJSProxyHandler_ownPropNames(C
                   if (!props.append(INT_TO_JSID(i))) {
                     return false;
                   }
                 }
                 """)
         else:
             addIndices = ""
 
-        if UseHolderForUnforgeable(self.descriptor):
-            addUnforgeable = dedent("""
-                if (!js::GetPropertyKeys(cx, ${holder}, flags, &props)) {
-                  return false;
-                }
-                """)
-            addUnforgeable = CallOnUnforgeableHolder(self.descriptor,
-                                                     addUnforgeable,
-                                                     "isXray")
-        else:
-            addUnforgeable = ""
-
         if self.descriptor.supportsNamedProperties():
             if self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
                 shadow = "!isXray"
             else:
                 shadow = "false"
             addNames = fill(
                 """
 
@@ -10459,29 +10337,27 @@ class CGDOMJSProxyHandler_ownPropNames(C
                 shadow=shadow)
         else:
             addNames = ""
 
         return fill(
             """
             bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
             $*{addIndices}
-            $*{addUnforgeable}
             $*{addNames}
 
             JS::Rooted<JSObject*> expando(cx);
             if (!isXray && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
                 !js::GetPropertyKeys(cx, expando, flags, &props)) {
               return false;
             }
 
             return true;
             """,
             addIndices=addIndices,
-            addUnforgeable=addUnforgeable,
             addNames=addNames)
 
 
 class CGDOMJSProxyHandler_hasOwn(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<jsid>', 'id'),
@@ -10503,29 +10379,16 @@ class CGDOMJSProxyHandler_hasOwn(ClassMe
                   return true;
                 }
 
                 """,
                 presenceChecker=CGProxyIndexedPresenceChecker(self.descriptor, foundVar="found").define())
         else:
             indexed = ""
 
-        if UseHolderForUnforgeable(self.descriptor):
-            unforgeable = dedent("""
-                bool b = true;
-                bool ok = JS_AlreadyHasOwnPropertyById(cx, ${holder}, id, &b);
-                *bp = !!b;
-                if (!ok || *bp) {
-                  return ok;
-                }
-                """)
-            unforgeable = CallOnUnforgeableHolder(self.descriptor, unforgeable)
-        else:
-            unforgeable = ""
-
         if self.descriptor.supportsNamedProperties():
             # If we support indexed properties we always return above for index
             # property names, so no need to check for those here.
             named = fill(
                 """
                 bool found = false;
                 $*{presenceChecker}
 
@@ -10551,66 +10414,49 @@ class CGDOMJSProxyHandler_hasOwn(ClassMe
             named = "*bp = false;\n"
 
         return fill(
             """
             MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
                       "Should not have a XrayWrapper here");
 
             $*{indexed}
-            $*{unforgeable}
 
             JS::Rooted<JSObject*> expando(cx, GetExpandoObject(proxy));
             if (expando) {
               bool b = true;
               bool ok = JS_HasPropertyById(cx, expando, id, &b);
               *bp = !!b;
               if (!ok || *bp) {
                 return ok;
               }
             }
 
             $*{named}
             return true;
             """,
             indexed=indexed,
-            unforgeable=unforgeable,
             named=named)
 
 
 class CGDOMJSProxyHandler_get(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<JSObject*>', 'receiver'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('JS::MutableHandle<JS::Value>', 'vp')]
         ClassMethod.__init__(self, "get", "bool", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
-        getUnforgeableOrExpando = "JS::Rooted<JSObject*> sharedRoot(cx);\n"
-        if UseHolderForUnforgeable(self.descriptor):
-            hasUnforgeable = dedent("""
-                bool hasUnforgeable;
-                if (!JS_AlreadyHasOwnPropertyById(cx, ${holder}, id, &hasUnforgeable)) {
-                  return false;
-                }
-                if (hasUnforgeable) {
-                  return JS_ForwardGetPropertyTo(cx, ${holder}, id, proxy, vp);
-                }
-                """)
-            getUnforgeableOrExpando += CallOnUnforgeableHolder(self.descriptor,
-                                                               hasUnforgeable,
-                                                               useSharedRoot=True)
-        getUnforgeableOrExpando += dedent("""
+        getUnforgeableOrExpando = dedent("""
             { // Scope for expando
-              JS::Rooted<JSObject*>& expando(sharedRoot);
-              expando = DOMProxyHandler::GetExpandoObject(proxy);
+              JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
               if (expando) {
                 bool hasProp;
                 if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
                   return false;
                 }
 
                 if (hasProp) {
                   // Forward the get to the expando object, but our receiver is whatever our
@@ -10700,17 +10546,17 @@ class CGDOMJSProxyHandler_setCustom(Clas
             self.descriptor.interface.getExtendedAttribute('OverrideBuiltins')):
             # Check assumptions.
             if self.descriptor.supportsIndexedProperties():
                 raise ValueError("In interface " + self.descriptor.name + ": " +
                                  "Can't cope with [OverrideBuiltins] and an indexed getter")
             if self.descriptor.operations['NamedCreator'] is not namedSetter:
                 raise ValueError("In interface " + self.descriptor.name + ": " +
                                  "Can't cope with named setter that is not also a named creator")
-            if UseHolderForUnforgeable(self.descriptor):
+            if HasUnforgeableMembers(self.descriptor):
                 raise ValueError("In interface " + self.descriptor.name + ": " +
                                  "Can't cope with [OverrideBuiltins] and unforgeable members")
 
             callSetter = CGProxyNamedSetter(self.descriptor, argumentMutableValue="vp")
             return (assertion +
                     callSetter.define() +
                     "*done = true;\n"
                     "return true;\n")
@@ -10770,17 +10616,18 @@ class CGDOMJSProxyHandler_finalizeInBack
 class CGDOMJSProxyHandler_finalize(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSFreeOp*', 'fop'), Argument('JSObject*', 'proxy')]
         ClassMethod.__init__(self, "finalize", "void", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
-        return ("%s* self = UnwrapProxy(proxy);\n\n" % self.descriptor.nativeType +
+        return (("%s* self = UnwrapPossiblyNotInitializedDOMObject<%s>(proxy);\n" %
+                 (self.descriptor.nativeType, self.descriptor.nativeType)) +
                 finalizeHook(self.descriptor, FINALIZE_HOOK_NAME, self.args[0].name).define())
 
 
 class CGDOMJSProxyHandler_getElements(ClassMethod):
     def __init__(self, descriptor):
         assert descriptor.supportsIndexedProperties()
 
         args = [Argument('JSContext*', 'cx'),
@@ -11160,24 +11007,24 @@ class CGDescriptor(CGThing):
         if descriptor.interface.isJSImplemented():
             for m in clearableCachedAttrs(descriptor):
                 cgThings.append(CGJSImplClearCachedValueMethod(descriptor, m))
 
         properties = PropertyArrays(descriptor)
         cgThings.append(CGGeneric(define=str(properties)))
         cgThings.append(CGNativeProperties(descriptor, properties))
 
-        # Set up our Xray callbacks as needed.  Note that we don't need to do
-        # it in workers.
-        if not descriptor.workers and descriptor.concrete and descriptor.proxy:
-            cgThings.append(CGResolveOwnProperty(descriptor))
-            cgThings.append(CGEnumerateOwnProperties(descriptor))
-        elif descriptor.needsXrayResolveHooks():
-            cgThings.append(CGResolveOwnPropertyViaResolve(descriptor))
-            cgThings.append(CGEnumerateOwnPropertiesViaGetOwnPropertyNames(descriptor))
+        # Set up our Xray callbacks as needed.
+        if descriptor.wantsXrays:
+            if descriptor.concrete and descriptor.proxy:
+                cgThings.append(CGResolveOwnProperty(descriptor))
+                cgThings.append(CGEnumerateOwnProperties(descriptor))
+            elif descriptor.needsXrayResolveHooks():
+                cgThings.append(CGResolveOwnPropertyViaResolve(descriptor))
+                cgThings.append(CGEnumerateOwnPropertiesViaGetOwnPropertyNames(descriptor))
 
         # Now that we have our ResolveOwnProperty/EnumerateOwnProperties stuff
         # done, set up our NativePropertyHooks.
         cgThings.append(CGNativePropertyHooks(descriptor, properties))
 
         if descriptor.interface.hasInterfaceObject():
             cgThings.append(CGClassConstructor(descriptor,
                                                descriptor.interface.ctor()))
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -297,16 +297,22 @@ def methodReturnsJSObject(method):
 class Descriptor(DescriptorProvider):
     """
     Represents a single descriptor for an interface. See Bindings.conf.
     """
     def __init__(self, config, interface, desc):
         DescriptorProvider.__init__(self, config, desc.get('workers', False))
         self.interface = interface
 
+        if self.workers:
+            assert 'wantsXrays' not in desc
+            self.wantsXrays = False
+        else:
+            self.wantsXrays = desc.get('wantsXrays', True)
+
         # Read the desc, and fill in the relevant defaults.
         ifaceName = self.interface.identifier.name
         if self.interface.isExternal():
             assert not self.workers
             nativeTypeDefault = "nsIDOM" + ifaceName
         elif self.interface.isCallback():
             nativeTypeDefault = "mozilla::dom::" + ifaceName
         else:
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -28,27 +28,32 @@ DefineStaticJSVals(JSContext* cx)
   return InternJSString(cx, s_length_id, "length");
 }
 
 const char DOMProxyHandler::family = 0;
 
 js::DOMProxyShadowsResult
 DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
 {
+  JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
   JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
-  if (v.isObject()) {
+  bool isOverrideBuiltins = !v.isObject() && !v.isUndefined();
+  if (expando) {
     bool hasOwn;
-    Rooted<JSObject*> object(cx, &v.toObject());
-    if (!JS_AlreadyHasOwnPropertyById(cx, object, id, &hasOwn))
+    if (!JS_AlreadyHasOwnPropertyById(cx, expando, id, &hasOwn))
       return js::ShadowCheckFailed;
 
-    return hasOwn ? js::Shadows : js::DoesntShadow;
+    if (hasOwn) {
+      return isOverrideBuiltins ?
+        js::ShadowsViaIndirectExpando : js::ShadowsViaDirectExpando;
+    }
   }
 
-  if (v.isUndefined()) {
+  if (!isOverrideBuiltins) {
+    // Our expando, if any, didn't shadow, so we're not shadowing at all.
     return js::DoesntShadow;
   }
 
   bool hasOwn;
   if (!GetProxyHandler(proxy)->hasOwn(cx, proxy, id, &hasOwn))
     return js::ShadowCheckFailed;
 
   return hasOwn ? js::Shadows : js::DoesntShadowUnique;
--- a/dom/bindings/JSSlots.h
+++ b/dom/bindings/JSSlots.h
@@ -21,13 +21,12 @@
 // Specific objects may have more for storing cached values.
 #define DOM_INSTANCE_RESERVED_SLOTS 1
 
 // Interface objects store a number of reserved slots equal to
 // DOM_INTERFACE_SLOTS_BASE + number of named constructors.
 #define DOM_INTERFACE_SLOTS_BASE 0
 
 // Interface prototype objects store a number of reserved slots equal to
-// DOM_INTERFACE_PROTO_SLOTS_BASE or DOM_INTERFACE_PROTO_SLOTS_BASE + 1 if a
-// slot for the unforgeable holder is needed.
+// DOM_INTERFACE_PROTO_SLOTS_BASE.
 #define DOM_INTERFACE_PROTO_SLOTS_BASE 0
 
 #endif /* mozilla_dom_DOMSlots_h */
--- a/dom/bindings/test/mochitest.ini
+++ b/dom/bindings/test/mochitest.ini
@@ -53,9 +53,10 @@ skip-if = debug == false
 [test_traceProtos.html]
 [test_sequence_detection.html]
 skip-if = debug == false
 [test_exception_options_from_jsimplemented.html]
 skip-if = debug == false
 [test_promise_rejections_from_jsimplemented.html]
 skip-if = debug == false
 [test_worker_UnwrapArg.html]
+[test_unforgeablesonexpando.html]
 [test_crossOriginWindowSymbolAccess.html]
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_unforgeablesonexpando.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for making sure named getters don't override the unforgeable location on HTMLDocument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<img name="location">
+<script>
+test(function() {
+  assert_equals(document.location, window.location,
+                'The <img name="location"> should not override the location getter');
+}, "document.location is the right thing");
+test(function() {
+  var doc = new DOMParser().parseFromString("<img name='location'>", "text/html");
+  assert_equals(doc.location, null,
+                'The <img name="location"> should not override the location getter on a data document');
+}, "document.location is the right thing on non-rendered document");
+</script>
--- a/dom/canvas/test/_webgl-conformance.ini
+++ b/dom/canvas/test/_webgl-conformance.ini
@@ -1,15 +1,15 @@
 # This is a GENERATED FILE. Do not edit it directly.
-# Regenerated it by using `python generate-wrapper-and-manifest.py`.
+# Regenerated it by using `python generate-wrappers-and-manifest.py`.
 # Mark skipped tests in mochitest-errata.ini.
 # Mark failing tests in mochi-single.html.
 
 [DEFAULT]
-skip-if = e10s || os == 'b2g' || ((os == 'linux') && (buildapp == 'b2g'))
+skip-if = e10s || os == 'b2g' || ((os == 'linux') && (buildapp == 'b2g')) || ((os == 'linux') && (buildapp == 'mulet')) # Bug 1136181 disabled on B2G Desktop and Mulet for intermittent failures
 
 support-files = webgl-conformance/../webgl-mochitest/driver-info.js
                 webgl-conformance/always-fail.html
                 webgl-conformance/conformance/00_readme.txt
                 webgl-conformance/conformance/00_test_list.txt
                 webgl-conformance/conformance/LICENSE_CHROMIUM
                 webgl-conformance/conformance/attribs/00_test_list.txt
                 webgl-conformance/conformance/attribs/gl-enable-vertex-attrib.html
--- a/dom/canvas/test/webgl-conformance/generate-wrappers-and-manifest.py
+++ b/dom/canvas/test/webgl-conformance/generate-wrappers-and-manifest.py
@@ -31,17 +31,17 @@ EXTRA_SUPPORT_FILES = [
 
 ACCEPTABLE_ERRATA_KEYS = set([
   'skip-if',
   'fail-if',
 ])
 
 GENERATED_HEADER = '''
 # This is a GENERATED FILE. Do not edit it directly.
-# Regenerated it by using `python generate-wrapper-and-manifest.py`.
+# Regenerated it by using `python generate-wrappers-and-manifest.py`.
 # Mark skipped tests in mochitest-errata.ini.
 # Mark failing tests in mochi-single.html.
 '''.strip()
 
 ########################################################################
 # GetTestList
 
 def GetTestList():
--- a/dom/canvas/test/webgl-conformance/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conformance/mochitest-errata.ini
@@ -1,16 +1,17 @@
 # See python/mozbuild/mozbuild/mozinfo.py for incoming data.
 
 [DEFAULT]
 # No e10s yet.
 # 'B2G Desktop Linux' fails to create WebGL contexts.
 # Also skip B2G for now, until we get a handle on the longer tail of emulator
 # bugs.
-skip-if = e10s || os == 'b2g' || ((os == 'linux') && (buildapp == 'b2g'))
+# Bug 1136181 disabled on B2G Desktop and Mulet for intermittent failures
+skip-if = e10s || os == 'b2g' || ((os == 'linux') && (buildapp == 'b2g')) || ((os == 'linux') && (buildapp == 'mulet'))
 
 ########################################################################
 # All
 #[_wrappers/test_always-fail.html]
 #fail-if = 1
 # We'll be able to use `fail-if` after bug 987849.
 
 ########################################################################
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -26,17 +26,16 @@ using class IPC::Principal from "mozilla
 using class mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
 using struct gfxSize from "gfxPoint.h";
 using CSSRect from "Units.h";
 using LayoutDeviceIntRect from "Units.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::ZoomConstraints from "FrameMetrics.h";
 using FrameMetrics::ViewID from "FrameMetrics.h";
-using mozilla::layout::ScrollingBehavior from "mozilla/layout/RenderFrameUtils.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
 using nscolor from "nsColor.h";
 using class mozilla::WidgetCompositionEvent from "ipc/nsGUIEventIPC.h";
 using struct mozilla::widget::IMENotification from "nsIWidget.h";
 using struct nsIMEUpdatePreference from "nsIWidget.h";
 using struct nsIntPoint from "nsPoint.h";
 using struct nsIntRect from "nsRect.h";
@@ -469,18 +468,17 @@ parent:
      * compositing.  This is sent when all pending changes have been
      * sent to the compositor and are ready to be shown on the next composite.
      * @see PCompositor
      * @see RequestNotifyAfterRemotePaint
      */
     async RemotePaintIsReady();
 
     sync GetRenderFrameInfo(PRenderFrame aRenderFrame)
-        returns (ScrollingBehavior scrolling,
-                 TextureFactoryIdentifier textureFactoryIdentifier,
+        returns (TextureFactoryIdentifier textureFactoryIdentifier,
                  uint64_t layersId);
 
     /**
      * Sent by the child to the parent to inform it that an update to the
      * dimensions has been requested, likely through win.moveTo or resizeTo
      */
     async SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, int32_t aCx, int32_t aCy);
 
@@ -491,17 +489,16 @@ child:
      * to trigger creation of the remote browser's "widget".
      *
      * |Show()| and |Move()| take IntSizes rather than Rects because
      * content processes always render to a virtual <0, 0> top-left
      * point.
      */
     Show(nsIntSize size,
          ShowInfo info,
-         ScrollingBehavior scrolling,
          TextureFactoryIdentifier textureFactoryIdentifier,
          uint64_t layersId,
          nullable PRenderFrame renderFrame,
          bool parentIsActive);
 
     LoadURL(nsCString uri, BrowserConfiguration config);
 
     CacheFileDescriptor(nsString path, FileDescriptor fd);
--- a/dom/ipc/PTabContext.ipdlh
+++ b/dom/ipc/PTabContext.ipdlh
@@ -2,18 +2,16 @@
 /* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
 /* 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 protocol PBrowser;
 include PBrowserOrId;
 
-using mozilla::layout::ScrollingBehavior from "mozilla/layout/RenderFrameUtils.h";
-
 namespace mozilla {
 namespace dom {
 
 // An IPCTabContext which corresponds to a PBrowser opened by a child when it
 // receives window.open().
 //
 // If isBrowserElement is false, this PopupIPCTabContext corresponds to an app
 // frame, and the frame's app-id and app-frame-owner-app-id will be equal to the
@@ -65,13 +63,12 @@ union IPCTabAppBrowserContext
   PopupIPCTabContext;
   AppFrameIPCTabContext;
   BrowserFrameIPCTabContext;
   VanillaFrameIPCTabContext;
 };
 
 struct IPCTabContext {
   IPCTabAppBrowserContext appBrowserContext;
-  ScrollingBehavior scrollingBehavior;
 };
 
 }
 }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -262,17 +262,17 @@ CSSToScreenScale ConvertScaleForRoot(CSS
 }
 CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale) {
   return ViewTargetAs<ParentLayerPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
 }
 
 bool
 TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
 {
-  if (!IsAsyncPanZoomEnabled()) {
+  if (!gfxPrefs::AsyncPanZoomEnabled()) {
     return false;
   }
 
   TABC_LOG("HandlePossibleViewportChange aOldScreenSize=%s mInnerSize=%s\n",
     Stringify(aOldScreenSize).c_str(), Stringify(mInnerSize).c_str());
 
   nsCOMPtr<nsIDocument> document(GetDocument());
   nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
@@ -551,22 +551,16 @@ TabChildBase::ProcessUpdateFrame(const F
         data.AppendFloat(cssCompositedSize.height);
         data.AppendLiteral(" }");
     data.AppendLiteral(" }");
 
     DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
     return newMetrics;
 }
 
-bool
-TabChildBase::IsAsyncPanZoomEnabled()
-{
-    return mScrolling == ASYNC_PAN_ZOOM;
-}
-
 NS_IMETHODIMP
 ContentListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   RemoteDOMEvent remoteEvent;
   remoteEvent.mEvent = do_QueryInterface(aEvent);
   NS_ENSURE_STATE(remoteEvent.mEvent);
   mTabChild->SendEvent(remoteEvent);
   return NS_OK;
@@ -902,17 +896,17 @@ TabChild::Observe(nsISupports *aSubject,
         CSSRect rect;
         sscanf(NS_ConvertUTF16toUTF8(aData).get(),
                "{\"x\":%f,\"y\":%f,\"w\":%f,\"h\":%f}",
                &rect.x, &rect.y, &rect.width, &rect.height);
         SendZoomToRect(presShellId, viewId, rect);
       }
     }
   } else if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) {
-    if (IsAsyncPanZoomEnabled()) {
+    if (gfxPrefs::AsyncPanZoomEnabled()) {
       nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject));
       nsCOMPtr<nsIDocument> doc(GetDocument());
 
       if (SameCOMIdentity(subject, doc)) {
         nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
         utils->SetIsFirstPaint(true);
 
         mContentDocumentIsDisplayed = true;
@@ -957,17 +951,17 @@ TabChild::OnProgressChange(nsIWebProgres
 }
 
 NS_IMETHODIMP
 TabChild::OnLocationChange(nsIWebProgress* aWebProgress,
                            nsIRequest* aRequest,
                            nsIURI *aLocation,
                            uint32_t aFlags)
 {
-  if (!IsAsyncPanZoomEnabled()) {
+  if (!gfxPrefs::AsyncPanZoomEnabled()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMWindow> window;
   aWebProgress->GetDOMWindow(getter_AddRefs(window));
   if (!window) {
     return NS_OK;
   }
@@ -1432,17 +1426,17 @@ TabChild::ProvideWindowCommon(nsIDOMWind
   // We must use PopupIPCTabContext here; ContentParent will not accept the
   // result of this->AsIPCTabContext() (which will be a
   // BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security
   // reasons.
   PopupIPCTabContext context;
   context.opener() = openerTabId;
   context.isBrowserElement() = IsBrowserElement();
 
-  IPCTabContext ipcContext(context, mScrolling);
+  IPCTabContext ipcContext(context);
 
   TabId tabId;
   cc->SendAllocateTabId(openerTabId,
                         ipcContext,
                         cc->GetID(),
                         &tabId);
 
   nsRefPtr<TabChild> newChild = new TabChild(ContentChild::GetSingleton(), tabId,
@@ -1450,17 +1444,17 @@ TabChild::ProvideWindowCommon(nsIDOMWind
   if (NS_FAILED(newChild->Init())) {
     return NS_ERROR_ABORT;
   }
 
   context.opener() = this;
   unused << Manager()->SendPBrowserConstructor(
       // We release this ref in DeallocPBrowserChild
       nsRefPtr<TabChild>(newChild).forget().take(),
-      tabId, IPCTabContext(context, mScrolling), aChromeFlags,
+      tabId, IPCTabContext(context), aChromeFlags,
       cc->GetID(), cc->IsForApp(), cc->IsForBrowser());
 
   nsAutoCString spec;
   if (aURI) {
     aURI->GetSpec(spec);
   }
 
   NS_ConvertUTF8toUTF16 url(spec);
@@ -1512,32 +1506,30 @@ TabChild::ProvideWindowCommon(nsIDOMWind
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
   if (!*aWindowIsNew) {
     PBrowserChild::Send__delete__(newChild);
     return NS_ERROR_ABORT;
   }
 
-  ScrollingBehavior scrolling = DEFAULT_SCROLLING;
   TextureFactoryIdentifier textureFactoryIdentifier;
   uint64_t layersId = 0;
   PRenderFrameChild* renderFrame = newChild->SendPRenderFrameConstructor();
   newChild->SendGetRenderFrameInfo(renderFrame,
-                                   &scrolling,
                                    &textureFactoryIdentifier,
                                    &layersId);
   if (layersId == 0) { // if renderFrame is invalid.
     PRenderFrameChild::Send__delete__(renderFrame);
     renderFrame = nullptr;
   }
 
   // Unfortunately we don't get a window unless we've shown the frame.  That's
   // pretty bogus; see bug 763602.
-  newChild->DoFakeShow(scrolling, textureFactoryIdentifier, layersId, renderFrame);
+  newChild->DoFakeShow(textureFactoryIdentifier, layersId, renderFrame);
 
   for (size_t i = 0; i < frameScripts.Length(); i++) {
     FrameScriptInfo& info = frameScripts[i];
     if (!newChild->RecvLoadRemoteScript(info.url(), info.runInGlobalScope())) {
       MOZ_CRASH();
     }
   }
 
@@ -1849,23 +1841,22 @@ TabChild::CancelCachedFileDescriptorCall
     // No need to hold the callback any longer.
     info->mCallback = nullptr;
 
     // Set this flag so that we will close the file descriptor when it arrives.
     info->mCanceled = true;
 }
 
 void
-TabChild::DoFakeShow(const ScrollingBehavior& aScrolling,
-                     const TextureFactoryIdentifier& aTextureFactoryIdentifier,
+TabChild::DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                      const uint64_t& aLayersId,
                      PRenderFrameChild* aRenderFrame)
 {
   ShowInfo info(EmptyString(), false, false, 0, 0);
-  RecvShow(nsIntSize(0, 0), info, aScrolling, aTextureFactoryIdentifier,
+  RecvShow(nsIntSize(0, 0), info, aTextureFactoryIdentifier,
            aLayersId, aRenderFrame, mParentIsActive);
   mDidFakeShow = true;
 }
 
 void
 TabChild::ApplyShowInfo(const ShowInfo& aInfo)
 {
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
@@ -1955,17 +1946,16 @@ TabChild::MaybeRequestPreinitCamera()
 
     observerService->NotifyObservers(nullptr, "init-camera-hw", nullptr);
 }
 #endif
 
 bool
 TabChild::RecvShow(const nsIntSize& aSize,
                    const ShowInfo& aInfo,
-                   const ScrollingBehavior& aScrolling,
                    const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                    const uint64_t& aLayersId,
                    PRenderFrameChild* aRenderFrame,
                    const bool& aParentIsActive)
 {
     MOZ_ASSERT((!mDidFakeShow && aRenderFrame) || (mDidFakeShow && !aRenderFrame));
 
     if (mDidFakeShow) {
@@ -1975,17 +1965,17 @@ TabChild::RecvShow(const nsIntSize& aSiz
     }
 
     nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
     if (!baseWindow) {
         NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
         return false;
     }
 
-    if (!InitRenderingState(aScrolling, aTextureFactoryIdentifier, aLayersId, aRenderFrame)) {
+    if (!InitRenderingState(aTextureFactoryIdentifier, aLayersId, aRenderFrame)) {
         // We can fail to initialize our widget if the <browser
         // remote> has already been destroyed, and we couldn't hook
         // into the parent-process's layer system.  That's not a fatal
         // error.
         return true;
     }
 
     baseWindow->SetVisibility(true);
@@ -2172,27 +2162,27 @@ TabChild::RecvRealMouseButtonEvent(const
   return true;
 }
 
 bool
 TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
                               const ScrollableLayerGuid& aGuid,
                               const uint64_t& aInputBlockId)
 {
-  if (IsAsyncPanZoomEnabled()) {
+  if (gfxPrefs::AsyncPanZoomEnabled()) {
     nsCOMPtr<nsIDocument> document(GetDocument());
     APZCCallbackHelper::SendSetTargetAPZCNotification(WebWidget(), document, aEvent, aGuid,
         aInputBlockId, mSetTargetAPZCCallback);
   }
 
   WidgetWheelEvent event(aEvent);
   event.widget = mWidget;
   APZCCallbackHelper::DispatchWidgetEvent(event);
 
-  if (IsAsyncPanZoomEnabled()) {
+  if (gfxPrefs::AsyncPanZoomEnabled()) {
     mAPZEventState->ProcessWheelEvent(event, aGuid, aInputBlockId);
   }
   return true;
 }
 
 static Touch*
 GetTouchForIdentifier(const WidgetTouchEvent& aEvent, int32_t aId)
 {
@@ -2356,26 +2346,26 @@ TabChild::RecvRealTouchEvent(const Widge
   TABC_LOG("Receiving touch event of type %d\n", aEvent.message);
 
   WidgetTouchEvent localEvent(aEvent);
   localEvent.widget = mWidget;
 
   APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
       mWidget->GetDefaultScale(), GetPresShellResolution());
 
-  if (localEvent.message == NS_TOUCH_START && IsAsyncPanZoomEnabled()) {
+  if (localEvent.message == NS_TOUCH_START && gfxPrefs::AsyncPanZoomEnabled()) {
     nsCOMPtr<nsIDocument> document = GetDocument();
     APZCCallbackHelper::SendSetTargetAPZCNotification(WebWidget(), document,
         localEvent, aGuid, aInputBlockId, mSetTargetAPZCCallback);
   }
 
   // Dispatch event to content (potentially a long-running operation)
   nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
 
-  if (!IsAsyncPanZoomEnabled()) {
+  if (!gfxPrefs::AsyncPanZoomEnabled()) {
     UpdateTapState(localEvent, status);
     return true;
   }
 
   mAPZEventState->ProcessTouchEvent(localEvent, aGuid, aInputBlockId);
   return true;
 }
 
@@ -2788,31 +2778,29 @@ TabChild::InitTabChildGlobal(FrameScript
       RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
     }
   }
 
   return true;
 }
 
 bool
-TabChild::InitRenderingState(const ScrollingBehavior& aScrolling,
-                             const TextureFactoryIdentifier& aTextureFactoryIdentifier,
+TabChild::InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                              const uint64_t& aLayersId,
                              PRenderFrameChild* aRenderFrame)
 {
     static_cast<PuppetWidget*>(mWidget.get())->InitIMEState();
 
     RenderFrameChild* remoteFrame = static_cast<RenderFrameChild*>(aRenderFrame);
     if (!remoteFrame) {
         NS_WARNING("failed to construct RenderFrame");
         return false;
     }
 
     MOZ_ASSERT(aLayersId != 0);
-    mScrolling = aScrolling;
     mTextureFactoryIdentifier = aTextureFactoryIdentifier;
 
     // Pushing layers transactions directly to a separate
     // compositor context.
     PCompositorChild* compositorChild = CompositorChild::Get();
     if (!compositorChild) {
       NS_WARNING("failed to get CompositorChild instance");
       PRenderFrameChild::Send__delete__(remoteFrame);
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -172,17 +172,16 @@ public:
     TabChildBase();
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TabChildBase)
 
     virtual nsIWebNavigation* WebNavigation() const = 0;
     virtual nsIWidget* WebWidget() = 0;
     nsIPrincipal* GetPrincipal() { return mPrincipal; }
-    bool IsAsyncPanZoomEnabled();
     // Recalculates the display state, including the CSS
     // viewport. This should be called whenever we believe the
     // viewport data on a document may have changed. If it didn't
     // change, this function doesn't do anything.  However, it should
     // not be called all the time as it is fairly expensive.
     bool HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize);
     virtual bool DoUpdateZoomConstraints(const uint32_t& aPresShellId,
                                          const mozilla::layers::FrameMetrics::ViewID& aViewId,
@@ -217,17 +216,16 @@ protected:
     bool UpdateFrameHandler(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
 protected:
     CSSSize mOldViewportSize;
     bool mContentDocumentIsDisplayed;
     nsRefPtr<TabChildGlobal> mTabChildGlobal;
     ScreenIntSize mInnerSize;
     mozilla::layers::FrameMetrics mLastRootMetrics;
-    mozilla::layout::ScrollingBehavior mScrolling;
     nsCOMPtr<nsIWebBrowserChrome3> mWebBrowserChrome;
 };
 
 class TabChild MOZ_FINAL : public TabChildBase,
                            public PBrowserChild,
                            public nsIWebBrowserChrome2,
                            public nsIEmbeddingSiteWindow,
                            public nsIWebBrowserChromeFocus,
@@ -238,17 +236,16 @@ class TabChild MOZ_FINAL : public TabChi
                            public nsSupportsWeakReference,
                            public nsITabChild,
                            public nsIObserver,
                            public TabContext,
                            public nsITooltipListener
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::layout::RenderFrameChild RenderFrameChild;
-    typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
     typedef mozilla::layers::APZEventState APZEventState;
     typedef mozilla::layers::SetTargetAPZCCallback SetTargetAPZCCallback;
 
 public:
     /**
      * Find TabChild of aTabId in the same content process of the
      * caller.
      */
@@ -308,17 +305,16 @@ public:
                                          const ZoomConstraints& aConstraints) MOZ_OVERRIDE;
     virtual bool RecvLoadURL(const nsCString& aURI,
                              const BrowserConfiguration& aConfiguration) MOZ_OVERRIDE;
     virtual bool RecvCacheFileDescriptor(const nsString& aPath,
                                          const FileDescriptor& aFileDescriptor)
                                          MOZ_OVERRIDE;
     virtual bool RecvShow(const nsIntSize& aSize,
                           const ShowInfo& aInfo,
-                          const ScrollingBehavior& aScrolling,
                           const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                           const uint64_t& aLayersId,
                           PRenderFrameChild* aRenderFrame,
                           const bool& aParentIsActive) MOZ_OVERRIDE;
     virtual bool RecvUpdateDimensions(const nsIntRect& rect,
                                       const nsIntSize& size,
                                       const ScreenOrientation& orientation,
                                       const nsIntPoint& chromeDisp) MOZ_OVERRIDE;
@@ -532,26 +528,24 @@ private:
     // You should call this after calling TabContext::SetTabContext().  We also
     // call this during Init().
     void NotifyTabContextUpdated();
 
     void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS };
     bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS);
-    bool InitRenderingState(const ScrollingBehavior& aScrolling,
-                            const TextureFactoryIdentifier& aTextureFactoryIdentifier,
+    bool InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                             const uint64_t& aLayersId,
                             PRenderFrameChild* aRenderFrame);
     void DestroyWindow();
     void SetProcessNameToAppName();
 
     // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
-    void DoFakeShow(const ScrollingBehavior& aScrolling,
-                    const TextureFactoryIdentifier& aTextureFactoryIdentifier,
+    void DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                     const uint64_t& aLayersId,
                     PRenderFrameChild* aRenderFrame);
 
     void ApplyShowInfo(const ShowInfo& aInfo);
 
     // These methods are used for tracking synthetic mouse events
     // dispatched for compatibility.  On each touch event, we
     // UpdateTapState().  If we've detected that the current gesture
--- a/dom/ipc/TabContext.cpp
+++ b/dom/ipc/TabContext.cpp
@@ -19,17 +19,16 @@ using namespace mozilla::layout;
 
 namespace mozilla {
 namespace dom {
 
 TabContext::TabContext()
   : mInitialized(false)
   , mOwnAppId(NO_APP_ID)
   , mContainingAppId(NO_APP_ID)
-  , mScrollingBehavior(DEFAULT_SCROLLING)
   , mIsBrowser(false)
 {
 }
 
 bool
 TabContext::IsBrowserElement() const
 {
   return mIsBrowser;
@@ -151,18 +150,17 @@ TabContext::SetTabContext(const TabConte
   *this = aContext;
   mInitialized = true;
 
   return true;
 }
 
 bool
 TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp,
-                                     mozIApplication* aAppFrameOwnerApp,
-                                     ScrollingBehavior aRequestedBehavior)
+                                     mozIApplication* aAppFrameOwnerApp)
 {
   NS_ENSURE_FALSE(mInitialized, false);
 
   // Get ids for both apps and only write to our member variables after we've
   // verified that this worked.
   uint32_t ownAppId = NO_APP_ID;
   if (aOwnApp) {
     nsresult rv = aOwnApp->GetLocalId(&ownAppId);
@@ -176,64 +174,58 @@ TabContext::SetTabContextForAppFrame(moz
     NS_ENSURE_SUCCESS(rv, false);
     NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
   }
 
   mInitialized = true;
   mIsBrowser = false;
   mOwnAppId = ownAppId;
   mContainingAppId = containingAppId;
-  mScrollingBehavior = aRequestedBehavior;
   mOwnApp = aOwnApp;
   mContainingApp = aAppFrameOwnerApp;
   return true;
 }
 
 bool
-TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp,
-                                         ScrollingBehavior aRequestedBehavior)
+TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
 {
   NS_ENSURE_FALSE(mInitialized, false);
 
   uint32_t containingAppId = NO_APP_ID;
   if (aBrowserFrameOwnerApp) {
     nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId);
     NS_ENSURE_SUCCESS(rv, false);
     NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
   }
 
   mInitialized = true;
   mIsBrowser = true;
   mOwnAppId = NO_APP_ID;
   mContainingAppId = containingAppId;
-  mScrollingBehavior = aRequestedBehavior;
   mContainingApp = aBrowserFrameOwnerApp;
   return true;
 }
 
 bool
-TabContext::SetTabContextForNormalFrame(ScrollingBehavior aRequestedBehavior)
+TabContext::SetTabContextForNormalFrame()
 {
   NS_ENSURE_FALSE(mInitialized, false);
 
   mInitialized = true;
-  mScrollingBehavior = aRequestedBehavior;
   return true;
 }
 
 IPCTabContext
 TabContext::AsIPCTabContext() const
 {
   if (mIsBrowser) {
-    return IPCTabContext(BrowserFrameIPCTabContext(mContainingAppId),
-                         mScrollingBehavior);
+    return IPCTabContext(BrowserFrameIPCTabContext(mContainingAppId));
   }
 
-  return IPCTabContext(AppFrameIPCTabContext(mOwnAppId, mContainingAppId),
-                       mScrollingBehavior);
+  return IPCTabContext(AppFrameIPCTabContext(mOwnAppId, mContainingAppId));
 }
 
 static already_AddRefed<mozIApplication>
 GetAppForId(uint32_t aAppId)
 {
   nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(appsService, nullptr);
 
@@ -337,22 +329,20 @@ MaybeInvalidTabContext::MaybeInvalidTabC
   nsCOMPtr<mozIApplication> containingApp = GetAppForId(containingAppId);
   if ((containingApp == nullptr) != (containingAppId == NO_APP_ID)) {
     mInvalidReason = "Got a containingAppId that didn't correspond to an app.";
     return;
   }
 
   bool rv;
   if (isBrowser) {
-    rv = mTabContext.SetTabContextForBrowserFrame(containingApp,
-                                                  aParams.scrollingBehavior());
+    rv = mTabContext.SetTabContextForBrowserFrame(containingApp);
   } else {
     rv = mTabContext.SetTabContextForAppFrame(ownApp,
-                                              containingApp,
-                                              aParams.scrollingBehavior());
+                                              containingApp);
   }
 
   if (!rv) {
     mInvalidReason = "Couldn't initialize TabContext.";
   }
 }
 
 bool
--- a/dom/ipc/TabContext.h
+++ b/dom/ipc/TabContext.h
@@ -2,17 +2,16 @@
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_TabContext_h
 #define mozilla_dom_TabContext_h
 
-#include "mozilla/layout/RenderFrameUtils.h"
 #include "mozIApplication.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace dom {
 
 class IPCTabContext;
 
@@ -25,19 +24,16 @@ class IPCTabContext;
  * standalone TabContext objects.
  *
  * This class is immutable except by calling one of the protected
  * SetTabContext*() methods (and those methods can only be called once).  See
  * also MutableTabContext.
  */
 class TabContext
 {
-protected:
-  typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
-
 public:
   TabContext();
 
   /* (The implicit copy-constructor and operator= are fine.) */
 
   /**
    * Generates IPCTabContext of type BrowserFrameIPCTabContext or
    * AppFrameIPCTabContext from this TabContext's information.
@@ -101,21 +97,16 @@ public:
    * OwnOrContainingAppId() gets the ID of this frame, if HasOwnApp().  If this
    * frame does not have its own app, it gets the ID of the app which contains
    * this frame (i.e., the result of {Browser,App}OwnerAppId(), as applicable).
    */
   uint32_t OwnOrContainingAppId() const;
   already_AddRefed<mozIApplication> GetOwnOrContainingApp() const;
   bool HasOwnOrContainingApp() const;
 
-  /**
-   * Return the requested scrolling behavior for this frame.
-   */
-  ScrollingBehavior GetScrollingBehavior() const { return mScrollingBehavior; }
-
 protected:
   friend class MaybeInvalidTabContext;
 
   /**
    * These protected mutator methods let you modify a TabContext once.  Further
    * attempts to modify a given TabContext will fail (the method will return
    * false).
    *
@@ -128,30 +119,28 @@ protected:
    */
   bool SetTabContext(const TabContext& aContext);
 
   /**
    * Set this TabContext to be an app frame (with the given own app) inside the
    * given app.  Either or both apps may be null.
    */
   bool SetTabContextForAppFrame(mozIApplication* aOwnApp,
-                                mozIApplication* aAppFrameOwnerApp,
-                                ScrollingBehavior aRequestedBehavior);
+                                mozIApplication* aAppFrameOwnerApp);
 
   /**
    * Set this TabContext to be a browser frame inside the given app (which may
    * be null).
    */
-  bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp,
-                                    ScrollingBehavior aRequestedBehavior);
+  bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp);
 
   /**
    * Set this TabContext to be a normal non-browser non-app frame.
    */
-  bool SetTabContextForNormalFrame(ScrollingBehavior aRequestedBehavior);
+  bool SetTabContextForNormalFrame();
 
 private:
   /**
    * Has this TabContext been initialized?  If so, mutator methods will fail.
    */
   bool mInitialized;
 
   /**
@@ -174,21 +163,16 @@ private:
   nsCOMPtr<mozIApplication> mContainingApp;
 
   /*
    * Cache of mContainingApp->GetLocalId().
    */
   uint32_t mContainingAppId;
 
   /**
-   * The requested scrolling behavior for this frame.
-   */
-  ScrollingBehavior mScrollingBehavior;
-
-  /**
    * Does this TabContext correspond to a browser element?
    *
    * If this is true, mOwnApp must be null.
    */
   bool mIsBrowser;
 };
 
 /**
@@ -199,33 +183,30 @@ private:
 class MutableTabContext : public TabContext
 {
 public:
   bool SetTabContext(const TabContext& aContext)
   {
     return TabContext::SetTabContext(aContext);
   }
 
-  bool SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication* aAppFrameOwnerApp,
-                                ScrollingBehavior aRequestedBehavior)
+  bool SetTabContextForAppFrame(mozIApplication* aOwnApp,
+                                mozIApplication* aAppFrameOwnerApp)
   {
-    return TabContext::SetTabContextForAppFrame(aOwnApp, aAppFrameOwnerApp,
-                                                aRequestedBehavior);
+    return TabContext::SetTabContextForAppFrame(aOwnApp, aAppFrameOwnerApp);
   }
 
-  bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp,
-                                    ScrollingBehavior aRequestedBehavior)
+  bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
   {
-    return TabContext::SetTabContextForBrowserFrame(aBrowserFrameOwnerApp,
-                                                    aRequestedBehavior);
+    return TabContext::SetTabContextForBrowserFrame(aBrowserFrameOwnerApp);
   }
 
-  bool SetTabContextForNormalFrame(ScrollingBehavior aRequestedBehavior)
+  bool SetTabContextForNormalFrame()
   {
-    return TabContext::SetTabContextForNormalFrame(aRequestedBehavior);
+    return TabContext::SetTabContextForNormalFrame();
   }
 };
 
 /**
  * MaybeInvalidTabContext is a simple class that lets you transform an
  * IPCTabContext into a TabContext.
  *
  * The issue is that an IPCTabContext is not necessarily valid; for example, it
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -800,31 +800,29 @@ TabParent::Show(const nsIntSize& size, b
 {
     // sigh
     mShown = true;
     mDimensions = size;
     if (mIsDestroyed) {
         return;
     }
 
-    ScrollingBehavior scrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
     TextureFactoryIdentifier textureFactoryIdentifier;
     uint64_t layersId = 0;
     bool success = false;
     RenderFrameParent* renderFrame = nullptr;
     // If TabParent is initialized by parent side then the RenderFrame must also
     // be created here. If TabParent is initialized by child side,
     // child side will create RenderFrame.
     MOZ_ASSERT(!GetRenderFrame());
     if (IsInitedByParent()) {
         nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
         if (frameLoader) {
           renderFrame =
               new RenderFrameParent(frameLoader,
-                                    scrolling,
                                     &textureFactoryIdentifier,
                                     &layersId,
                                     &success);
           MOZ_ASSERT(success);
           AddTabParentToTable(layersId, this);
           unused << SendPRenderFrameConstructor(renderFrame);
         }
     }
@@ -837,17 +835,17 @@ TabParent::Show(const nsIntSize& size, b
       mFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
       bool allowFullscreen =
         mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
         mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen);
       bool isPrivate = mFrameElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing);
       info = ShowInfo(name, allowFullscreen, isPrivate, mDPI, mDefaultScale.scale);
     }
 
-    unused << SendShow(size, info, scrolling, textureFactoryIdentifier,
+    unused << SendShow(size, info, textureFactoryIdentifier,
                        layersId, renderFrame, aParentIsActive);
 }
 
 bool
 TabParent::RecvSetDimensions(const uint32_t& aFlags,
                              const int32_t& aX, const int32_t& aY,
                              const int32_t& aCx, const int32_t& aCy)
 {
@@ -2329,24 +2327,22 @@ TabParent::DeallocPColorPickerParent(PCo
   return true;
 }
 
 PRenderFrameParent*
 TabParent::AllocPRenderFrameParent()
 {
   MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty());
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
-  ScrollingBehavior scrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
   TextureFactoryIdentifier textureFactoryIdentifier;
   uint64_t layersId = 0;
   bool success = false;
   if(frameLoader) {
     PRenderFrameParent* renderFrame = 
       new RenderFrameParent(frameLoader,
-                            scrolling,
                             &textureFactoryIdentifier,
                             &layersId,
                             &success);
     MOZ_ASSERT(success);
     AddTabParentToTable(layersId, this);
     return renderFrame;
   } else {
     return nullptr;
@@ -2357,22 +2353,20 @@ bool
 TabParent::DeallocPRenderFrameParent(PRenderFrameParent* aFrame)
 {
   delete aFrame;
   return true;
 }
 
 bool
 TabParent::RecvGetRenderFrameInfo(PRenderFrameParent* aRenderFrame,
-                                  ScrollingBehavior* aScrolling,
                                   TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                   uint64_t* aLayersId)
 {
   RenderFrameParent* renderFrame = static_cast<RenderFrameParent*>(aRenderFrame);
-  *aScrolling = renderFrame->UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
   renderFrame->GetTextureFactoryIdentifier(aTextureFactoryIdentifier);
   *aLayersId = renderFrame->GetLayersId();
   return true;
 }
 
 bool
 TabParent::AllowContentIME()
 {
@@ -2424,24 +2418,16 @@ TabParent::GetWidget() const
   nsIFrame *frame = content->GetPrimaryFrame();
   if (!frame)
     return nullptr;
 
   nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
   return widget.forget();
 }
 
-bool
-TabParent::UseAsyncPanZoom()
-{
-  bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
-  return (usingOffMainThreadCompositing && gfxPrefs::AsyncPanZoomEnabled() &&
-          GetScrollingBehavior() == ASYNC_PAN_ZOOM);
-}
-
 void
 TabParent::ApzAwareEventRoutingToChild(ScrollableLayerGuid* aOutTargetGuid,
                                        uint64_t* aOutInputBlockId)
 {
   if (gfxPrefs::AsyncPanZoomEnabled()) {
     if (aOutTargetGuid) {
       *aOutTargetGuid = InputAPZContext::GetTargetLayerGuid();
 
@@ -2613,17 +2599,17 @@ TabParent::InjectTouchEvent(const nsAStr
 
   SendRealTouchEvent(event);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabParent::GetUseAsyncPanZoom(bool* useAsyncPanZoom)
 {
-  *useAsyncPanZoom = UseAsyncPanZoom();
+  *useAsyncPanZoom = gfxPrefs::AsyncPanZoomEnabled();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabParent::SetIsDocShellActive(bool isActive)
 {
   unused << SendSetIsDocShellActive(isActive);
   return NS_OK;
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -61,17 +61,16 @@ struct StructuredCloneData;
 class TabParent : public PBrowserParent 
                 , public nsITabParent 
                 , public nsIAuthPromptProvider
                 , public nsISecureBrowserUI
                 , public nsSupportsWeakReference
                 , public TabContext
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
-    typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
 
     virtual ~TabParent();
 
 public:
     // nsITabParent
     NS_DECL_NSITABPARENT
 
     TabParent(nsIContentParent* aManager,
@@ -395,17 +394,16 @@ protected:
     bool AllowContentIME();
 
     virtual PRenderFrameParent* AllocPRenderFrameParent() MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrameParent(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
 
     virtual bool RecvRemotePaintIsReady() MOZ_OVERRIDE;
 
     virtual bool RecvGetRenderFrameInfo(PRenderFrameParent* aRenderFrame,
-                                        ScrollingBehavior* aScrolling,
                                         TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                         uint64_t* aLayersId) MOZ_OVERRIDE;
 
     virtual bool RecvSetDimensions(const uint32_t& aFlags,
                                    const int32_t& aX, const int32_t& aY,
                                    const int32_t& aCx, const int32_t& aCy) MOZ_OVERRIDE;
 
     bool SendCompositionChangeEvent(mozilla::WidgetCompositionEvent& event);
@@ -448,19 +446,16 @@ protected:
 private:
     already_AddRefed<nsFrameLoader> GetFrameLoader() const;
     layout::RenderFrameParent* GetRenderFrame();
     nsRefPtr<nsIContentParent> mManager;
     void TryCacheDPIAndScale();
 
     CSSPoint AdjustTapToChildWidget(const CSSPoint& aPoint);
 
-    // When true, we create a pan/zoom controller for our frame and
-    // notify it of input events targeting us.
-    bool UseAsyncPanZoom();
     // Update state prior to routing an APZ-aware event to the child process.
     // |aOutTargetGuid| will contain the identifier
     // of the APZC instance that handled the event. aOutTargetGuid may be
     // null.
     // |aOutInputBlockId| will contain the identifier of the input block
     // that this event was added to, if there was one. aOutInputBlockId may
     // be null.
     void ApzAwareEventRoutingToChild(ScrollableLayerGuid* aOutTargetGuid,
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -1280,17 +1280,17 @@ PeerConnectionObserver.prototype = {
     pc._onReplaceTrackSender = null;
     pc._onReplaceTrackSuccess();
   },
 
   onReplaceTrackError: function(code, message) {
     var pc = this._dompc;
     pc._onReplaceTrackWithTrack = null;
     pc._onReplaceTrackSender = null;
-    pc._onReplaceTrackError(this.newError(message, code));
+    pc._onReplaceTrackFailure(this.newError(message, code));
   },
 
   foundIceCandidate: function(cand) {
     this.dispatchEvent(new this._dompc._win.RTCPeerConnectionIceEvent("icecandidate",
                                                                       { candidate: cand } ));
   },
 
   notifyDataChannel: function(channel) {
--- a/dom/media/omx/OmxDecoder.cpp
+++ b/dom/media/omx/OmxDecoder.cpp
@@ -60,17 +60,17 @@ OmxDecoder::OmxDecoder(MediaResource *aR
   mVideoHeight(0),
   mVideoColorFormat(0),
   mVideoStride(0),
   mVideoSliceHeight(0),
   mVideoRotation(0),
   mAudioChannels(-1),
   mAudioSampleRate(-1),
   mDurationUs(-1),
-  mVideoLastFrameTime(-1),
+  mLastSeekTime(-1),
   mVideoBuffer(nullptr),
   mAudioBuffer(nullptr),
   mIsVideoSeeking(false),
   mAudioMetadataRead(false),
   mAudioPaused(false),
   mVideoPaused(false)
 {
   mLooper = new ALooper;
@@ -381,16 +381,20 @@ void OmxDecoder::ReleaseMediaResources()
 
   if (mAudioSource.get()) {
     mAudioSource->stop();
     mAudioSource.clear();
   }
 
   mNativeWindowClient.clear();
   mNativeWindow.clear();
+
+  // Reset this variable to make the first seek go to the previous keyframe
+  // when resuming
+  mLastSeekTime = -1;
 }
 
 bool OmxDecoder::SetVideoFormat() {
   const char *componentName;
 
   if (!mVideoSource->getFormat()->findInt32(kKeyWidth, &mVideoWidth) ||
       !mVideoSource->getFormat()->findInt32(kKeyHeight, &mVideoHeight) ||
       !mVideoSource->getFormat()->findCString(kKeyDecoderComponent, &componentName) ||
@@ -559,22 +563,23 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
       Mutex::Autolock autoLock(mSeekLock);
       ReleaseAllPendingVideoBuffersLocked();
       mIsVideoSeeking = true;
     }
     MediaSource::ReadOptions options;
     MediaSource::ReadOptions::SeekMode seekMode;
     // If the last timestamp of decoded frame is smaller than seekTime,
     // seek to next key frame. Otherwise seek to the previos one.
-    if (mVideoLastFrameTime > aTimeUs || mVideoLastFrameTime == -1) {
+    OD_LOG("SeekTime: %lld, mLastSeekTime:%lld", aTimeUs, mLastSeekTime);
+    if (mLastSeekTime == -1 || mLastSeekTime > aTimeUs) {
       seekMode = MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC;
     } else {
       seekMode = MediaSource::ReadOptions::SEEK_NEXT_SYNC;
     }
-
+    mLastSeekTime = aTimeUs;
     bool findNextBuffer = true;
     while (findNextBuffer) {
       options.setSeekTo(aTimeUs, seekMode);
       findNextBuffer = false;
       if (mIsVideoSeeking) {
         err = mVideoSource->read(&mVideoBuffer, &options);
         Mutex::Autolock autoLock(mSeekLock);
         mIsVideoSeeking = false;
@@ -670,17 +675,16 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
       if (!ToVideoFrame(aFrame, timeUs, data, length, keyFrame)) {
         return false;
       }
     }
     // Check if this frame is valid or not. If not, skip it.
     if ((aKeyframeSkip && timeUs < aTimeUs) || length == 0) {
       aFrame->mShouldSkip = true;
     }
-    mVideoLastFrameTime = timeUs;
   }
   else if (err == INFO_FORMAT_CHANGED) {
     // If the format changed, update our cached info.
     if (!SetVideoFormat()) {
       return false;
     } else {
       return ReadVideo(aFrame, aTimeUs, aKeyframeSkip, aDoSeek);
     }
--- a/dom/media/omx/OmxDecoder.h
+++ b/dom/media/omx/OmxDecoder.h
@@ -55,17 +55,17 @@ class OmxDecoder : public OMXCodecProxy:
   int32_t mVideoHeight;
   int32_t mVideoColorFormat;
   int32_t mVideoStride;
   int32_t mVideoSliceHeight;
   int32_t mVideoRotation;
   int32_t mAudioChannels;
   int32_t mAudioSampleRate;
   int64_t mDurationUs;
-  int64_t mVideoLastFrameTime;
+  int64_t mLastSeekTime;
 
   VideoFrame mVideoFrame;
   AudioFrame mAudioFrame;
   MP3FrameParser mMP3FrameParser;
   bool mIsMp3;
 
   // Lifetime of these should be handled by OMXCodec, as long as we release
   //   them after use: see ReleaseVideoBuffer(), ReleaseAudioBuffer()
--- a/dom/tests/mochitest/webcomponents/test_unresolved_pseudo_class.html
+++ b/dom/tests/mochitest/webcomponents/test_unresolved_pseudo_class.html
@@ -83,17 +83,17 @@ var del = document.querySelector('#del')
 is(getComputedStyle(del).color, "rgb(0, 0, 255)", "del - color");
 var par = del.parentNode;
 par.removeChild(del);
 // Changing is attribute after creation should not change the type
 // of a custom element, even if the element was removed and re-append to the tree.
 del.setAttribute("is", "foobar");
 par.appendChild(del);
 is(getComputedStyle(del).color, "rgb(0, 0, 255)", "del - color (after reappend)");
-var Del = document.registerElement('x-del', { prototype: Object.create(HTMLSpanElement.prototype) });
+var Del = document.registerElement('x-del', { extends: 'span', prototype: Object.create(HTMLSpanElement.prototype) });
 // [is="x-del"] will not match any longer so the rule of span will apply
 is(getComputedStyle(del).color, "rgb(0, 255, 0)", "del - color (after registerElement)");
 // but the element should have been upgraded:
 ok(del instanceof Del, "element was upgraded correctly after changing |is|");
 
 </script>
 </body>
 </html>
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -2292,17 +2292,17 @@ ServiceWorkerManager::DispatchFetchEvent
   nsCOMPtr<nsISupports> serviceWorker;
 
   bool isNavigation = false;
   nsresult rv = aChannel->GetIsNavigation(&isNavigation);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!isNavigation) {
     MOZ_ASSERT(aDoc);
-    rv = GetDocumentController(aDoc->GetWindow(), getter_AddRefs(serviceWorker));
+    rv = GetDocumentController(aDoc->GetInnerWindow(), getter_AddRefs(serviceWorker));
   } else {
     nsCOMPtr<nsIChannel> internalChannel;
     rv = aChannel->GetChannel(getter_AddRefs(internalChannel));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIURI> uri;
     rv = internalChannel->GetURI(getter_AddRefs(uri));
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -911,16 +911,18 @@ GetOrCreateMapEntryForPrototype(JSContex
   const char* name = xpc::IsInContentXBLScope(proto) ? "__ContentClassObjectMap__"
                                                      : "__XBLClassObjectMap__";
 
   // Now, enter the XBL scope, since that's where we need to operate, and wrap
   // the proto accordingly. We hang the map off of the content XBL scope for
   // content, and the Window for chrome (whether add-ons are involved or not).
   JS::Rooted<JSObject*> scope(cx, xpc::GetXBLScopeOrGlobal(cx, proto));
   NS_ENSURE_TRUE(scope, nullptr);
+  MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(scope) == scope);
+
   JS::Rooted<JSObject*> wrappedProto(cx, proto);
   JSAutoCompartment ac(cx, scope);
   if (!JS_WrapObject(cx, &wrappedProto)) {
     return nullptr;
   }
 
   // Grab the appropriate WeakMap.
   JS::Rooted<JSObject*> map(cx, GetOrCreateClassObjectMap(cx, scope, name));
@@ -934,17 +936,17 @@ GetOrCreateMapEntryForPrototype(JSContex
     return nullptr;
   }
   if (val.isObject()) {
     return &val.toObject();
   }
 
   // We don't have an entry. Create one and stick it in the map.
   JS::Rooted<JSObject*> entry(cx);
-  entry = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr(), scope);
+  entry = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr());
   if (!entry) {
     return nullptr;
   }
   JS::Rooted<JS::Value> entryVal(cx, JS::ObjectValue(*entry));
   if (!JS::SetWeakMapEntry(cx, map, wrappedProto, entryVal)) {
     NS_WARNING("SetWeakMapEntry failed, probably due to non-preservable WeakMap "
                "key. XBL binding will fail for this element.");
     return nullptr;
@@ -1008,17 +1010,17 @@ nsXBLBinding::DoInitJSClass(JSContext *c
   if (desc.object()) {
     proto = &desc.value().toObject();
     MOZ_ASSERT(JS_GetClass(js::UncheckedUnwrap(proto)) == &gPrototypeJSClass);
   } else {
 
     // We need to create the prototype. First, enter the compartment where it's
     // going to live, and create it.
     JSAutoCompartment ac2(cx, global);
-    proto = JS_NewObjectWithGivenProto(cx, &gPrototypeJSClass, parent_proto, global);
+    proto = JS_NewObjectWithGivenProto(cx, &gPrototypeJSClass, parent_proto);
     if (!proto) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // Keep this proto binding alive while we're alive.  Do this first so that
     // we can guarantee that in XBLFinalize this will be non-null.
     // Note that we can't just store aProtoBinding in the private and
     // addref/release the nsXBLDocumentInfo through it, because cycle
--- a/dom/xbl/nsXBLProtoImpl.cpp
+++ b/dom/xbl/nsXBLProtoImpl.cpp
@@ -82,16 +82,17 @@ nsXBLProtoImpl::InstallImplementation(ns
 
   // First, start by entering the compartment of the XBL scope. This may or may
   // not be the same compartment as globalObject.
   JSAddonId* addonId = MapURIToAddonID(aPrototypeBinding->BindingURI());
   JS::Rooted<JSObject*> globalObject(cx,
     GetGlobalForObjectCrossCompartment(targetClassObject));
   JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
+  MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(scopeObject) == scopeObject);
   JSAutoCompartment ac(cx, scopeObject);
 
   // Determine the appropriate property holder.
   //
   // Note: If |targetIsNew| is false, we'll early-return above. However, that only
   // tells us if the content-side object is new, which may be the case even if
   // we've already set up the binding on the XBL side. For example, if we apply
   // a binding #foo to a <span> when we've already applied it to a <div>, we'll
@@ -107,17 +108,17 @@ nsXBLProtoImpl::InstallImplementation(ns
   }
   bool propertyHolderIsNew = !existingHolder.object() || !existingHolder.value().isObject();
 
   if (!propertyHolderIsNew) {
     propertyHolder = &existingHolder.value().toObject();
   } else if (scopeObject != globalObject) {
 
     // This is just a property holder, so it doesn't need any special JSClass.
-    propertyHolder = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr(), scopeObject);
+    propertyHolder = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr());
     NS_ENSURE_TRUE(propertyHolder, NS_ERROR_OUT_OF_MEMORY);
 
     // Define it as a property on the scopeObject, using the same name used on
     // the content side.
     bool ok = JS_DefineProperty(cx, scopeObject, className, propertyHolder,
                                 JSPROP_PERMANENT | JSPROP_READONLY,
                                 JS_STUBGETTER, JS_STUBSETTER);
     NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
@@ -240,19 +241,18 @@ nsXBLProtoImpl::CompilePrototypeMembers(
   // We want to pre-compile our implementation's members against a "prototype context". Then when we actually 
   // bind the prototype to a real xbl instance, we'll clone the pre-compiled JS into the real instance's 
   // context.
   AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.Init(xpc::CompilationScope())))
     return NS_ERROR_FAILURE;
   jsapi.TakeOwnershipOfErrorReporting();
   JSContext* cx = jsapi.cx();
-  JS::Rooted<JSObject*> compilationGlobal(cx, xpc::CompilationScope());
 
-  mPrecompiledMemberHolder = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr(), compilationGlobal);
+  mPrecompiledMemberHolder = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr());
   if (!mPrecompiledMemberHolder)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Now that we have a class object installed, we walk our member list and compile each of our
   // properties and methods in turn.
   JS::Rooted<JSObject*> rootedHolder(cx, mPrecompiledMemberHolder);
   for (nsXBLProtoImplMember* curr = mMembers;
        curr;
@@ -361,18 +361,17 @@ nsXBLProtoImpl::DestroyMembers()
 
 nsresult
 nsXBLProtoImpl::Read(nsIObjectInputStream* aStream,
                      nsXBLPrototypeBinding* aBinding)
 {
   AssertInCompilationScope();
   AutoJSContext cx;
   // Set up a class object first so that deserialization is possible
-  JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
-  mPrecompiledMemberHolder = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr(), global);
+  mPrecompiledMemberHolder = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr());
   if (!mPrecompiledMemberHolder)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsXBLProtoImplField* previousField = nullptr;
   nsXBLProtoImplMember* previousMember = nullptr;
 
   do {
     XBLBindingSerializeDetails type;
--- a/editor/libeditor/TypeInState.cpp
+++ b/editor/libeditor/TypeInState.cpp
@@ -81,17 +81,17 @@ NS_IMETHODIMP TypeInState::NotifySelecti
   // XXX: The following code attempts to work around the bogus notifications,
   // XXX: and should probably be removed once bug 140303 is fixed.
   // XXX:
   // XXX: This code temporarily fixes the problem where clicking the mouse in
   // XXX: the same location clears the type-in-state.
   nsRefPtr<Selection> selection = static_cast<Selection*>(aSelection);
 
   if (aSelection) {
-    int32_t rangeCount = selection->GetRangeCount();
+    int32_t rangeCount = selection->RangeCount();
 
     if (selection->Collapsed() && rangeCount) {
       nsCOMPtr<nsIDOMNode> selNode;
       int32_t selOffset = 0;
 
       nsresult result =
         nsEditor::GetStartNodeAndOffset(selection, getter_AddRefs(selNode),
                                         &selOffset);
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -3556,17 +3556,17 @@ nsEditor::GetStartNodeAndOffset(Selectio
 {
   MOZ_ASSERT(aSelection);
   MOZ_ASSERT(aStartNode);
   MOZ_ASSERT(aStartOffset);
 
   *aStartNode = nullptr;
   *aStartOffset = 0;
 
-  NS_ENSURE_TRUE(aSelection->GetRangeCount(), NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(aSelection->RangeCount(), NS_ERROR_FAILURE);
 
   const nsRange* range = aSelection->GetRangeAt(0);
   NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
 
   NS_ENSURE_TRUE(range->IsPositioned(), NS_ERROR_FAILURE);
 
   NS_IF_ADDREF(*aStartNode = range->GetStartParent());
   *aStartOffset = range->StartOffset();
@@ -3603,17 +3603,17 @@ nsEditor::GetEndNodeAndOffset(Selection*
 {
   MOZ_ASSERT(aSelection);
   MOZ_ASSERT(aEndNode);
   MOZ_ASSERT(aEndOffset);
 
   *aEndNode = nullptr;
   *aEndOffset = 0;
 
-  NS_ENSURE_TRUE(aSelection->GetRangeCount(), NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(aSelection->RangeCount(), NS_ERROR_FAILURE);
 
   const nsRange* range = aSelection->GetRangeAt(0);
   NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
 
   NS_ENSURE_TRUE(range->IsPositioned(), NS_ERROR_FAILURE);
 
   NS_IF_ADDREF(*aEndNode = range->GetEndParent());
   *aEndOffset = range->EndOffset();
@@ -4157,17 +4157,17 @@ nsEditor::CreateTxnForDeleteSelection(ED
   // Check whether the selection is collapsed and we should do nothing:
   if (selection->Collapsed() && aAction == eNone) {
     return NS_OK;
   }
 
   // allocate the out-param transaction
   nsRefPtr<EditAggregateTxn> aggTxn = new EditAggregateTxn();
 
-  for (int32_t rangeIdx = 0; rangeIdx < selection->GetRangeCount(); ++rangeIdx) {
+  for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
     nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
     NS_ENSURE_STATE(range);
 
     // Same with range as with selection; if it is collapsed and action
     // is eNone, do nothing.
     if (!range->Collapsed()) {
       nsRefPtr<DeleteRangeTxn> txn = new DeleteRangeTxn();
       txn->Init(this, range, &mRangeUpdater);
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -310,17 +310,17 @@ nsHTMLEditRules::BeforeEdit(EditAction a
     
     // remember where our selection was before edit action took place:
     
     // get selection
     NS_ENSURE_STATE(mHTMLEditor);
     nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
 
     // get the selection location
-    NS_ENSURE_STATE(selection->GetRangeCount());
+    NS_ENSURE_STATE(selection->RangeCount());
     mRangeItem->startNode = selection->GetRangeAt(0)->GetStartParent();
     mRangeItem->startOffset = selection->GetRangeAt(0)->StartOffset();
     mRangeItem->endNode = selection->GetRangeAt(0)->GetEndParent();
     mRangeItem->endOffset = selection->GetRangeAt(0)->EndOffset();
     nsCOMPtr<nsIDOMNode> selStartNode = GetAsDOMNode(mRangeItem->startNode);
     nsCOMPtr<nsIDOMNode> selEndNode = GetAsDOMNode(mRangeItem->endNode);
 
     // register this range with range updater to track this as we perturb the doc
@@ -577,17 +577,17 @@ nsHTMLEditRules::WillDoAction(Selection*
       info->action == EditAction::redo) {
     return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel, aHandled);
   }
 
   // Nothing to do if there's no selection to act on
   if (!aSelection) {
     return NS_OK;
   }
-  NS_ENSURE_TRUE(aSelection->GetRangeCount(), NS_OK);
+  NS_ENSURE_TRUE(aSelection->RangeCount(), NS_OK);
 
   nsRefPtr<nsRange> range = aSelection->GetRangeAt(0);
   nsCOMPtr<nsINode> selStartNode = range->GetStartParent();
 
   NS_ENSURE_STATE(mHTMLEditor);
   if (!mHTMLEditor->IsModifiableNode(selStartNode)) {
     *aCancel = true;
     return NS_OK;
@@ -2420,17 +2420,17 @@ nsHTMLEditRules::WillDeleteSelection(Sel
             return NS_OK;
           }
         }
 
         // Else blocks not same type, or not siblings.  Delete everything
         // except table elements.
         join = true;
 
-        uint32_t rangeCount = aSelection->GetRangeCount();
+        uint32_t rangeCount = aSelection->RangeCount();
         for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
           nsRefPtr<nsRange> range = aSelection->GetRangeAt(rangeIdx);
 
           // Build a list of nodes in the range
           nsTArray<nsCOMPtr<nsINode>> arrayOfNodes;
           nsTrivialFunctor functor;
           nsDOMSubtreeIterator iter;
           res = iter.Init(range);
@@ -6045,17 +6045,17 @@ nsHTMLEditRules::GetListActionNodes(nsCO
   
   NS_ENSURE_STATE(mHTMLEditor);
   nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
   // added this in so that ui code can ask to change an entire list, even if selection
   // is only in part of it.  used by list item dialog.
   if (aEntireList)
   {       
-    uint32_t rangeCount = selection->GetRangeCount();
+    uint32_t rangeCount = selection->RangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
       nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
       nsCOMPtr<nsIDOMNode> commonParent, parent, tmp;
       range->GetCommonAncestorContainer(getter_AddRefs(commonParent));
       if (commonParent)
       {
         parent = commonParent;
         while (parent)
@@ -7514,17 +7514,17 @@ nsHTMLEditRules::ReapplyCachedStyles()
   // remember if we are in css mode
   NS_ENSURE_STATE(mHTMLEditor);
   bool useCSS = mHTMLEditor->IsCSSEnabled();
 
   // get selection point; if it doesn't exist, we have nothing to do
   NS_ENSURE_STATE(mHTMLEditor);
   nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
   MOZ_ASSERT(selection);
-  if (!selection->GetRangeCount()) {
+  if (!selection->RangeCount()) {
     // Nothing to do
     return NS_OK;
   }
   nsCOMPtr<nsIContent> selNode =
     do_QueryInterface(selection->GetRangeAt(0)->GetStartParent());
   if (!selNode) {
     // Nothing to do
     return NS_OK;
@@ -8174,17 +8174,17 @@ nsHTMLEditRules::SelectionEndpointInNode
   nsIDOMNode* node = aNode->AsDOMNode();
   
   *aResult = false;
   
   NS_ENSURE_STATE(mHTMLEditor);
   nsRefPtr<Selection> selection = mHTMLEditor->GetSelection();
   NS_ENSURE_STATE(selection);
   
-  uint32_t rangeCount = selection->GetRangeCount();
+  uint32_t rangeCount = selection->RangeCount();
   for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
     nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
     nsCOMPtr<nsIDOMNode> startParent, endParent;
     range->GetStartContainer(getter_AddRefs(startParent));
     if (startParent)
     {
       if (node == startParent) {
         *aResult = true;
--- a/editor/libeditor/nsHTMLEditor.cpp
+++ b/editor/libeditor/nsHTMLEditor.cpp
@@ -3270,17 +3270,17 @@ nsHTMLEditor::GetIsSelectionEditable(boo
   MOZ_ASSERT(aIsSelectionEditable);
 
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   // Per the editing spec as of June 2012: we have to have a selection whose
   // start and end nodes are editable, and which share an ancestor editing
   // host.  (Bug 766387.)
-  *aIsSelectionEditable = selection->GetRangeCount() &&
+  *aIsSelectionEditable = selection->RangeCount() &&
                           selection->GetAnchorNode()->IsEditable() &&
                           selection->GetFocusNode()->IsEditable();
 
   if (*aIsSelectionEditable) {
     nsINode* commonAncestor =
       selection->GetAnchorFocusRange()->GetCommonAncestor();
     while (commonAncestor && !commonAncestor->IsEditable()) {
       commonAncestor = commonAncestor->GetParentNode();
@@ -4542,17 +4542,17 @@ nsHTMLEditor::SetCSSBackgroundColor(cons
   bool cancel, handled;
   nsTextRulesInfo ruleInfo(EditAction::setTextProperty);
   nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
   NS_ENSURE_SUCCESS(res, res);
   if (!cancel && !handled)
   {
     // loop thru the ranges in the selection
     nsAutoString bgcolor; bgcolor.AssignLiteral("bgcolor");
-    uint32_t rangeCount = selection->GetRangeCount();
+    uint32_t rangeCount = selection->RangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
       nsCOMPtr<nsIDOMNode> cachedBlockParent = nullptr;
       nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
       NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
       
       // check for easy case: both range endpoints in same text node
       nsCOMPtr<nsIDOMNode> startNode, endNode;
       int32_t startOffset, endOffset;
--- a/editor/libeditor/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/nsHTMLEditorStyle.cpp
@@ -139,17 +139,17 @@ nsHTMLEditor::SetInlineProperty(nsIAtom 
   bool cancel, handled;
   nsTextRulesInfo ruleInfo(EditAction::setTextProperty);
   // Protect the edit rules object from dying
   nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
   nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
   NS_ENSURE_SUCCESS(res, res);
   if (!cancel && !handled) {
     // loop thru the ranges in the selection
-    uint32_t rangeCount = selection->GetRangeCount();
+    uint32_t rangeCount = selection->RangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
       nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
 
       // adjust range to include any ancestors whose children are entirely
       // selected
       res = PromoteInlineRange(range);
       NS_ENSURE_SUCCESS(res, res);
 
@@ -1364,17 +1364,17 @@ nsresult nsHTMLEditor::RemoveInlinePrope
   nsTextRulesInfo ruleInfo(EditAction::removeTextProperty);
   // Protect the edit rules object from dying
   nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
   res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
   NS_ENSURE_SUCCESS(res, res);
   if (!cancel && !handled)
   {
     // loop thru the ranges in the selection
-    uint32_t rangeCount = selection->GetRangeCount();
+    uint32_t rangeCount = selection->RangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
       nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
       if (aProperty == nsGkAtoms::name) {
         // promote range if it starts or end in a named anchor and we
         // want to remove named anchors
         res = PromoteRangeIfStartsOrEndsInNamedAnchor(range);
       }
       else {
@@ -1537,17 +1537,17 @@ nsHTMLEditor::RelativeFontChange( int32_
   
   // wrap with txn batching, rules sniffing, and selection preservation code
   nsAutoEditBatch batchIt(this);
   nsAutoRules beginRulesSniffing(this, EditAction::setTextProperty, nsIEditor::eNext);
   nsAutoSelectionReset selectionResetter(selection, this);
   nsAutoTxnsConserveSelection dontSpazMySelection(this);
 
   // loop thru the ranges in the selection
-  uint32_t rangeCount = selection->GetRangeCount();
+  uint32_t rangeCount = selection->RangeCount();
   for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
     nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
 
     // adjust range to include any ancestors who's children are entirely selected
     nsresult res = PromoteInlineRange(range);
     NS_ENSURE_SUCCESS(res, res);
     
     // check for easy case: both range endpoints in same text node
--- a/editor/libeditor/nsSelectionState.cpp
+++ b/editor/libeditor/nsSelectionState.cpp
@@ -50,17 +50,17 @@ nsSelectionState::DoTraverse(nsCycleColl
   }
 }
 
 void
 nsSelectionState::SaveSelection(Selection* aSel)
 {
   MOZ_ASSERT(aSel);
   int32_t arrayCount = mArray.Length();
-  int32_t rangeCount = aSel->GetRangeCount();
+  int32_t rangeCount = aSel->RangeCount();
 
   // if we need more items in the array, new them
   if (arrayCount < rangeCount) {
     for (int32_t i = arrayCount; i < rangeCount; i++) {
       mArray.AppendElement();
       mArray[i] = new nsRangeStore();
     }
   } else if (arrayCount > rangeCount) {
--- a/editor/libeditor/nsTableEditor.cpp
+++ b/editor/libeditor/nsTableEditor.cpp
@@ -2951,17 +2951,17 @@ nsHTMLEditor::GetNextSelectedCell(nsIDOM
 {
   NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
   *aCell = nullptr;
   if (aRange) *aRange = nullptr;
 
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
 
-  int32_t rangeCount = selection->GetRangeCount();
+  int32_t rangeCount = selection->RangeCount();
 
   // Don't even try if index exceeds range count
   if (mSelectedCellIndex >= rangeCount) 
     return NS_EDITOR_ELEMENT_NOT_FOUND;
 
   // Scan through ranges to find next valid selected cell
   nsRefPtr<nsRange> range;
   nsresult res;
--- a/editor/libeditor/tests/test_bug484181.html
+++ b/editor/libeditor/tests/test_bug484181.html
@@ -2,23 +2,23 @@
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=484181
 -->
 <head>
   <title>Test for Bug 484181</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>  
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=484181">Mozilla Bug 484181</a>
 <p id="display"></p>
 <div id="content" style="display: none">
-  
+
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 484181 **/
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(runTest);
@@ -33,17 +33,17 @@ function getEditor() {
                           .QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIEditingSession);
   return editingSession.getEditorForWindow(win);
 }
 
 function getSpellCheckSelection() {
   var editor = getEditor();
   var selcon = editor.selectionController;
-  return selcon.getSelection(selcon.SELECTION_SPELLCHECK);  
+  return selcon.getSelection(selcon.SELECTION_SPELLCHECK);
 }
 
 function append(str) {
 
   var edit = document.getElementById("edit");
   var editor = getEditor();
   var sel = editor.selection;
   sel.selectAllChildren(edit);
@@ -58,37 +58,37 @@ function runTest() {
   gMisspeltWords = ["haz", "cheezburger"];
   var edit = document.getElementById("edit");
   edit.focus();
 
   SpecialPowers.Cu.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm", window);
   onSpellCheck(edit, function () {
     is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for.");
 
-    append(" becaz I'm a lolcat!");
+    append(" becaz I'm a lulcat!");
     onSpellCheck(edit, function () {
       gMisspeltWords.push("becaz");
-      gMisspeltWords.push("lolcat");
+      gMisspeltWords.push("lulcat");
       is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for.");
 
       SimpleTest.finish();
     });
   });
 }
 
 function isSpellingCheckOk() {
 
   var sel = getSpellCheckSelection();
   var numWords = sel.rangeCount;
-  
+
   is(numWords, gMisspeltWords.length, "Correct number of misspellings and words.");
-  
-  if (numWords != gMisspeltWords.length) 
+
+  if (numWords != gMisspeltWords.length)
     return false;
-  
+
   for (var i=0; i<numWords; i++) {
     var word = sel.getRangeAt(i);
     is (word, gMisspeltWords[i], "Misspelling is what we think it is.");
     if (word != gMisspeltWords[i])
       return false;
   }
   return true;
 }
--- a/editor/libeditor/tests/test_bug596333.html
+++ b/editor/libeditor/tests/test_bug596333.html
@@ -66,20 +66,20 @@ function paste(str) {
   getEditor().pasteTransferable(trans);
 }
 
 function runOnFocus() {
   var edit = document.getElementById("edit");
 
   gMisspeltWords = ["haz", "cheezburger"];
   is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for.");
-  append(" becaz I'm a lolcat!");
+  append(" becaz I'm a lulcat!");
   onSpellCheck(edit, function () {
     gMisspeltWords.push("becaz");
-    gMisspeltWords.push("lolcat");
+    gMisspeltWords.push("lulcat");
     is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for.");
 
     // Now, type an invalid word, and instead of hitting "space" at the end, just blur
     // the textarea and see if the spell check after the blur event catches it.
     append(" workd");
     edit.blur();
     onSpellCheck(edit, function () {
       gMisspeltWords.push("workd");
--- a/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
+++ b/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
@@ -1,11429 +1,20118 @@
 1c1
 < 51247
 ---
 > 57065
-30c30
-< ABC/SM
----
-> ABC/M
-77a78,79
+34c34
+< ACLU
+---
+> ACLU/M
+44c44
+< AFC
+---
+> AFC/M
+54a55
+> AMD/M
+56c57
+< ANZUS
+---
+> ANZUS/M
+58c59
+< AP
+---
+> AP/M
+72c73
+< AWACS
+---
+> AWACS/M
+78,80c79,91
+< Aaron
+< Abbas
+< Abbasid
+---
 > Aaren/M
 > Aarika/M
-79c81,84
-< Abbas
----
+> Aaron/M
 > Ab/M
 > Abagael/M
 > Abagail/M
 > Abba/S
-80a86,90
+> Abbasid/M
 > Abbe/M
 > Abbey/M
 > Abbi/M
 > Abbie/M
 > Abbot/M
-82a93,94
+82a94,95
 > Abbye/M
 > Abdel/M
-89a102,103
+86c99
+< Abelard
+---
+> Abelard/M
+89a103,104
 > Abeu/M
 > Abey/M
-90a105,106
+91,92c106,110
+< Abigail
+< Abilene
+---
 > Abie/M
 > Abigael/M
-91a108
+> Abigail/M
 > Abigale/M
-94a112
+> Abilene/M
+94a113
 > Abra/M
-95a114
+95a115
 > Abrahan/M
-96a116,117
+96a117,118
 > Abramo/M
 > Abran/M
-119a141
+98c120
+< Abuja
+---
+> Abuja/M
+109c131
+< Achernar
+---
+> Achernar/M
+116,118c138,140
+< Actaeon
+< Acton
+< Acts
+---
+> Actaeon/M
+> Acton/M
+> Acts/M
+119a142
 > Ad/MN
-120a143,145
+120a144,146
 > Adah/M
 > Adair/M
 > Adaline/M
-121a147
+121a148,149
 > Adamo/M
-124a151,152
+> Adams/M
+123c151
+< Adana
+---
+> Adana/M
+125c153,155
+< Addams
+---
 > Adara/M
 > Adda/M
-126a155,156
+> Addams/M
+126a157,158
 > Addi/M
 > Addia/M
-128a159,161
+128c160,163
+< Addison
+---
+> Addison/M
 > Addy/M
 > Ade/M
 > Adel/M
-129a163
+129a165
 > Adelaida/M
-130a165
+130a167
 > Adelbert/M
-131a167,170
+131a169,172
 > Adelheid/M
 > Adelice/M
 > Adelina/M
 > Adelind/M
-132a172,173
+132a174,175
 > Adella/M
 > Adelle/M
-133a175
+134c177,180
+< Adenauer
+---
 > Adena/M
-134a177,178
+> Adenauer/M
 > Adey/M
 > Adham/M
-135a180,181
+135a182,183
 > Adi/M
 > Adiana/M
-136a183
+136a185
 > Adina/M
-139a187
+140c189,190
+< Adler
+---
 > Adlai/M
-142a191
+> Adler/M
+142a193
 > Ado/M
-145a195,197
+145a197,199
 > Adolphe/M
 > Adolpho/M
 > Adolphus/M
-146a199,203
+146a201,205
 > Adora/M
 > Adore/M
 > Adoree/M
 > Adorne/M
 > Adrea/M
-147a205
+148c207,208
+< Adrian
+---
 > Adria/MX
-149a208,211
+> Adrian/M
+149a210,213
 > Adriane/M
 > Adrianna/M
 > Adrianne/M
 > Adriano/M
-150a213,214
+150a215,216
 > Adrien/M
 > Adriena/M
-159a224,226
+159a226,228
 > Aeriel/M
 > Aeriela/M
 > Aeriell/M
-173a241
+164a234
+> Afghani/M
+173c243,244
+< Afrocentrism
+---
+> Afrocentrism/M
 > Afton/M
-174a243
+174a246
 > Agace/M
-178a248
+178a251
 > Agata/M
-179a250,251
+180,182c253,263
+< Aggie
+< Aglaia
+< Agnes
+---
 > Agathe/M
 > Aggi/M
-180a253
+> Aggie/M
 > Aggy/M
-181a255,256
+> Aglaia/M
 > Agna/M
 > Agnella/M
-182a258,260
+> Agnes/M
 > Agnese/M
 > Agnesse/M
 > Agneta/M
-184a263,264
+185,186c266,270
+< Agra
+< Agricola
+---
 > Agnola/M
 > Agosto/M
-185a266
+> Agra/M
 > Agretha/M
-189a271
+> Agricola/M
+189a274
 > Aguie/M
-192a275,276
+192a278,279
 > Aguistin/M
 > Aguste/M
-194a279
+194a282
 > Aharon/M
-200a286,287
+196c284
+< Ahmadabad
+---
+> Ahmadabad/M
+201c289,295
+< Aiken
+---
 > Aidan/M
 > Aigneis/M
-201a289,292
+> Aiken/M
 > Aila/M
 > Ailbert/M
 > Aile/M
 > Ailee/M
-202a294,300
+202a297,303
 > Ailene/M
 > Ailey/M
 > Aili/SM
 > Ailina/M
 > Ailsun/M
 > Ailyn/M
 > Aime/M
-203a302,306
+204c305,310
+< Ainu
+---
 > Aimil/M
 > Aindrea/M
 > Ainslee/M
 > Ainsley/M
 > Ainslie/M
-207a311
+> Ainu/M
+206c312
+< Aisha
+---
+> Aisha/M
+208c314,315
+< Akbar
+---
 > Ajay/M
-210a315
+> Akbar/M
+210,211c317,319
+< Akihito
+< Akita
+---
+> Akihito/M
 > Akim/M
-214a320
+> Akita/M
+213c321
+< Akkad
+---
+> Akkad/M
+214a323
 > Aksel/M
-220a327,330
+220a330,333
 > Alain/M
 > Alaine/M
 > Alair/M
 > Alameda/M
-224a335,340
+224a338,343
 > Alanah/M
 > Aland/M
 > Alane/M
 > Alanna/M
 > Alano/M
 > Alanson/M
-225a342
+226c345,347
+< Alaric
+---
 > Alard/M
-226a344
+> Alaric/M
 > Alasdair/M
-228a347,350
+229c350,354
+< Alba
+---
 > Alastair/M
 > Alasteir/M
 > Alaster/M
 > Alayne/M
-233a356
+> Alba/M
+233c358,359
+< Albee
+---
+> Albee/M
 > Alberik/M
-237a361,362
+235c361
+< Albert
+---
+> Albert/M
+237a364,365
 > Albertina/M
 > Albertine/M
-238a364
+239,240c367,370
+< Albigensian
+< Albion
+---
 > Albie/M
-239a366
+> Albigensian/M
 > Albina/M
-241a369
+> Albion/M
+241a372
 > Albrecht/M
-255a384,385
+243,245c374,376
+< Alcatraz
+< Alcestis
+< Alcibiades
+---
+> Alcatraz/M
+> Alcestis/M
+> Alcibiades/M
+249,252c380,383
+< Alcott
+< Alcuin
+< Alcyone
+< Aldan
+---
+> Alcott/M
+> Alcuin/M
+> Alcyone/M
+> Aldan/M
+254c385
+< Alden
+---
+> Alden/M
+255a387,388
 > Aldin/M
 > Aldis/M
-256a387,391
+256a390,394
 > Aldon/M
 > Aldous/M
 > Aldric/M
 > Aldrich/M
 > Aldridge/M
-257a393,394
+257a396,397
 > Aldus/M
 > Aldwin/M
-258a396,399
+258a399,402
 > Alecia/M
 > Aleda/M
 > Aleece/M
 > Aleen/M
-260a402
+260a405
 > Alejandrina/M
-261a404,405
+261a407,408
 > Alejoa/M
 > Aleksandr/M
-262a407,408
+262a410,411
 > Alena/M
 > Alene/M
-263a410,413
+263a413,416
 > Alessandra/M
 > Alessandro/M
 > Aleta/M
 > Alethea/M
-266a417
+266a420
 > Alexa/M
-267a419
+268c422,424
+< Alexandra
+---
 > Alexandr/M
-268a421
+> Alexandra/M
 > Alexandre/M
-270a424,425
+270a427,428
 > Alexandrina/M
 > Alexandro/MS
-272c427,436
+272c430,440
 < Alexis
 ---
 > Alexi/MS
 > Alexia/M
 > Alexina/M
 > Alexine/M
 > Alexio/M
+> Alexis/M
 > Alf/M
 > Alfi/M
 > Alfie/M
 > Alfons/M
 > Alfonse/M
-278a443
+276c444
+< Alfred
+---
+> Alfred/M
+278c446,447
+< Alfredo
+---
+> Alfredo/M
 > Alfy/M
-282a448
+280c449
+< Alger
+---
+> Alger/M
+282a452
 > Algernon/M
-290c456,459
+288c458
+< Alhambra
+---
+> Alhambra/M
+290c460,463
 < Ali
 ---
-> Ali/S
+> Ali/SM
 > Alia/M
 > Alic/M
 > Alica/M
-291a461
+291a465
 > Alicea/M
-292a463,466
+292a467,470
 > Alick/M
 > Alida/M
 > Alidia/M
 > Alie/M
-293a468,470
+293a472,474
 > Alika/M
 > Alikee/M
 > Alina/M
-296a474
+296a478
 > Alisander/M
-300a479,482
+300a483,486
 > Alister/M
 > Alisun/M
 > Alix/M
 > Aliza/M
-301a484
+301a488
 > Alla/M
-304a488,490
+303c490
+< Allahabad
+---
+> Allahabad/M
+304a492,494
 > Allard/M
 > Allayne/M
 > Alleen/M
-309a496
+306c496
+< Allegheny/S
+---
+> Allegheny/SM
+308c498
+< Allen
+---
+> Allen/M
+310c500,503
+< Allentown
+---
 > Allene/M
-310a498,499
+> Allentown/M
 > Alley/M
 > Alleyn/M
-313a503,506
+313a507,510
 > Allissa/M
 > Allister/M
 > Allistir/M
 > Allix/M
-314a508,512
+314a512,516
 > Allsun/M
 > Allx/M
 > Ally/SM
 > Allyce/M
 > Allyn/M
-318a517,519
+318a521,523
 > Almeda/M
 > Almeria/M
 > Almeta/M
-319a521,522
+319a525,526
 > Almira/M
 > Almire/M
-323a527,531
+323a531,535
 > Aloin/M
 > Aloise/M
 > Aloisia/M
 > Alon/M
 > Alonso/M
-324a533,534
+324a537,538
 > Aloysia/M
 > Aloysius/M
-333a544
+331c545
+< Alpine
+---
+> Alpine/M
+333a548
 > Alric/M
-348a560,561
+338c553
+< Alta
+---
+> Alta/M
+341,342c556,557
+< Altair
+< Altamira
+---
+> Altair/M
+> Altamira/M
+349c564,567
+< Alva
+---
 > Aluin/M
 > Aluino/M
-349a563
+> Alva/M
 > Alvan/M
-352a567,569
+352a571,573
 > Alvera/M
 > Alverta/M
 > Alvie/M
-353a571,577
+353a575,581
 > Alvina/M
 > Alvinia/M
 > Alvira/M
 > Alvis/M
 > Alvy/M
 > Alwin/M
 > Alwyn/M
-354a579,584
+354a583,588
 > Alyda/M
 > Alyosha/M
 > Alys/M
 > Alysa/M
 > Alyse/M
 > Alysia/M
-355a586
+355a590
 > Alyss
-358a590,591
+358a594,595
 > Amabel/M
 > Amabelle/M
-360a594,596
+360a598,600
 > Amalea/M
 > Amalee/M
 > Amaleta/M
-361a598,600
+361a602,604
 > Amalie/M
 > Amalita/M
 > Amalle/M
-362a602,606
+363c606,611
+< Amarillo
+---
 > Amandi/M
 > Amandie/M
 > Amandy/M
 > Amara/M
 > Amargo/M
-364a609
+> Amarillo/M
+364a613
 > Amata/M
-369c614,624
+366c615
+< Amati
+---
+> Amati/M
+369c618,628
 < Amber/M
 ---
 > Amber/MY
 > Amberly/M
 > Amble/M
 > Ambros/M
 > Ambrose
 > Ambrosi/M
 > Ambrosio/M
 > Ambrosius/M
 > Ambur/M
 > Amby/M
 > Ame/M
-370a626,629
+370a630,633
 > Amelie/M
 > Amelina/M
 > Ameline/M
 > Amelita/M
-379a639
+373c636
+< Amerasian
+---
+> Amerasian/M
+379a643
 > Amerigo/M
-381a642
+381a646
 > Amery/M
-384a646
+384c649,650
+< Amherst
+---
+> Amherst/M
 > Ami/M
-386a649,650
+386a653,654
 > Amii/M
 > Amil/M
-387a652,654
+387a656,658
 > Amitie/M
 > Amity/M
 > Ammamaria/M
-389a657
+390c661,662
+< Amos
+---
 > Amory/M
-399a668
+> Amos/M
+393c665
+< Amritsar
+---
+> Amritsar/M
+395,396c667,668
+< Amtrak
+< Amundsen
+---
+> Amtrak/M
+> Amundsen/M
+399a672
 > Amye/M
-400a670
+400a674
 > Anabal/M
-402a673,674
+402a677,678
 > Anabella/M
 > Anabelle/M
-406a679,682
+404,405c680,681
+< Anacreon
+< Anaheim
+---
+> Anacreon/M
+> Anaheim/M
+406a683,686
 > Analiese/M
 > Analise/M
 > Anallese/M
 > Anallise/M
-409a686,689
+408,409c688,693
+< Anasazi
+< Anastasia
+---
+> Anasazi/M
+> Anastasia/M
 > Anastasie/M
 > Anastassia/M
 > Anatol/M
 > Anatola/M
-412a693
+413c697,699
+< Anaxagoras
+---
 > Anatollo/M
-413a695
+> Anaxagoras/M
 > Ancell/M
-418a701,704
+416,418c702,708
+< Andalusian
+< Andaman
+< Andean
+---
+> Andalusian/M
+> Andaman/M
+> Andean/M
 > Andee/M
 > Andeee/M
 > Anderea/M
 > Anders/N
-421a708,710
+420c710
+< Anderson
+---
+> Anderson/M
+421a712,714
 > Andi/M
 > Andie/M
 > Andonis/M
-423a713
+423a717
 > Andra/MS
-425c715,717
+425c719,721
 < Andrea/M
 ---
 > Andrea/SM
 > Andreana/M
 > Andree/M
-427a720
+427a724
 > Andrej/M
-428a722,724
+428a726,728
 > Andrey/M
 > Andria/M
 > Andriana/M
-429a726,727
+430c730,733
+< Andromache
+---
 > Andriette/M
-> Andris
-432a731,732
+> Andris/M
+> Android/M
+> Andromache/M
+432c735,737
+< Andropov
+---
+> Andropov/M
 > Andros
 > Andrus/M
-433a734,738
+434c739,745
+< Angara
+---
 > Anestassia/M
 > Anet/M
 > Anett/M
 > Anetta/M
 > Anette/M
-434a740
+> Angara/M
 > Ange/M
-436a743,744
+436a748,749
 > Angele/M
 > Angeli/M
-439a748
+438,439c751,753
+< Angelica
+< Angelico
+---
+> Angelica/M
+> Angelico/M
 > Angelika/M
-443a753
+443a758
 > Angelle/M
-447a758
+445c760
+< Angelou
+---
+> Angelou/M
+448c763,764
+< Angkor
+---
 > Angil/M
-455c766
+> Angkor/M
+450c766
+< Anglia
+---
+> Anglia/M
+455,458c771,774
 < Anglicize
+< Anglo
+< Anglophil
+< Anglophile
 ---
 > Anglicize/DSG
-465a777,778
+> Anglo/M
+> Anglophil/M
+> Anglophile/M
+463c779
+< Angstrom
+---
+> Angstrom/M
+465a782,783
 > Angy/M
 > Ania/M
-467a781,782
+467a786,787
 > Anica/M
 > Anissa/M
-468a784,786
+468a789,791
 > Anitra/M
 > Anjanette/M
 > Anjela/M
-471a790
+471c794,795
+< Anna
+---
+> Anna/M
 > Annabal/M
-472a792,794
+472a797,799
 > Annabela/M
 > Annabell/M
 > Annabella/M
-473a796,800
+473a801,805
 > Annadiana/M
 > Annadiane/M
 > Annalee/M
 > Annaliese/M
 > Annalise/M
-474a802,803
+474a807,808
 > Annamaria/M
 > Annamarie/M
-477a807,811
+477c811,816
+< Anne
+---
+> Anne/M
 > Annecorinne/M
 > Anneliese/M
 > Annelise/M
 > Annemarie/M
 > Annetta/M
-478a813,814
+478a818,819
 > Anni/SM
 > Annice/M
-479a816,817
+479a821,822
 > Annissa/M
 > Annmaria/M
-480a819,820
+480a824,825
 > Annnora/M
 > Annora/M
-481a822
+482,483c827,832
+< Anouilh
+< Anselm
+---
 > Anny/M
-482a824,825
+> Anouilh/M
 > Ansel/M
 > Ansell/M
-483a827
+> Anselm/M
 > Anselma/M
-485a830,832
+486c835,838
+< Antaeus
+---
 > Ansley/M
 > Anson/M
 > Anstice/M
-490a838,841
+> Antaeus/M
+491c843,848
+< Anthony
+---
 > Anthe/M
 > Anthea/M
 > Anthia/M
 > Anthiathia/M
-497a849
+> Anthony/M
+> Anthropocene
+493c850
+< Antietam
+---
+> Antietam/M
+496c853
+< Antillean
+---
+> Antillean/M
+498c855,856
+< Antioch
+---
 > Antin/M
-504c856
+> Antioch/M
+503,504c861,862
+< Antoinette
 < Anton/M
 ---
+> Antoinette/M
 > Anton/MS
-505a858,860
+505a864,866
 > Antonella/M
 > Antonetta/M
 > Antoni/M
-506a862,866
+507c868,873
+< Antoninus
+---
 > Antonie/M
 > Antonietta/M
 > Antonin/M
 > Antonina/M
 > Antonino/M
-513a874,875
+> Antoninus/M
+509c875
+< Antonius
+---
+> Antonius/M
+514c880,882
+< Anzac
+---
 > Any/M
 > Anya/M
-530a893
+> Anzac/M
+517c885,886
+< Apennines
+---
+> Apatosaurus/M
+> Apennines/M
+519c888
+< Apia
+---
+> Apia/M
+522c891
+< Apollinaire
+---
+> Apollinaire/M
+524c893
+< Apollonian
+---
+> Apollonian/M
+529,531c898,901
+< Appleseed
+< Appleton
+< Appomattox
+---
+> Appleseed/M
+> Appleton/M
 > Appolonia/M
-533a897
+> Appomattox/M
+534c904,905
+< Apuleius
+---
 > Aprilette/M
-541c905
+> Apuleius/M
+537c908
+< Aquila
+---
+> Aquila/M
+541c912
 < Ar/M
 ---
 > Ar/MY
-543a908,912
+543a915,919
 > Arabel/M
 > Arabela/M
 > Arabele/M
 > Arabella/M
 > Arabelle/M
-552a922
+548c924
+< Araby
+---
+> Araby/M
+552a929
 > Araldo/M
-563a934,936
+564c941,944
+< Archean
+---
 > Arch/R
 > Archaimbaud/M
 > Archambault/M
-565a939,940
+> Archean/M
+565a946,947
 > Archibaldo/M
 > Archibold/M
-567a943
+567c949,950
+< Archimedes
+---
+> Archimedes/M
 > Archy/M
-569a946
+569a953
 > Arda/MH
-570a948
+570a955
 > Ardath/M
-571a950,954
+572,574c957,976
+< Arden
+< Arequipa
+< Ares
+---
 > Ardeen/M
 > Ardelia/M
 > Ardelis/M
 > Ardella/M
 > Ardelle/M
-572a956,966
+> Arden/M
 > Ardene/M
 > Ardenia/M
 > Ardine/M
 > Ardis/M
 > Ardisj/M
 > Ardith/M
 > Ardra/M
 > Ardyce/M
 > Ardys
 > Ardyth/M
 > Arel/M
-574a969
+> Arequipa/M
+> Ares/M
 > Aretha/M
-582a978
+579c981
+< Argo/S
+---
+> Argo/SM
+581a984
+> Argos/M
+582a986
 > Ari/M
-583a980
+583a988
 > Ariana/M
-584a982,983
+585c990,995
+< Ariel
+---
 > Aridatha/M
 > Arie/SM
-585a985,987
+> Ariel/M
 > Ariela/M
 > Ariella/M
 > Arielle/M
-586a989,990
+587c997,999
+< Ariosto
+---
 > Arin/M
 > Ario/M
-603a1008,1013
+> Ariosto/M
+589c1001
+< Aristides
+---
+> Aristides/M
+594c1006
+< Ariz
+---
+> Ariz/M
+598,599c1010,1011
+< Arjuna
+< Ark
+---
+> Arjuna/M
+> Ark/M
+602,603c1014,1021
+< Arkhangelsk
+< Arkwright
+---
+> Arkhangelsk/M
+> Arkwright/M
 > Arlan/M
 > Arlana/M
 > Arlee/M
 > Arleen/M
 > Arlen/M
 > Arlena/M
-604a1015,1023
+604a1023,1031
 > Arleta/M
 > Arlette/M
 > Arley/M
 > Arleyne/M
 > Arlie/M
 > Arliene/M
 > Arlin/M
 > Arlina/M
 > Arlinda/M
-606a1026,1029
+606c1033,1037
+< Arlington
+---
+> Arlington/M
 > Arluene/M
 > Arly/M
 > Arlyn/M
 > Arlyne/M
-608a1032
+608a1040
 > Arman/M
-613a1038
+613a1046
 > Armin/M
-617a1043,1044
+617a1051,1052
 > Arnaldo/M
-> Arne
-618a1046
+> Arne/M
+619c1054,1057
+< Arnhem
+---
 > Arney/M
-619a1048,1049
+> Arnhem/M
 > Arni/M
 > Arnie/M
-621a1052,1053
+621c1059,1061
+< Arnold
+---
+> Arnold/M
 > Arnoldo/M
 > Arnuad/M
-622a1055
+622a1063
 > Arny/M
-624a1058
+624c1065,1066
+< Arrhenius
+---
+> Arrhenius/M
 > Arri/M
-626a1061
+626a1069
 > Artair/M
-627a1063,1064
+627a1071,1072
 > Arte/M
-> Artemas
-628a1066,1067
+> Artemas/M
+628a1074,1075
 > Artemus/M
 > Arther/M
-631a1071
+630c1077
+< Arthurian
+---
+> Arthurian/M
+631a1079
 > Artur/M
-632a1073,1074
+632a1081,1082
 > Artus/M
 > Arty/M
-633a1076,1079
+633a1084,1087
 > Arv/M
 > Arvie/M
 > Arvin/M
 > Arvy/M
-634a1081,1082
+634a1089,1091
 > Aryn/M
+> As/M
 > Asa/M
-637a1086
+638,641c1095,1103
+< Asgard
+< Ashanti
+< Ashcroft
+< Ashe
+---
 > Ase/M
-638a1088
+> Asgard/M
 > Ash/MRY
-639a1090,1091
+> Ashanti/M
 > Ashbey/M
 > Ashby/M
-641c1093,1094
-< Ashe
----
+> Ashcroft/M
 > Ashe/Y
 > Ashely/M
-642a1096,1097
+642a1105,1106
 > Ashia/M
 > Ashien/M
-643a1099
+644c1108,1109
+< Ashkenazim
+---
 > Ashil/M
-645a1102,1103
+> Ashkenazim/M
+645a1111,1112
 > Ashla/M
 > Ashlan/M
-646a1105,1106
+646a1114,1115
 > Ashleigh/M
 > Ashlen/M
-647a1108,1111
+647a1117,1120
 > Ashli/M
 > Ashlie/M
 > Ashlin/M
 > Ashly/M
-648a1113
-> Ashton
-672a1138
+649c1122,1123
+< Ashurbanipal
+---
+> Ashton/M
+> Ashurbanipal/M
+650a1125
+> Asiago
+653,655c1128,1130
+< Asimov
+< Asmara
+< Asoka
+---
+> Asimov/M
+> Asmara/M
+> Asoka/M
+657a1133
+> Asperger/M
+659c1135
+< Asquith
+---
+> Asquith/M
+664c1140
+< Assisi
+---
+> Assisi/M
+667c1143
+< Astaire
+---
+> Astaire/M
+670,675c1146,1154
+< Aston
+< Astor
+< Astoria
+< Astrakhan
+< AstroTurf
+< Asturias
+---
+> Aston/M
+> Astor/M
+> Astoria/M
 > Astra/M
-673a1140,1141
+> Astrakhan/M
 > Astrid/M
 > Astrix/M
-695c1163
+> AstroTurf/M
+> Asturias/M
+680,681c1159,1160
+< Atahualpa
+< Atalanta
+---
+> Atahualpa/M
+> Atalanta/M
+693c1172
+< Atkinson
+---
+> Atkinson/M
+695c1174
 < Atlantes
 ---
 > Atlante/SM
-710a1179,1185
+699,700c1178,1179
+< Atman
+< Atreus
+---
+> Atman/M
+> Atreus/M
+706c1185
+< Attlee
+---
+> Attlee/M
+708c1187
+< Attucks
+---
+> Attucks/M
+711,712c1190,1200
+< Aubrey
+< Auckland
+---
 > Aube
 > Auberon/M
 > Aubert/M
 > Auberta/M
 > Aubine/M
 > Aubree/M
 > Aubrette/M
-711a1187,1188
+> Aubrey/M
 > Aubrie/M
 > Aubry/M
-714a1192
+> Auckland/M
+714a1203
 > Audie/M
-716a1195
+716a1206
 > Audre/M
-717a1197,1199
+718c1208,1212
+< Audubon
+---
 > Audrie/M
 > Audry/M
 > Audrye/M
-718a1201
+> Audubon/M
 > Audy/M
-720a1204
+720,721c1214,1216
+< Augean
+< Augsburg
+---
+> Augean/M
 > Augie/M
-724a1209,1211
+> Augsburg/M
+724c1219,1222
+< Augustan
+---
+> Augustan/M
 > Auguste/M
 > Augustin/M
 > Augustina/M
-726a1214
+726a1225
 > Augusto/M
-727a1216,1218
+728c1227,1233
+< Aurangzeb
+---
 > Augy/M
 > Aundrea/M
 > Aura/M
-728a1220,1222
+> Aurangzeb/M
 > Aurea/M
 > Aurel/M
 > Aurelea/M
-729a1224
+729a1235
 > Aurelie/M
-732a1228,1229
+731c1237
+< Aurelius
+---
+> Aurelius/M
+732a1239,1240
 > Auria/M
 > Aurie/M
-733a1231,1233
+733a1242,1244
 > Aurilia/M
 > Aurlie/M
 > Auroora/M
-734a1235,1236
+735c1246,1248
+< Auschwitz
+---
 > Aurore/M
 > Aurthur/M
-739a1242,1243
+> Auschwitz/M
+737c1250
+< Austen
+---
+> Austen/M
+739a1253,1254
 > Austina/M
 > Austine/M
-753a1258
+741c1256
+< Australasian
+---
+> Australasian/M
+744c1259
+< Australoid
+---
+> Australoid/M
+752,756c1267,1275
+< Avalon
+< Ave
+< Aventine
+< Avernus
+< Averroes
+---
+> Avalon/M
+> Ave/M
 > Aveline/M
-754a1260,1262
+> Aventine/M
 > Averell/M
 > Averil/M
 > Averill/M
-757a1266
+> Avernus/M
+> Averroes/M
+757a1277
 > Averyl/M
-759a1269,1271
+759,760c1279,1283
+< Avicenna
+< Avignon
+---
+> Avicenna/M
 > Avictor/M
 > Avie/M
 > Avigdor/M
-763a1276,1277
+> Avignon/M
+763,767c1286,1299
+< Avis
+< Avogadro
+< Avon
+< Axis
+< Axum
+---
+> Avis/M
 > Aviva/M
 > Avivah/M
-765a1280,1286
+> Avogadro/M
+> Avon/M
 > Avram/M
 > Avril/M
 > Avrit/M
 > Avrom/M
 > Ax/M
 > Axe/M
-> Axel
-769a1291,1292
+> Axel/M
+> Axis/M
+> Axum/M
+769,770c1301,1306
+< Ayers
+< Aymara
+---
+> Ayers/M
 > Aylmar/M
 > Aylmer/M
-770a1294,1295
+> Aymara/M
 > Aymer/M
 > Ayn/M
-813a1339
+772c1308
+< Ayurveda
+---
+> Ayurveda/M
+776c1312
+< Azazel
+---
+> Azazel/M
+780c1316
+< Azov
+---
+> Azov/M
+788,789c1324,1325
+< BBB
+< BBC
+---
+> BBB/M
+> BBC/M
+793a1330
+> BFF
+801c1338
+< BP
+---
+> BP/M
+806c1343
+< BSD/S
+---
+> BSD/SM
+813c1350,1351
+< Baathist
+---
+> Baathist/M
 > Bab/SM
-814a1341,1342
+815,816c1353,1358
+< Babbage
+< Babbitt
+---
 > Babara/M
 > Babb/M
-815a1344,1345
+> Babbage/M
 > Babbette/M
 > Babbie/M
-817a1348,1349
+> Babbitt/M
+817a1360,1361
 > Babette/M
 > Babita/M
-847a1380
+823c1367
+< Bacardi
+---
+> Bacardi/M
+830,831c1374,1375
+< Bactria
+< Baden
+---
+> Bactria/M
+> Baden/M
+834c1378
+< Baez
+---
+> Baez/M
+836c1380
+< Baggies
+---
+> Baggies/M
+838,840c1382,1384
+< Baguio
+< Baha'i
+< Baha'ullah
+---
+> Baguio/M
+> Baha'i/M
+> Baha'ullah/M
+845c1389
+< Bahia
+---
+> Bahia/M
+847c1391,1392
+< Baikal
+---
+> Baikal/M
 > Bail/M
-848a1382,1384
+849c1394,1397
+< Baird
+---
 > Bailie/M
 > Baillie/M
 > Baily/M
-857a1394
+> Baird/M
+851,852c1399,1400
+< Baker
+< Bakersfield
+---
+> Baker/M
+> Bakersfield/M
+854,857c1402,1406
+< Bakunin
+< Balanchine
+< Balaton
+< Balboa
+---
+> Bakunin/M
+> Balanchine/M
+> Balaton/M
+> Balboa/M
 > Bald/MR
-858a1396
+858a1408
 > Balduin/M
-859a1398
+859a1410
 > Bale/M
-874a1414,1416
+861c1412
+< Balfour
+---
+> Balfour/M
+864,866c1415,1417
+< Balkan/S
+< Balkhash
+< Ball
+---
+> Balkan/SM
+> Balkhash/M
+> Ball/M
+868c1419
+< Balthazar
+---
+> Balthazar/M
+871c1422
+< Baluchistan
+---
+> Baluchistan/M
+874a1426,1428
 > Bambie/M
 > Bamby/M
 > Ban/M
-886c1428,1429
+878c1432
+< Bangalore
+---
+> Bangalore/M
+882c1436
+< Bangor
+---
+> Bangor/M
+885,886c1439,1441
+< Banjul
 < Banks
 ---
+> Banjul/M
 > Bank/SM
 > Banky/M
-893a1437
+888,889c1443,1444
+< Bannister
+< Banting
+---
+> Bannister/M
+> Banting/M
+894c1449,1450
+< Barabbas
+---
 > Bar/H
-895a1440,1442
+> Barabbas/M
+895a1452,1454
 > Barb/MR
 > Barbabas/M
 > Barbabra/M
-898a1446
+898a1458
 > Barbaraanne/M
-901a1450
+902,903c1462,1468
+< Barber
+< Barbie
+---
 > Barbe/M
-902a1452,1455
+> Barber/M
 > Barbee/M
 > Barbette/M
 > Barbey/M
 > Barbi/M
-906a1460
+> Barbie/M
+906a1472
 > Barby/M
-908a1463,1464
+908a1475,1476
 > Bard/M
 > Barde/M
-910a1467
+910a1479
 > Bari/M
-913a1471
+914c1483,1485
+< Barnabas
+---
 > Barn/M
-914a1473
+> Barnabas/M
 > Barnabe/M
-917a1477
+916,918c1487,1490
+< Barnard
+< Barnaul
+< Barnes
+---
+> Barnard/M
+> Barnaul/M
 > Barnebas/M
-920a1481
+> Barnes/M
+921,922c1493,1497
+< Barnum
+< Baroda
+---
 > Barnie/M
-921a1483
+> Barnum/M
 > Barny/M
-922a1485
+> Baroda/M
 > Baron/M
-927a1491
+924c1499
+< Barquisimeto
+---
+> Barquisimeto/M
+926c1501
+< Barranquilla
+---
+> Barranquilla/M
+927a1503
 > Barret/M
-928a1493
+928a1505
 > Barri/MS
-933a1499
+931,934c1508,1513
+< Barry
+< Barrymore
+< Bart
+< Barth/S
+---
+> Barry/M
+> Barrymore/M
+> Bart/M
 > Bartel/M
-934a1501
+> Barth/SM
 > Barthel/M
-935a1503,1505
+936,941c1515,1532
+< Bartholomew
+< Bartlett
+< Bartok
+< Barton
+< Baruch
+< Baryshnikov
+---
 > Bartholemy/M
 > Bartholomeo/M
 > Bartholomeus/M
-936a1507,1508
+> Bartholomew/M
 > Bartie/M
 > Bartlet/M
-938a1511,1512
+> Bartlett/M
+> Bartok/M
 > Bartolemo/M
 > Bartolomeo/M
-939a1514,1515
+> Barton/M
 > Bartram/M
 > Barty/M
-940a1517,1518
+> Baruch/M
 > Bary/M
 > Baryram/M
-941a1520
+> Baryshnikov/M
 > Base/M
-943a1523
+944,946c1535,1541
+< Basic
+< Basie
+< Basil
+---
 > Basia/M
-946a1527,1529
+> Basic/M
+> Basie/M
+> Basil/M
 > Basile/M
 > Basilio/M
 > Basilius/M
-950a1534,1535
+948c1543
+< Basra
+---
+> Basra/M
+950a1546,1547
 > Bastian/M
 > Bastien/M
-952a1538
+952a1550
 > Bat/M
-954a1541
+954,956c1552,1555
+< Bates
+< Bathsheba
+< Batista
+---
+> Bates/M
 > Batholomew/M
-957a1545
+> Bathsheba/M
+> Batista/M
+957a1557
 > Batsheva/M
-960a1549
+960a1561
 > Baudoin/M
-966a1556,1557
+962c1563
+< Bauer
+---
+> Bauer/M
+964c1565
+< Baum
+---
+> Baum/M
+966a1568,1569
 > Bax
 > Baxie/M
-967a1559,1560
+967a1571,1572
 > Baxy/M
 > Bay/MR
-968a1562
+968a1574
 > Bayard
-977a1572
+970,971c1576,1577
+< Bayes
+< Bayesian
+---
+> Bayes/M
+> Bayesian/M
+975c1581
+< Bayreuth
+---
+> Bayreuth/M
+977a1584
 > Bea/M
-979a1575,1576
+979c1586,1588
+< Beadle
+---
+> Beadle/M
 > Beale/M
 > Bealle/M
-980a1578
+980a1590
 > Bear/M
-984a1583
+983c1593
+< Beardsley
+---
+> Beardsley/M
+984a1595
 > Bearnard/M
-988a1588
+988a1600
 > Beatrisa/M
-997a1598,1599
+992c1604
+< Beaufort
+---
+> Beaufort/M
+995c1607
+< Beaumont
+---
+> Beaumont/M
+997c1609,1611
+< Beauvoir
+---
+> Beauvoir/M
 > Bebe/M
 > Becca/M
-999a1602
+999a1614
 > Becka/M
-1002a1606,1607
+1002a1618,1619
 > Becki/M
 > Beckie/M
-1006a1612
+1004,1005c1621,1622
+< Becquerel
+< Bede
+---
+> Becquerel/M
+> Bede/M
+1006a1624
 > Bee/M
-1018a1625
+1008c1626
+< Beecher
+---
+> Beecher/M
+1011c1629
+< Beerbohm
+---
+> Beerbohm/M
+1014,1017c1632,1635
+< Begin
+< Behan
+< Behring
+< Beiderbecke
+---
+> Begin/M
+> Behan/M
+> Behring/M
+> Beiderbecke/M
+1018a1637
 > Beilul/M
-1019a1627
+1019a1639
 > Beitris/M
-1020a1629,1630
+1020a1641,1642
 > Bekki/M
 > Bel/M
-1029a1640,1641
+1026c1648
+< Belg
+---
+> Belg/M
+1029a1652,1653
 > Belia/M
 > Belicia/M
-1030a1643
+1030a1655
 > Belita/M
-1034a1648
+1034a1660
 > Bellanca/M
-1035a1650
+1036,1038c1662,1666
+< Belleek
+< Bellini
+< Bellow
+---
 > Belle/M
-1036a1652
+> Belleek/M
 > Bellina/M
-1044a1661
+> Bellini/M
+> Bellow/M
+1040c1668
+< Belmopan
+---
+> Belmopan/M
+1044c1672,1673
+< Beltane
+---
+> Beltane/M
 > Beltran/M
-1045a1663,1664
+1045a1675,1676
 > Belva/M
 > Belvia/M
-1050a1670,1672
+1050a1682,1684
 > Bendick/M
 > Bendicty/M
 > Bendite/M
-1051a1674,1676
+1051a1686,1688
 > Benedetta/M
 > Benedetto/M
 > Benedick/M
-1052a1678
+1052a1690
 > Benedicta/M
-1053a1680,1682
+1053a1692,1694
 > Benedicto/M
 > Benedikt/M
 > Benedikta/M
-1055a1685
+1055c1696,1697
+< Benet
+---
+> Benet/M
 > Benetta/M
-1059a1690,1691
+1059a1702,1703
 > Bengt/M
 > Beniamino/M
-1063a1696
+1064,1065c1708,1715
+< Benjamin
+< Bennett
+---
 > Benjamen/M
-1064a1698,1701
+> Benjamin/M
 > Benji/M
 > Benjie/M
 > Benjy/M
 > Benn/M
-1065a1703
+> Bennett/M
 > Benni/M
-1067a1706,1707
+1067a1718,1719
 > Benoit/M
 > Benoite/M
-1068a1709
+1069,1072c1721,1727
+< Bentham
+< Bentley
+< Benton
+< Benz
+---
 > Bent/M
-1069a1711
+> Bentham/M
 > Bentlee/M
-1071a1714
+> Bentley/M
+> Benton/M
 > Benyamin/M
-1074a1718
+> Benz/M
+1074c1729,1730
+< Beowulf
+---
+> Beowulf/M
 > Ber/MG
-1076a1721
+1076a1733
 > Beret
-1081a1727
+1078c1735
+< Berg/NR
+---
+> Berg/MNR
+1081,1085c1738,1745
+< Bergerac
+< Bergman
+< Bergson
+< Beria
+< Bering
+---
+> Bergerac/M
 > Berget/M
-1085a1732,1733
+> Bergman/M
+> Bergson/M
+> Beria/M
+> Bering/M
 > Berk/MY
 > Berke/M
-1086a1735,1737
+1086a1747,1749
 > Berkie/M
 > Berkley/M
 > Berkly/M
-1087a1739
+1087a1751
 > Berky/M
-1096a1749,1750
+1091c1755
+< Berlioz
+---
+> Berlioz/M
+1097c1761,1764
+< Bernadette
+---
 > Berna/M
 > Bernadene/M
-1097a1752
+> Bernadette/M
 > Bernadina/M
-1100a1756,1757
+1100c1767,1769
+< Bernard
+---
+> Bernard/M
 > Bernardina/M
 > Bernardine
-1101a1759
+1101a1771
 > Bernarr/M
-1104c1762
+1104c1774
 < Berne/M
 ---
 > Bernelle/M
-1105a1764,1767
+1106c1776,1781
+< Bernhardt
+---
 > Bernete/M
 > Bernetta/M
 > Bernette/M
 > Bernhard/M
-1106a1769
+> Bernhardt/M
 > Berni/M
-1109a1773
+1109,1111c1784,1788
+< Bernini
+< Bernoulli
+< Bernstein
+---
+> Bernini/M
 > Bernita/M
-1111a1776
+> Bernoulli/M
+> Bernstein/M
 > Berny/M
-1112a1778,1779
+1113c1790,1792
+< Berry
+---
 > Berri/M
 > Berrie/M
-1115a1783
+> Berry/M
+1115a1795
 > Berte/M
-1117a1786,1787
+1117a1798,1799
 > Berthe/M
 > Berti/M
-1119a1790,1792
+1119a1802,1804
 > Bertina/M
 > Bertine/M
 > Berton/M
-1121a1795,1796
+1121a1807,1808
 > Bertrando/M
 > Berty/M
-1122a1798
+1123,1125c1810,1813
+< Berzelius
+< Bess
+< Bessel
+---
 > Beryle/M
-1127a1804
+> Berzelius/M
+> Bess/M
+> Bessel/M
+1127c1815,1816
+< Bessie
+---
+> Bessie/M
 > Bessy/M
-1130a1808
+1131,1133c1820,1825
+< Bethany
+< Bethe
+< Bethesda
+---
 > Bethanne/M
-1132a1811
+> Bethany/M
+> Bethe/M
 > Bethena/M
-1133a1813
+> Bethesda/M
 > Bethina/M
-1135a1816
+1135c1827,1828
+< Bethune
+---
+> Bethune/M
 > Betsey/M
-1136a1818
+1136a1830
 > Betta/M
-1137a1820,1822
+1137a1832,1834
 > Betteann/M
 > Betteanne/M
 > Betti
-1138a1824,1825
+1138a1836,1837
 > Bettina/M
 > Bettine/M
-1141a1829,1831
+1141c1840,1843
+< Beulah
+---
+> Beulah/M
 > Bevan
 > Beverie/M
 > Beverlee/M
-1142a1833
+1142a1845
 > Beverlie/M
-1143a1835,1837
+1144,1145c1847,1851
+< Beyer
+< Bhopal
+---
 > Bevin
 > Bevon/M
 > Bevvy/M
-1151a1846
+> Beyer/M
+> Bhopal/M
+1150c1856
+< Bialystok
+---
+> Bialystok/M
+1151a1858
 > Bianka/M
-1152a1848,1851
+1152a1860,1863
 > Bibbie/M
 > Bibby/M
 > Bibbye/M
 > Bibi/M
-1155a1855
+1156c1867,1869
+< Biddle
+---
 > Biddie/M
-1156a1857
+> Biddle/M
 > Biddy/M
-1157a1859
+1158c1871,1872
+< Bierce
+---
 > Bidget/M
-1161a1864
+> Bierce/M
+1162c1876,1877
+< Bilbao
+---
 > Bil/MY
-1163a1867
+> Bilbao/M
+1163a1879
 > Bili/M
-1164a1869
+1164a1881
 > Billi/M
-1167a1873
+1167a1885
 > Billye/M
-1168a1875,1879
+1168a1887,1891
 > Bink/M
 > Binky/M
 > Binni/M
 > Binnie/M
 > Binny/M
-1169a1881
+1170c1893,1895
+< Bird
+---
 > Birch/M
-1170a1883
+> Bird/M
 > Birdie/M
-1171a1885,1887
+1172c1897,1900
+< Birkenstock
+---
 > Birgit/M
 > Birgitta/M
 > Birk/M
-1174a1891
+> Birkenstock/M
+1175c1903,1904
+< Biscay
+---
 > Biron/M
-1183a1901
+> Biscay/M
+1177c1906
+< Bishkek
+---
+> Bishkek/M
+1183c1912,1914
+< Bizet
+---
+> BitTorrent/M
+> Bizet/M
 > Bjorn/M
-1197a1916
+1190c1921
+< Blackfeet
+---
+> Blackfeet/M
+1194,1195c1925,1926
+< Blackstone
+< Blackwell
+---
+> Blackstone/M
+> Blackwell/M
+1198c1929,1932
+< Blake
+---
 > Blaire/M
-1198a1918,1919
+> Blake/M
 > Blakelee/M
 > Blakeley/M
-1199a1921,1922
+1199a1934,1935
 > Blanch/M
 > Blancha/M
-1201a1925
+1201a1938
 > Blane/M
-1205a1930
+1205c1942,1943
+< Blavatsky
+---
+> Blavatsky/M
 > Blayne/M
-1208a1934,1939
+1209c1947,1953
+< Bloch
+---
 > Blinni/M
 > Blinnie/M
 > Blinny/M
 > Bliss
 > Blisse/M
 > Blithe/M
-1212a1944,1945
+> Bloch/M
+1212a1957,1958
 > Blondell/M
 > Blondelle/M
-1213a1947
+1213a1960
 > Blondy/M
-1221a1956
+1215c1962,1963
+< Bloomfield
+---
+> Bloomer/M
+> Bloomfield/M
+1217c1965,1966
+< Bloomsbury
+---
+> Bloomsbury/M
+> Blu
+1221a1971
 > Bo/MRZ
-1224a1960,1962
+1224a1975,1977
 > Bobbe/M
 > Bobbee/M
 > Bobbette/M
-1228a1967,1971
+1229c1982,1987
+< Boccaccio
+---
 > Bobbye/M
 > Bobette/M
 > Bobina/M
 > Bobine/M
 > Bobinette/M
-1237a1981
+> Boccaccio/M
+1234c1992
+< Boeotian
+---
+> Boeotian/M
+1236c1994
+< Boethius
+---
+> Boethius/M
+1237a1996
 > Bogey/M
-1241a1986
+1239c1998
+< Bohemia
+---
+> Bohemia/M
+1241c2000,2001
+< Bohr
+---
+> Bohr/M
 > Boigie/M
-1259a2005,2008
+1251,1252c2011,2012
+< Bolshevism
+< Bolshevist
+---
+> Bolshevism/M
+> Bolshevist/M
+1254,1255c2014,2015
+< Bolton
+< Boltzmann
+---
+> Bolton/M
+> Boltzmann/M
+1257,1258c2017,2018
+< Bonaparte
+< Bonaventure
+---
+> Bonaparte/M
+> Bonaventure/M
+1259a2020,2023
 > Bondie/M
 > Bondon/M
 > Bondy/M
 > Bone/M
-1263a2013
+1261c2025
+< Boniface
+---
+> Boniface/M
+1263a2028
 > Bonnee/M
-1265a2016,2017
+1265a2031,2032
 > Bonni/M
 > Bonnibelle/M
-1266a2019
-> Bonny
-1271a2025,2028
+1266a2034
+> Bonny/M
+1270c2038
+< Boolean
+---
+> Boolean/M
+1271a2040,2043
 > Boonie/M
 > Boony/M
 > Boot/M
 > Boote/MS
-1273a2031,2032
+1273c2045,2047
+< Booth
+---
+> Booth/M
 > Boothe/M
 > Bord/MN
-1275a2035
+1275a2050
 > Bordie/M
-1276a2037
+1276a2052
 > Bordy/M
-1304a2066
+1279,1282c2055,2058
+< Borges
+< Borgia
+< Borglum
+< Boris
+---
+> Borges/M
+> Borgia/M
+> Borglum/M
+> Boris/M
+1285c2061
+< Born
+---
+> Born/M
+1288c2064
+< Borodin
+---
+> Borodin/M
+1290,1291c2066,2067
+< Bosch
+< Bose
+---
+> Bosch/M
+> Bose/M
+1293c2069
+< Bosnian
+---
+> Bosnian/M
+1296,1297c2072,2074
+< Bostonian
+< Boswell
+---
+> Bostonian/M
+> Boswell/M
+> Botox
+1299,1301c2076,2078
+< Botticelli
+< Boudicca
+< Boulder
+---
+> Botticelli/M
+> Boudicca/M
+> Boulder/M
+1305c2082,2083
+< Bournemouth
+---
 > Bourke/M
-1313a2076,2079
+> Bournemouth/M
+1310c2088
+< Bowers
+---
+> Bowers/M
+1312c2090
+< Bowie
+---
+> Bowie/M
+1314c2092,2096
+< Boyd
+---
 > Boy/MR
 > Boyce/M
 > Boycey/M
 > Boycie/M
-1317c2083
+> Boyd/M
+1316,1317c2098,2099
+< Boyle
 < Br/MT
 ---
+> Boyle/M
 > Br/MNT
-1318a2085
+1319c2101,2102
+< Bradbury
+---
 > Bradan/M
-1320a2088,2089
+> Bradbury/M
+1321,1322c2104,2107
+< Bradford
+< Bradley
+---
 > Brade/M
 > Braden/M
-1323a2093
+> Bradford/M
+> Bradley/M
+1323a2109
 > Bradney/M
-1339a2110
+1326c2112
+< Brady
+---
+> Brady/M
+1328c2114
+< Brahe
+---
+> Brahe/M
+1332,1333c2118,2119
+< Brahmanee
+< Brahmani
+---
+> Brahmanee/M
+> Brahmani/M
+1339a2126
 > Bram/M
-1341a2113
+1341a2129
 > Brana/M
-1342a2115,2118
+1343c2131,2135
+< Brandeis
+---
 > Brand/MNR
 > Brandais/M
 > Brande/M
 > Brandea/M
-1345a2122
+> Brandeis/M
+1345c2137,2138
+< Brandenburg
+---
+> Brandenburg/M
 > Brander/M
-1346a2124
+1346a2140
 > Brandice/M
-1347a2126
+1348c2142,2143
+< Brando
+---
 > Brandise/M
-1350a2130
+> Brando/M
+1350c2145,2146
+< Brandt
+---
+> Brandt/M
 > Brandtr/M
-1351a2132,2133
+1351a2148,2149
 > Brandyn/M
 > Brannon/M
-1352a2135
+1353c2151,2152
+< Braque
+---
 > Brantley/M
-1362a2146,2147
+> Braque/M
+1355c2154
+< Bratislava
+---
+> Bratislava/M
+1362a2162,2163
 > Breanne/M
 > Brear/M
-1365a2151,2152
+1364c2165
+< Brecht
+---
+> Brecht/M
+1366c2167,2171
+< Bremen
+---
 > Bree/M
 > Breena/M
-1366a2154,2155
+> Bremen/M
 > Bren/M
 > Brena/M
-1368a2158,2163
+1368a2174,2179
 > Brenden/M
 > Brendin/M
 > Brendis/M
 > Brendon/M
 > Brenn/MNR
 > Brenna/M
-1369a2165
+1369a2181
 > Brennen/M
-1376a2173
+1372a2185
+> Brest/M
+1376a2190
 > Brew/MR
-1379a2177
+1378,1379c2192,2194
+< Brewster
+< Brezhnev
+---
+> Brewster/M
+> Brezhnev/M
 > Bria/M
-1382a2181,2183
+1382a2198,2200
 > Brianne/M
 > Briano/M
 > Briant/M
-1384a2186
+1384a2203
 > Bride/M
-1393c2195,2200
+1387c2206
+< Bridges
+---
+> Bridges/M
+1389c2208
+< Bridgetown
+---
+> Bridgetown/M
+1392,1395c2211,2219
+< Bridgman
 < Brie/SM
----
+< Brigadoon
+< Briggs
+---
+> Bridgman/M
 > Bridie/M
 > Brie/RSM
 > Brien/M
 > Brier/M
 > Brietta/M
-> Brig
-1395c2202
-< Briggs
----
+> Brig/M
+> Brigadoon/M
 > Brigg/MS
-1399a2207,2209
+1397c2221
+< Bright
+---
+> Bright/M
+1399a2224,2226
 > Brigida/M
 > Brigit/M
 > Brigitta/M
-1401a2212,2213
+1401c2228,2230
+< Brillo
+---
+> Brillo/M
 > Brina/M
 > Briney/M
-1402a2215,2218
+1402a2232,2235
 > Brinn/M
 > Brinna/M
 > Briny/M
 > Brion/M
-1405a2222
+1405a2239
 > Brita/M
-1413a2231
+1407,1408c2241,2242
+< Britannia
+< Britannic
+---
+> Britannia/M
+> Britannic/M
+1413a2248
 > Britni/M
-1415a2234,2237
+1415a2251,2254
 > Britta/M
 > Brittan/M
 > Brittaney/M
 > Brittani/M
-1416a2239,2241
+1416a2256,2259
 > Britte/M
+> Britten/M
 > Britteny/M
 > Brittne/M
-1417a2243,2245
+1418c2261,2264
+< Brno
+---
 > Brittni/M
 > Brnaba/M
 > Brnaby/M
-1422a2251,2260
+> Brno/M
+1421c2267
+< Brobdingnagian
+---
+> Brobdingnagian/M
+1422a2269,2278
 > Brockie/M
 > Brocky/M
 > Brod/M
 > Broddie/M
 > Broddy/M
 > Broderic/M
 > Broderick/M
 > Brodie/M
 > Brody/M
 > Brok/M
-1423a2262,2264
+1423a2280,2282
 > Bron/M
 > Bronnie/M
 > Bronny/M
-1426a2268
+1425c2284,2285
+< Bronte
+---
+> Bronte/M
+> Brontosaurus
+1427c2287,2288
+< Brooke
+---
 > Brook/MS
-1429d2270
+> Brooke/M
+1429c2290
 < Brooks
-1430a2272
+---
+> Brooks/M
+1431,1432c2292,2294
+< Brown/G
+< Browne
+---
 > Brose/M
-1438a2281
+> Brown/MG
+> Browne/M
+1435,1437c2297,2300
+< Brownshirt
+< Brownsville
+< Brubeck
+---
+> Browning/M
+> Brownshirt/M
+> Brownsville/M
+> Brubeck/M
+1439,1441c2302,2306
+< Bruckner
+< Bruegel
+< Brueghel
+---
 > Brucie/M
-1441a2285
+> Bruckner/M
+> Bruegel/M
+> Brueghel/M
 > Bruis/M
-1445a2290
+1445c2310,2311
+< Brunelleschi
+---
+> Brunelleschi/M
 > Brunhilda/M
-1452a2298
+1447c2313
+< Bruno
+---
+> Bruno/M
+1452,1453c2318,2321
+< Bryan
+< Bryant
+---
+> Bryan/M
 > Bryana/M
-1453a2300
+> Bryant/M
 > Bryanty/M
-1454a2302,2306
+1454a2323,2327
 > Bryn/M
 > Bryna/M
 > Brynn/MR
 > Brynna/M
 > Brynne/M
-1464a2317
+1459c2332
+< Buber
+---
+> Buber/M
+1464,1465c2337,2339
+< Buck
+< Buckingham
+---
+> Buck/M
 > Buckie/M
-1467a2321
+> Buckingham/M
+1467a2342
 > Bucky/M
-1469a2324
+1469a2345
 > Budd/M
-1472a2328
+1472a2349
 > Buddie/M
-1479d2334
+1479d2355
 < Bugzilla/M
-1480a2336
+1480a2357
 > Buiron/M
-1499a2356,2358
+1482,1487c2359,2364
+< Bukhara
+< Bukharin
+< Bulawayo
+< Bulfinch
+< Bulganin
+< Bulgar
+---
+> Bukhara/M
+> Bukharin/M
+> Bulawayo/M
+> Bulfinch/M
+> Bulganin/M
+> Bulgar/M
+1495c2372
+< Bunche
+---
+> Bunche/M
+1497,1498c2374,2375
+< Bundestag
+< Bunin
+---
+> Bundestag/M
+> Bunin/M
+1500c2377,2380
+< Bunsen
+---
 > Bunni/M
 > Bunnie/M
 > Bunny/M
-1505a2365
+> Bunsen/M
+1503c2383
+< Burbank
+---
+> Burbank/M
+1505a2386
 > Burg/MR
-1510a2371
+1507c2388
+< Burgess
+---
+> Burgess/M
+1509c2390
+< Burgundian
+---
+> Burgundian/M
+1511,1512c2392,2394
+< Burke
+< Burks
+---
 > Burk/SM
-1512d2372
-< Burks
-1513a2374
+> Burke/M
+> Burks/M
+1513a2396
 > Burlie/M
-1516a2378,2379
+1517,1520c2400,2405
+< Burnett
+< Burns
+< Burnside
+< Burr
+---
 > Burnaby/M
 > Burnard/M
-1524a2388
+> Burnett/M
+> Burns/M
+> Burnside/M
+> Burr/M
+1522,1523c2407,2408
+< Burroughs
+< Bursa
+---
+> Burroughs/M
+> Bursa/M
+1524a2410
 > Burtie/M
-1525a2390
+1525a2412
 > Burty/M
-1531a2397
+1530c2417
+< Bushido
+---
+> Bushido/M
+1531a2419
 > Butch/M
-1537a2404,2406
+1538,1540c2426,2433
+< Byrd
+< Byron
+< Byronic
+---
 > Byram/M
 > Byran/M
 > Byrann/M
-1538a2408,2409
+> Byrd/M
 > Byrle/M
 > Byrom/M
-1543c2414
+> Byron/M
+> Byronic/M
+1543c2436
 < C/SM
 ---
 > C/SMDY
-1559c2430
+1553c2446
+< CBS
+---
+> CBS/M
+1559c2452
 < CEO/M
 ---
 > CEO/MS
-1561c2432
+1561c2454
 < CFC/M
 ---
 > CFC/MS
-1588a2460,2463
+1565c2458
+< CNN
+---
+> CNN/M
+1580a2474
+> CVS/M
+1585,1586c2479,2480
+< Cabot
+< Cabral
+---
+> Cabot/M
+> Cabral/M
+1588c2482,2486
+< Cabrini
+---
+> Cabrini/M
 > Cacilia/M
 > Cacilie/M
 > Cad/M
 > Caddric/M
-1598a2474
+1590c2488
+< Cadillac
+---
+> Cadillac/M
+1593c2491
+< Caerphilly
+---
+> Caerphilly/M
+1596c2494
+< Cage
+---
+> Cage/M
+1599c2497,2498
+< Caiaphas
+---
 > Cahra/M
-1600a2477
+> Caiaphas/M
+1600a2500
 > Cairistiona/M
-1602a2480
+1602a2503
 > Caitrin/M
-1605c2483
+1605,1606c2506,2507
 < Cal
----
-> Cal/Y
-1610a2489
+< Calais
+---
+> Cal/YM
+> Calais/M
+1610c2511,2512
+< Caldwell
+---
+> Caldwell/M
 > Cale/M
-1616a2496
+1612c2514
+< Caledonia
+---
+> Caledonia/M
+1614,1616c2516,2519
+< Calhoun
+< Cali
+< Caliban
+---
+> Calhoun/M
+> Cali/M
+> Caliban/M
 > Calida/M
-1620a2501
+1620,1621c2523,2525
+< Caligula
+< Callaghan
+---
+> Caligula/M
 > Calla/MS
-1624c2505,2508
+> Callaghan/M
+1623,1624c2527,2532
+< Callao
 < Callas
 ---
+> Callao/M
+> Callas/M
 > Callean/M
 > Calley/M
 > Calli/M
 > Callida/M
-1627a2512
+1627a2536
 > Cally/M
-1628a2514
+1628a2538
 > Calv/M
-1634a2521,2522
+1630c2540
+< Calvert
+---
+> Calvert/M
+1634a2545,2546
 > Calypso
 > Cam
-1635a2524
+1635a2548
 > Camala/M
-1641a2531,2532
+1642c2555,2557
+< Camelopardalis
+---
 > Camella/M
 > Camellia/M
-1647a2539,2542
+> Camelopardalis/M
+1647a2563,2566
 > Camey/M
 > Cami/M
 > Camila/M
 > Camile/M
-1649a2545,2547
+1649a2569,2571
 > Cammi/M
 > Cammie/M
 > Cammy/M
-1670a2569
+1652,1654c2574,2576
+< Campbell
+< Campinas
+< Campos
+---
+> Campbell/M
+> Campinas/M
+> Campos/M
+1656,1657c2578,2579
+< Camus
+< Can
+---
+> Camus/M
+> Can/M
+1664c2586
+< Canaletto
+---
+> Canaletto/M
+1666c2588
+< Canaveral
+---
+> Canaveral/M
+1670a2593
 > Candi/MS
-1671a2571
+1671a2595
 > Candida/M
-1672a2573,2574
+1672a2597,2598
 > Candie/M
 > Candra/M
-1699a2602
+1677c2603
+< Canopus
+---
+> Canopus/M
+1679c2605
+< Canterbury
+---
+> Canterbury/M
+1685,1686c2611,2612
+< Canute
+< Capablanca
+---
+> Canute/M
+> Capablanca/M
+1689,1690c2615,2616
+< Capet
+< Capetian
+---
+> Capet/M
+> Capetian/M
+1695,1697c2621,2623
+< Capitoline
+< Capone
+< Capote
+---
+> Capitoline/M
+> Capone/M
+> Capote/M
+1699a2626
 > Caprice/M
-1703a2607
+1702c2629
+< Capuchin
+---
+> Capuchin/M
+1703a2631
 > Car/MNY
-1706a2611
+1705c2633
+< Caracalla
+---
+> Caracalla/M
+1707c2635,2636
+< Caravaggio
+---
 > Caralie/M
-1710a2616
+> Caravaggio/M
+1710c2639,2640
+< Carborundum
+---
+> Carborundum/M
 > Carce/M
-1714a2621,2626
+1715c2645,2653
+< Carey
+---
 > Care/M
 > Caren/M
 > Carena/M
 > Caresa/M
 > Caressa/M
 > Caresse/M
-1715a2628,2629
+> Carey/M
 > Cari/M
 > Caria
-1717a2632,2635
+1718c2656,2662
+< Carina
+---
 > Carie/M
 > Caril/M
 > Carilyn/M
 > Carin/M
-1718a2637,2638
+> Carina/M
 > Carine/M
 > Cariotta/M
-1720c2640,2642
+1720c2664,2666
 < Carl/M
 ---
 > Carita/M
 > Caritta/M
 > Carl/GMN
-1721a2644,2646
+1721a2668,2670
 > Carlee/M
 > Carleen/M
 > Carlen/M
-1722a2648,2650
+1722a2672,2674
 > Carleton/M
 > Carley/M
 > Carlie/M
-1723a2652,2655
+1723a2676,2679
 > Carlina/M
 > Carline/M
 > Carling/M
 > Carlita/M
-1724a2657,2658
-> Carlota
+1725c2681,2684
+< Carlsbad
+---
+> Carlos/M
+> Carlota/M
 > Carlotta/M
-1728a2663
+> Carlsbad/M
+1727c2686
+< Carlton
+---
+> Carlton/M
+1729c2688,2694
+< Carlyle
+---
 > Carlye/M
-1729a2665,2669
+> Carlyle/M
 > Carlyn/M
 > Carlynn/M
 > Carlynne/M
 > Carma/M
-> Carmel
-1730a2671,2673
+> Carmel/M
+1730a2696,2698
 > Carmelia/M
 > Carmelina/M
 > Carmelita/M
-1731a2675
+1731a2700
 > Carmelle/M
-1733a2678
+1733a2703
 > Carmencita/M
-1734a2680
+1734a2705
 > Carmina/M
-1735a2682,2683
+1736c2707,2709
+< Carnap
+---
 > Carmita/M
 > Carmon/M
-1740a2689,2690
+> Carnap/M
+1740c2713,2715
+< Carnot
+---
+> Carnot/M
 > Carny/M
 > Caro/M
-1741a2692,2694
+1741a2717,2719
 > Carola/M
 > Carolan/M
 > Carolann/M
-1742a2696,2697
+1743,1745c2721,2725
+< Carolina
+< Caroline
+< Carolingian
+---
 > Carolee/M
 > Carolin/M
-1746a2702,2703
+> Carolina/M
+> Caroline/M
+> Carolingian/M
+1746a2727,2728
 > Caroljean/M
 > Carolus/M
-1747a2705,2707
+1747a2730,2732
 > Carolyne/M
 > Carolynn/M
 > Caron/M
-1752c2712,2714
-< Carrie/RM
----
+1749c2734,2735
+< Carpenter
+---
+> Carpathians/M
+> Carpenter/M
+1751a2738,2739
 > Carree/M
 > Carri/MR
-> Carrie/M
-1754a2717,2718
+1754a2743,2744
 > Carrissa/M
 > Carrol/M
-1755a2720
+1756c2746,2748
+< Carson
+---
 > Carry/M
-1756a2722
+> Carson/M
 > Cart/MR
-1765a2732,2733
+1758c2750
+< Cartesian
+---
+> Cartesian/M
+1761,1765c2753,2759
+< Cartier
+< Cartwright
+< Caruso
+< Carver
+< Cary
+---
+> Cartier/M
+> Cartwright/M
+> Caruso/M
+> Carver/M
+> Cary/M
 > Caryl/M
 > Caryn/M
-1769a2738
+1767c2761
+< Casals
+---
+> Casals/M
+1769a2764
 > Casar/M
-1773a2743,2744
+1773c2768,2770
+< Cash
+---
+> Cash/M
 > Casi/M
 > Casie/M
-1775a2747
+1775,1776c2772,2775
+< Caspar
+< Caspian
+---
+> Caspar/M
 > Casper/M
-1776a2749
+> Caspian/M
 > Cass/M
-1777a2751,2752
+1778c2777,2782
+< Cassatt
+---
 > Cassandre/M
 > Cassandry/M
-1778a2754,2756
+> Cassatt/M
 > Cassaundra/M
 > Cassey/M
 > Cassi/M
-1781a2760,2761
+1781a2786,2787
 > Cassondra/M
 > Cassy/M
-1791a2772
+1785c2791
+< Castlereagh
+---
+> Castlereagh/M
+1788c2794
+< Castro
+---
+> Castro/M
+1791a2798
 > Catarina/M
-1792a2774,2775
+1792a2800,2801
 > Cate/M
 > Caterina/M
-1793a2777,2779
+1793a2803,2805
 > Catha/M
 > Catharina/M
 > Catharine/M
-1795c2781,2784
+1795c2807,2811
 < Cather
 ---
 > Cathe/MR
 > Cathee/M
+> Cather/M
 > Catherin/M
 > Catherina/M
-1796a2786,2787
+1796a2813,2814
 > Cathi/M
 > Cathie/M
-1797a2789
+1797a2816
 > Cathlene/M
-1799a2792,2793
+1799a2819,2820
 > Cathrin/M
 > Cathrine/M
-1801a2796,2798
+1802,1803c2823,2833
+< Catiline
+< Cato
+---
 > Cathyleen/M
 > Cati/M
 > Catie/M
-1802a2800,2803
+> Catiline/M
 > Catina/M
 > Catlaina/M
 > Catlee/M
 > Catlin/M
-1803a2805,2806
+> Cato/M
 > Catrina/M
 > Catriona/M
-1807a2811
+1806,1807c2836,2838
+< Catt
+< Catullus
+---
+> Catt/M
+> Catullus/M
 > Caty/M
-1814a2819
+1811,1815c2842,2848
+< Cauchy
+< Cavendish
+< Cavour
+< Caxton
+< Cayenne
+---
+> Cauchy/M
+> Cavendish/M
+> Cavour/M
+> Caxton/M
 > Caye/M
-1815a2821
+> Cayenne/M
 > Cayla/M
-1818a2825,2826
+1818a2852,2853
 > Caz/M
 > Cazzie/M
-1819a2828
+1819a2855
 > Cchaddie/M
-1824a2834
+1824a2861
 > Cece/M
-1827a2838
+1826c2863
+< Cecil
+---
+> Cecil/M
+1828c2865,2869
+< Cecilia
+---
 > Ceciley/M
-1828a2840,2842
+> Cecilia/M
 > Cecilio/M
 > Cecilius/M
 > Cecilla/M
-1829a2844
+1829a2871
 > Ced/M
-1830a2846,2849
+1830a2873,2876
 > Ceil/M
 > Cele/M
 > Celene/M
 > Celesta/M
-1832a2852,2856
+1832a2879,2883
 > Celestia/M
 > Celestina/M
 > Celestine/M
 > Celestyn/M
 > Celestyna/M
-1833a2858
+1833a2885
 > Celie/M
-1834a2860,2865
+1835,1836c2887,2895
+< Cellini
+< Celsius
+---
 > Celinda/M
 > Celine/M
 > Celinka/M
 > Celisse/M
 > Celka/M
 > Celle/M
-1835a2867
+> Cellini/M
 > Cello/M
-1850a2883
+> Celsius/M
+1843c2902
+< Cepheid
+---
+> Cepheid/M
+1846c2905
+< Cerenkov
+---
+> Cerenkov/M
+1850a2910
 > Cesare/M
-1851a2885
+1852c2912,2913
+< Cesarian
+---
 > Cesaro/M
-1853a2888
+> Cesarian/M
+1854c2915,2916
+< Cetus
+---
 > Cesya/M
-1860c2895
+> Cetus/M
+1857c2919
+< Cezanne
+---
+> Cezanne/M
+1859,1860c2921,2922
+< Ch'in
 < Ch/N
 ---
+> Ch'in/M
 > Ch/NRS
-1862a2898,2900
+1862a2925,2927
 > Chadd/M
 > Chaddie/M
 > Chaddy/M
-1865a2904
+1864,1865c2929,2931
+< Chadwick
+< Chagall
+---
+> Chadwick/M
+> Chagall/M
 > Chaim/M
-1870a2910
+1869c2935
+< Chaldean
+---
+> Chaldean/M
+1871,1874c2937,2941
+< Chamberlain
+< Chambers
+< Champlain
+< Champollion
+---
 > Chalmers
-1877a2918,2920
+> Chamberlain/M
+> Chambers/M
+> Champlain/M
+> Champollion/M
+1878,1879c2945,2949
+< Chandigarh
+< Chandler
+---
 > Chancey/M
 > Chanda/M
 > Chandal/M
-1883a2927
+> Chandigarh/M
+> Chandler/M
+1882c2952
+< Chandragupta
+---
+> Chandragupta/M
+1884c2954,2955
+< Chanel
+---
 > Chane/M
-1888a2933,2935
+> Chanel/M
+1887,1889c2958,2963
+< Changchun
+< Changsha
+< Chantilly
+---
+> Changchun/M
+> Changsha/M
 > Channa/M
 > Chantal/M
 > Chantalle/M
-1895a2943
+> Chantilly/M
+1892,1893c2966,2967
+< Chaplin
+< Chapman
+---
+> Chaplin/M
+> Chapman/M
+1895a2970
 > Chara
-1897a2946,2952
+1897a2973,2979
 > Charil/M
 > Charin/M
 > Chariot/M
-> Charis
+> Charis/M
 > Charissa/M
 > Charisse/M
 > Charita/M
-1898a2954,2956
+1898a2981,2983
 > Charla/M
 > Charlean/M
 > Charleen/M
-1899a2958
+1899a2985
 > Charlena/M
-1904a2964,2966
+1903,1904c2989,2993
+< Charley
+< Charlie
+---
+> Charley/M
+> Charlie/M
 > Charline/M
 > Charlot/M
 > Charlotta/M
-1906a2969,2970
-> Charlton
+1906a2996,2997
+> Charlton/M
 > Charmain/M
-1907a2972,2973
+1907a2999,3000
 > Charmane/M
 > Charmian/M
-1908a2975,2977
+1908a3002,3004
 > Charmine/M
 > Charmion/M
 > Charo/M
-1913a2983,2984
+1912c3008
+< Chartres
+---
+> Chartres/M
+1914c3010,3012
+< Chase
+---
 > Charyl/M
-> Chas
-1915a2987
+> Chas/M
+> Chase/M
+1915a3014
 > Chastity/M
-1921a2994
+1920c3019
+< Chatterton
+---
+> Chatterton/M
+1921a3021
 > Chaunce/M
-1935a3009
+1923c3023
+< Chautauqua
+---
+> Chautauqua/M
+1927c3027
+< Chechen
+---
+> Chechen/M
+1929c3029
+< Cheddar
+---
+> Cheddar/M
+1933c3033
+< Cheever
+---
+> Cheever/M
+1936c3036,3040
+< Chelsea
+---
 > Chelsae/M
-1936a3011,3013
+> Chelsea/M
 > Chelsey/M
 > Chelsie/M
 > Chelsy/M
-1942a3020,3021
+1942c3046,3048
+< Cheops
+---
+> Cheops/M
 > Chere/M
 > Cherey/M
-1943a3023,3025
+1943a3050,3052
 > Cherianne/M
 > Cherice/M
 > Cherida/M
-1944a3027,3032
+1944a3054,3059
 > Cherilyn/M
 > Cherilynn/M
 > Cherin/M
 > Cherise/M
 > Cherish/M
 > Cherlyn/M
-1948a3037,3038
+1948a3064,3065
 > Cherri/M
 > Cherrita/M
-1949a3040,3041
+1949a3067,3068
 > Chery/M
 > Cherye/M
-1952a3045
+1951,1952c3070,3072
+< Chesapeake
+< Cheshire
+---
+> Chesapeake/M
+> Cheshire/M
 > Cheslie/M
-1955a3049,3051
+1954,1956c3074,3079
+< Chesterfield
+< Chesterton
+< Chevalier
+---
+> Chesterfield/M
+> Chesterton/M
 > Cheston/M
 > Chet/M
 > Chev/M
-1963a3060
+> Chevalier/M
+1964,1965c3087,3090
+< Chiba
+< Chibcha
+---
 > Chiarra/M
-1965a3063
+> Chiba/M
+> Chibcha/M
 > Chic/M
-1969a3068
+1967,1969c3092,3095
+< Chicagoan
+< Chicana
+< Chicano
+---
+> Chicagoan/M
+> Chicana/M
+> Chicano/M
 > Chick/M
-1970a3070,3071
+1970a3097,3098
 > Chickie/M
 > Chicky/M
-1971a3073
+1971a3100
 > Chico/M
-1974a3077
+1974a3104
 > Chilton/M
-1982a3086
+1980c3110
+< Chinatown
+---
+> Chinatown/M
+1982a3113
 > Chip/M
-1985a3090
+1985a3117
 > Chiquia/M
-1991a3097
+1987c3119
+< Chirico
+---
+> Chirico/M
+1990c3122
+< Chittagong
+---
+> Chittagong/M
+1992c3124,3127
+< Chloe
+---
 > Chlo/M
-1992a3099,3100
+> Chloe/M
 > Chloette/M
 > Chloris/M
-2001c3109,3112
+1994,1995c3129,3130
+< Chomsky
+< Chongqing
+---
+> Chomsky/M
+> Chongqing/M
+1998c3133
+< Chou
+---
+> Chou/M
+2001c3136,3139
 < Christ/MS
 ---
 > Chrisse/M
 > Chrissie/M
 > Chrissy/M
 > Christ/MNS
-2002a3114,3118
+2003,2004c3141,3150
+< Christchurch
+< Christendom/SM
+---
 > Christabel/M
 > Christabella/M
 > Christal/M
 > Christalle/M
 > Christan/M
-2003a3120,3122
+> Christchurch/M
 > Christean/M
 > Christel/M
 > Christen/M
-2007a3127,3128
+> Christendom/MS
+2007a3154,3155
 > Christiana/M
 > Christiane/M
-2009c3130,3131
+2009,2011c3157,3161
 < Christianize
+< Christie
+< Christina
 ---
 > Christianize/DSG
 > Christiano/M
-2010a3133
+> Christie/M
 > Christin/M
-2016a3140,3141
+> Christina/M
+2016a3167,3168
 > Christoffer/M
 > Christoforo/M
-2017a3143,3144
+2017a3170,3171
 > Christoph/MR
-> Christophe
-2019c3146,3150
+> Christophe/M
+2019c3173,3177
 < Christy
 ---
 > Christophorus/M
 > Christos/M
 > Christye/M
 > Christyna/M
 > Chrisy/M
-2020a3152,3153
+2020a3179,3180
 > Chrotoem/M
 > Chrysa/M
-2023a3157,3159
+2022c3182
+< Chrysostom
+---
+> Chrysostom/M
+2023a3184,3186
 > Chryste/M
 > Chrystel/M
 > Chucho/M
-2033a3170
+2025,2026c3188,3189
+< Chukchi
+< Chumash
+---
+> Chukchi/M
+> Chumash/M
+2029c3192
+< Church
+---
+> Church/M
+2033c3196,3197
+< Ci
+---
+> Ci/M
 > Cicely/M
-2034a3172
+2035c3199,3202
+< Cid
+---
 > Cicily/M
-2035a3174,3175
+> Cid/M
 > Ciel/M
 > Cilka/M
-2037a3178,3180
+2037c3204,3207
+< Cincinnati
+---
+> Cincinnati/M
 > Cinda/M
 > Cindee/M
 > Cindelyn/M
-2038a3182,3184
+2038a3209,3211
 > Cindi/M
 > Cindie/M
 > Cindra/M
-2041a3188
+2041c3214,3215
+< Cinerama
+---
+> Cinerama/M
 > Cinnamon/M
-2043a3191,3193
+2043a3218,3220
 > Cirillo/M
 > Cirilo/M
 > Ciro/M
-2044a3195,3196
+2044a3222,3223
 > Cissiee/M
 > Cissy/M
-2048a3201
+2048a3228
 > Claiborn/M
-2056a3210,3211
+2057c3237,3239
+< Clare
+---
 > Clarabelle/M
 > Clarance/M
-2059a3215,3221
+> Clare/M
+2059c3241,3248
+< Clarendon
+---
+> Clarendon/M
 > Claresta/M
 > Clareta/M
 > Claretta/M
 > Clarette/M
 > Clarey/M
 > Clari/M
 > Claribel/M
-2060a3223,3225
+2060a3250,3252
 > Clarie/M
 > Clarinda/M
 > Clarine/M
-2061a3227,3228
+2062c3254,3256
+< Clark
+---
 > Clarisse/M
 > Clarita/M
-2063a3231
+> Clark/M
+2063a3258
 > Clary/M
-2064a3233,3235
+2064a3260,3262
 > Claudell/M
 > Claudelle/M
 > Claudetta/M
-2066a3238,3241
+2066a3265,3268
 > Claudian/M
 > Claudianus/M
 > Claudie/M
 > Claudina/M
-2073a3249,3252
+2071,2073c3273,3279
+< Clausewitz
+< Clausius
+< Clay
+---
+> Clausewitz/M
+> Clausius/M
+> Clay/M
 > Clayborn/M
 > Clayborne/M
 > Claybourne/M
 > Clayson/M
-2074a3254
+2074a3281
 > Clea/M
-2075a3256
+2075a3283
 > Cleavland/M
-2076a3258
+2077c3285,3287
+< Clemenceau
+---
 > Clemence/M
-2078a3261,3263
+> Clemenceau/M
+> Clemens/M
+2078a3289,3292
 > Clemente/M
+> Clementes/M
 > Clementia/M
 > Clementina/M
-2079a3265,3267
+2080c3294,3297
+< Clemons
+---
 > Clementius/M
 > Clemmie/M
 > Clemmy/M
-2082a3271
-> Cleon
-2083a3273,3277
+> Clemons/M
+2082a3300
+> Cleon/M
+2083a3302,3306
 > Clerc/M
 > Clerissa/M
-> Cletis
+> Cletis/M
 > Cletus/M
 > Cleve/M
-2084a3279,3280
+2084a3308,3309
 > Clevey/M
 > Clevie/M
-2088a3285
+2087c3312
+< Clifford
+---
+> Clifford/M
+2088a3314
 > Clim/M
-2092a3290,3291
+2092a3319,3321
+> Clive/M
 > Clo/M
 > Cloe/M
-2093a3293
+2093a3323
 > Cloris/M
-2095a3296
+2094a3325
+> Closure/M
+2095a3327
 > Clotilda/M
-2097a3299
+2098c3330,3331
+< Clyde
+---
 > Cly/M
-2100a3303,3304
+> Clyde/M
+2100c3333,3335
+< Clytemnestra
+---
+> Clytemnestra/M
 > Clyve/M
 > Clywd/M
-2103c3307,3308
+2103c3338,3339
 < Co/M
 ---
 > Co/SM
 > Cob/M
-2105a3311,3312
+2105,2108c3341,3346
+< Cobb
+< Cochabamba
+< Cochin
+< Cochise
+---
+> Cobb/M
 > Cobbie/M
 > Cobby/M
-2112a3320,3322
+> Cochabamba/M
+> Cochin/M
+> Cochise/M
+2111c3349
+< Cocteau
+---
+> Cocteau/M
+2113c3351,3354
+< Cody
+---
 > Codee/M
 > Codi/M
 > Codie/M
-2118a3329
+> Cody/M
+2116,2119c3357,3361
+< Cohan
+< Cohen
+< Coimbatore
+< Cointreau
+---
+> Cohan/M
+> Cohen/M
+> Coimbatore/M
 > Cointon/M
-2121a3333,3334
+> Cointreau/M
+2121c3363,3365
+< Col
+---
+> Col/M
 > Colan/M
-> Colas
-2126a3340
+> Colas/M
+2123,2124c3367,3368
+< Colby
+< Cole
+---
+> Colby/M
+> Cole/M
+2126a3371
 > Colene/M
-2127a3342,3343
-> Colet
+2128c3373,3375
+< Colette
+---
+> Colet/M
 > Coletta/M
-2132a3349,3352
+> Colette/M
+2132a3380,3383
 > Collen/M
 > Collete/M
 > Collette/M
 > Collie/M
-2134a3355,3357
+2134a3386,3389
+> Collins/M
 > Colline/M
 > Colly/RM
 > Colman/M
-2150a3374
+2145c3400
+< Colosseum
+---
+> Colosseum/M
+2147c3402
+< Coltrane
+---
+> Coltrane/M
+2149c3404
+< Columbine
+---
+> Columbine/M
+2150a3406
 > Colver/M
-2167a3392
+2155,2156c3411,3412
+< Comintern
+< Commons
+---
+> Comintern/M
+> Commons/M
+2161c3417
+< Como
+---
+> Como/M
+2165c3421
+< Compton
+---
+> Compton/M
+2167c3423,3424
+< Comte
+---
+> Comte/M
 > Con
-2169a3395
+2170c3427,3428
+< Concepcion
+---
 > Conant/M
-2171a3398,3399
+> Concepcion/M
+2171a3430,3431
 > Concettina/M
 > Conchita/M
-2173a3402
+2173,2175c3433,3436
+< Concorde
+< Condillac
+< Condorcet
+---
+> Concorde/M
 > Concordia/M
-2195a3425,3426
+> Condillac/M
+> Condorcet/M
+2182c3443
+< Cong
+---
+> Cong/M
+2189c3450
+< Congreve
+---
+> Congreve/M
+2191c3452
+< Conn/R
+---
+> Conn/MR
+2193c3454
+< Connemara
+---
+> Connemara/M
+2195a3457,3458
 > Conney/M
 > Conni/M
-2198c3429,3430
+2198,2199c3461,3466
 < Connors
+< Conrad
 ---
 > Connor/SM
+> Connors/M
 > Conny/M
-2199a3432,3433
+> Conrad/M
 > Conrade/M
 > Conrado/M
-2200a3435,3436
+2200a3468,3469
 > Conroy/M
 > Consalve/M
-2201a3438
+2202,2204c3471,3481
+< Constable
+< Constance
+< Constantine
+---
 > Consolata/M
-2203a3441,3446
+> Constable/M
+> Constance/M
 > Constancia/M
 > Constancy/M
 > Constanta/M
 > Constantia
 > Constantin/M
 > Constantina/M
-2204a3448
+> Constantine/M
 > Constantino/M
-2206a3451
+2206a3484
 > Consuela/M
-2213a3459
+2209c3487
+< Continental
+---
+> Continental/M
+2211,2212c3489,3490
+< Conway
+< Cook
+---
+> Conway/M
+> Cook/M
+2213a3492
 > Cookie/M
-2216c3462
+2216c3495
 < Cooper
 ---
 > Coop/MR
-2230a3477,3489
+2222c3501
+< Copernican
+---
+> Copernican/M
+2224,2225c3503,3504
+< Copland
+< Copley
+---
+> Copland/M
+> Copley/M
+2230a3510,3522
 > Corabel/M
 > Corabella/M
 > Corabelle/M
 > Coral/M
 > Coralie/M
 > Coraline/M
 > Coralyn/M
 > Corbet/M
 > Corbett/M
 > Corbie/M
 > Corbin/M
-> Corby
+> Corby/M
 > Cord/M
-2231a3491,3495
+2232c3524,3529
+< Cordilleras
+---
 > Cordelie/M
 > Cordell/M
 > Cordey/M
 > Cordi/M