Merge MC->JM
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 08 Sep 2011 09:59:59 -0700
changeset 77056 cc669ae63634a25e03f44523e02816ea720c0579
parent 77055 b68281262e15166ebdf7c0085c1637e101bb571d (current diff)
parent 76714 4be2da039559773ee412fce9aa22c007718a4cb3 (diff)
child 77057 c1f0817e5cb4877273b90f6c5d07be9043d09413
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
milestone9.0a1
Merge MC->JM
js/src/jsapi-tests/testGCChunkAlloc.cpp
js/src/jsfun.cpp
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jstracer.cpp
js/src/methodjit/BaseAssembler.h
js/src/methodjit/MethodJIT.cpp
js/src/methodjit/MethodJIT.h
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -7,19 +7,20 @@
   top: 0;
   left: 0;
 }
 
 #highlighter-veil-container {
   overflow: hidden;
 }
 
-.highlighter-veil,
-#highlighter-veil-middlebox,
-#highlighter-veil-transparentbox {
+#highlighter-veil-container:not([locked]) > .highlighter-veil,
+#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox,
+#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox > .highlighter-veil,
+#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
   -moz-transition-property: width, height;
   -moz-transition-duration: 0.1s;
   -moz-transition-timing-function: linear;
 }
 
 #highlighter-veil-bottombox,
 #highlighter-veil-rightbox {
   -moz-box-flex: 1;
--- a/browser/base/content/inspector.js
+++ b/browser/base/content/inspector.js
@@ -105,31 +105,31 @@ Highlighter.prototype = {
     this.browser = aBrowser;
     let stack = this.browser.parentNode;
     this.win = this.browser.contentWindow;
     this._highlighting = false;
 
     this.highlighterContainer = document.createElement("stack");
     this.highlighterContainer.id = "highlighter-container";
 
-    let veilBox = document.createElement("vbox");
-    veilBox.id = "highlighter-veil-container";
+    this.veilContainer = document.createElement("vbox");
+    this.veilContainer.id = "highlighter-veil-container";
 
     let controlsBox = document.createElement("box");
     controlsBox.id = "highlighter-controls";
 
     // The veil will make the whole page darker except
     // for the region of the selected box.
-    this.buildVeil(veilBox);
+    this.buildVeil(this.veilContainer);
 
     // The controlsBox will host the different interactive
     // elements of the highlighter (buttons, toolbars, ...).
     this.buildControls(controlsBox);
 
-    this.highlighterContainer.appendChild(veilBox);
+    this.highlighterContainer.appendChild(this.veilContainer);
     this.highlighterContainer.appendChild(controlsBox);
 
     stack.appendChild(this.highlighterContainer);
 
     this.browser.addEventListener("resize", this, true);
     this.browser.addEventListener("scroll", this, true);
 
     this.handleResize();
@@ -218,16 +218,17 @@ Highlighter.prototype = {
     this.browser.removeEventListener("scroll", this, true);
     this.browser.removeEventListener("resize", this, true);
     this._highlightRect = null;
     this._highlighting = false;
     this.veilTopBox = null;
     this.veilLeftBox = null;
     this.veilMiddleBox = null;
     this.veilTransparentBox = null;
+    this.veilContainer = null;
     this.node = null;
     this.highlighterContainer.parentNode.removeChild(this.highlighterContainer);
     this.highlighterContainer = null;
     this.win = null
     this.browser = null;
     this.toolbar = null;
   },
 
@@ -920,17 +921,17 @@ var InspectorUI = {
     // if currently editing an attribute value, starting
     // "live inspection" mode closes the editor
     if (this.editingContext)
       this.closeEditor();
 
     document.getElementById("inspector-inspect-toolbutton").checked = true;
     this.attachPageListeners();
     this.inspecting = true;
-    this.highlighter.veilTransparentBox.removeAttribute("locked");
+    this.highlighter.veilContainer.removeAttribute("locked");
   },
 
   /**
    * Stop inspecting webpage, detach page listeners, disable highlighter
    * event listeners.
    * @param aPreventScroll
    *        Prevent scroll in the HTML tree?
    */
@@ -943,17 +944,17 @@ var InspectorUI = {
     document.getElementById("inspector-inspect-toolbutton").checked = false;
     this.detachPageListeners();
     this.inspecting = false;
     if (this.highlighter.node) {
       this.select(this.highlighter.node, true, true, !aPreventScroll);
     } else {
       this.select(null, true, true);
     }
-    this.highlighter.veilTransparentBox.setAttribute("locked", true);
+    this.highlighter.veilContainer.setAttribute("locked", true);
   },
 
   /**
    * Select an object in the tree view.
    * @param aNode
    *        node to inspect
    * @param forceUpdate
    *        force an update?
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1031,17 +1031,17 @@ nsContextMenu.prototype = {
     this.saveHelper(this.linkURL, this.linkText(), null, true, doc);
   },
 
   sendLink: function() {
     // we don't know the title of the link so pass in an empty string
     MailIntegration.sendMessage( this.linkURL, "" );
   },
 
-  // Backwards-compatability wrapper
+  // Backwards-compatibility wrapper
   saveImage : function() {
     if (this.onCanvas || this.onImage)
         this.saveMedia();
   },
 
   // Save URL of the clicked upon image, video, or audio.
   saveMedia: function() {
     var doc =  this.target.ownerDocument;
@@ -1057,17 +1057,17 @@ nsContextMenu.prototype = {
     }
     else if (this.onVideo || this.onAudio) {
       urlSecurityCheck(this.mediaURL, doc.nodePrincipal);
       var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle";
       this.saveHelper(this.mediaURL, null, dialogTitle, false, doc);
     }
   },
 
-  // Backwards-compatability wrapper
+  // Backwards-compatibility wrapper
   sendImage : function() {
     if (this.onCanvas || this.onImage)
         this.sendMedia();
   },
 
   sendMedia: function() {
     MailIntegration.sendMessage(this.mediaURL, "");
   },
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4034,21 +4034,24 @@
       <handler event="mouseout">
         var anonid = event.originalTarget.getAttribute("anonid");
         if (anonid == "close-button")
           this.mOverCloseButton = false;
       </handler>
       <handler event="dragstart" phase="capturing">
         this.style.MozUserFocus = '';
       </handler>
-      <handler event="mousedown">
+      <handler event="mousedown" phase="capturing">
       <![CDATA[
         if (this.selected) {
           this.style.MozUserFocus = 'ignore';
           this.clientTop; // just using this to flush style updates
+        } else if (this.mOverCloseButton) {
+          // Prevent tabbox.xml from selecting the tab.
+          event.stopPropagation();
         }
       ]]>
       </handler>
       <handler event="mouseup">
         this.style.MozUserFocus = '';
       </handler>
     </handlers>
   </binding>
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -706,33 +706,44 @@ GroupItem.prototype = Utils.extend(new I
         }
       });
 
       this.droppable(false);
       this.removeTrenches();
       this._createUndoButton();
     } else
       this.close();
-    
-    this._makeClosestTabActive();
+
+    this._makeLastActiveGroupItemActive();
   },
   
   // ----------
   // Function: _makeClosestTabActive
   // Make the closest tab external to this group active.
   // Used when closing the group.
   _makeClosestTabActive: function GroupItem__makeClosestTabActive() {
     let closeCenter = this.getBounds().center();
     // Find closest tab to make active
     let closestTabItem = UI.getClosestTab(closeCenter);
     if (closestTabItem)
       UI.setActive(closestTabItem);
   },
 
   // ----------
+  // Function: _makeLastActiveGroupItemActive
+  // Makes the last active group item active.
+  _makeLastActiveGroupItemActive: function GroupItem__makeLastActiveGroupItemActive() {
+    let groupItem = GroupItems.getLastActiveGroupItem();
+    if (groupItem)
+      UI.setActive(groupItem);
+    else
+      this._makeClosestTabActive();
+  },
+
+  // ----------
   // Function: closeIfEmpty
   // Closes the group if it's empty, is closable, and autoclose is enabled
   // (see pauseAutoclose()). Returns true if the close occurred and false
   // otherwise.
   closeIfEmpty: function GroupItem_closeIfEmpty() {
     if (this.isEmpty() && !UI._closedLastVisibleTab &&
         !GroupItems.getUnclosableGroupItemId() && !GroupItems._autoclosePaused) {
       this.close();
@@ -1144,19 +1155,19 @@ GroupItem.prototype = Utils.extend(new I
         item.setResizable(true, options.immediately);
 
       // if a blank tab is selected while restoring a tab the blank tab gets
       // removed. we need to keep the group alive for the restored tab.
       if (item.isRemovedAfterRestore)
         options.dontClose = true;
 
       let closed = options.dontClose ? false : this.closeIfEmpty();
-      if (closed)
-        this._makeClosestTabActive();
-      else if (!options.dontArrange) {
+      if (closed) {
+        this._makeLastActiveGroupItemActive();
+      } else if (!options.dontArrange) {
         this.arrange({animate: !options.immediately});
         this._unfreezeItemSize({dontArrange: true});
       }
 
       this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
     } catch(e) {
       Utils.log(e);
     }
@@ -1939,16 +1950,17 @@ let GroupItems = {
   _cleanupFunctions: [],
   _arrangePaused: false,
   _arrangesPending: [],
   _removingHiddenGroups: false,
   _delayedModUpdates: [],
   _autoclosePaused: false,
   minGroupHeight: 110,
   minGroupWidth: 125,
+  _lastActiveList: null,
 
   // ----------
   // Function: toString
   // Prints [GroupItems] for debug use
   toString: function GroupItems_toString() {
     return "[GroupItems count=" + this.groupItems.length + "]";
   },
 
@@ -1964,16 +1976,18 @@ let GroupItems = {
 
     // make sure any closed tabs are removed from the delay update list
     function handleClose(event) {
       let idx = self._delayedModUpdates.indexOf(event.target);
       if (idx != -1)
         self._delayedModUpdates.splice(idx, 1);
     }
 
+    this._lastActiveList = new MRUList();
+
     AllTabs.register("attrModified", handleAttrModified);
     AllTabs.register("close", handleClose);
     this._cleanupFunctions.push(function() {
       AllTabs.unregister("attrModified", handleAttrModified);
       AllTabs.unregister("close", handleClose);
     });
   },
 
@@ -2307,16 +2321,17 @@ let GroupItems = {
 
     if (groupItem == this._activeGroupItem)
       this._activeGroupItem = null;
 
     this._arrangesPending = this._arrangesPending.filter(function (pending) {
       return groupItem != pending.groupItem;
     });
 
+    this._lastActiveList.remove(groupItem);
     UI.updateTabButton();
   },
 
   // ----------
   // Function: groupItem
   // Given some sort of identifier, returns the appropriate groupItem.
   // Currently only supports groupItem ids.
   groupItem: function GroupItems_groupItem(a) {
@@ -2418,21 +2433,32 @@ let GroupItems = {
   setActiveGroupItem: function GroupItems_setActiveGroupItem(groupItem) {
     Utils.assert(groupItem, "groupItem must be given");
 
     if (this._activeGroupItem)
       iQ(this._activeGroupItem.container).removeClass('activeGroupItem');
 
     iQ(groupItem.container).addClass('activeGroupItem');
 
+    this._lastActiveList.update(groupItem);
     this._activeGroupItem = groupItem;
     this._save();
   },
 
   // ----------
+  // Function: getLastActiveGroupItem
+  // Gets last active group item.
+  // Returns the <groupItem>. If nothing is found, return null.
+  getLastActiveGroupItem: function GroupItem_getLastActiveGroupItem() {
+    return this._lastActiveList.peek(function(groupItem) {
+      return (groupItem && !groupItem.hidden && groupItem.getChildren().length > 0)
+    });
+  },
+
+  // ----------
   // Function: _updateTabBar
   // Hides and shows tabs in the tab bar based on the active groupItem
   _updateTabBar: function GroupItems__updateTabBar() {
     if (!window.UI)
       return; // called too soon
 
     Utils.assert(this._activeGroupItem, "There must be something to show in the tab bar!");
 
--- a/browser/base/content/tabview/modules/utils.jsm
+++ b/browser/base/content/tabview/modules/utils.jsm
@@ -45,17 +45,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 "use strict";
 
 // **********
 // Title: utils.js
 
-let EXPORTED_SYMBOLS = ["Point", "Rect", "Range", "Subscribable", "Utils"];
+let EXPORTED_SYMBOLS = ["Point", "Rect", "Range", "Subscribable", "Utils", "MRUList"];
 
 // #########
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 
 // ##########
@@ -790,8 +790,68 @@ let Utils = {
       try {
         return args[i]();
       } catch (e) {}
     }
 
     return null;
   }
 };
+
+// ##########
+// Class: MRUList
+// A most recently used list.
+//
+// Constructor: MRUList
+// If a is an array of entries, creates a copy of it.
+function MRUList(a) {
+  if (Array.isArray(a))
+    this._list = a.concat();
+  else
+    this._list = [];
+};
+
+MRUList.prototype = {
+  // ----------
+  // Function: toString
+  // Prints [List (entry1, entry2, ...)] for debug use
+  toString: function MRUList_toString() {
+    return "[List (" + this._list.join(", ") + ")]";
+  },
+
+  // ----------
+  // Function: update
+  // Updates/inserts the given entry as the most recently used one in the list.
+  update: function MRUList_update(entry) {
+    this.remove(entry);
+    this._list.unshift(entry);
+  },
+
+  // ----------
+  // Function: remove
+  // Removes the given entry from the list.
+  remove: function MRUList_remove(entry) {
+    let index = this._list.indexOf(entry);
+    if (index > -1)
+      this._list.splice(index, 1);
+  },
+
+  // ----------
+  // Function: peek
+  // Returns the most recently used entry.  If a filter exists, gets the most 
+  // recently used entry which matches the filter.
+  peek: function MRUList_peek(filter) {
+    let match = null;
+    if (filter && typeof filter == "function")
+      this._list.some(function MRUList_peek_getEntry(entry) {
+        if (filter(entry)) {
+          match = entry
+          return true;
+        }
+        return false;
+      });
+    else 
+      match = this._list.length > 0 ? this._list[0] : null;
+
+    return match;
+  },
+};
+
--- a/browser/base/content/test/browser_sanitize-download-history.js
+++ b/browser/base/content/test/browser_sanitize-download-history.js
@@ -68,17 +68,17 @@ function test()
   {
     let doc = aWin.document;
     let downloads = doc.getElementById("downloads-checkbox");
     let history = doc.getElementById("history-checkbox");
 
     // Add download to DB
     let file = Cc["@mozilla.org/file/directory_service;1"].
                getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
-    file.append("satitize-dm-test.file");
+    file.append("sanitize-dm-test.file");
     file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
     let testPath = Services.io.newFileURI(file).spec;
     let data = {
       name: "381603.patch",
       source: "https://bugzilla.mozilla.org/attachment.cgi?id=266520",
       target: testPath,
       startTime: 1180493839859230,
       endTime: 1180493839859239,
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -125,16 +125,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug630157.js \
                  browser_tabview_bug631662.js \
                  browser_tabview_bug631752.js \
                  browser_tabview_bug633788.js \
                  browser_tabview_bug634077.js \
                  browser_tabview_bug634085.js \
                  browser_tabview_bug634672.js \
                  browser_tabview_bug635696.js \
+                 browser_tabview_bug637840.js \
                  browser_tabview_bug640765.js \
                  browser_tabview_bug641802.js \
                  browser_tabview_bug642793.js \
                  browser_tabview_bug643392.js \
                  browser_tabview_bug644097.js \
                  browser_tabview_bug648882.js \
                  browser_tabview_bug649006.js \
                  browser_tabview_bug649307.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug637840.js
@@ -0,0 +1,92 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let cw;
+
+function test() {
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function(win) {
+    registerCleanupFunction(function() {
+      win.close();
+    });
+
+    cw = win.TabView.getContentWindow();
+
+    let groupItemOne = cw.GroupItems.groupItems[0];
+    is(groupItemOne.getChildren().length, 1, "Group one has 1 tab item");
+
+    let groupItemTwo = createGroupItemWithBlankTabs(win, 300, 300, 40, 2);
+    is(groupItemTwo.getChildren().length, 2, "Group two has 2 tab items");
+
+    let groupItemThree = createGroupItemWithBlankTabs(win, 300, 300, 40, 2);
+    is(groupItemThree.getChildren().length, 2, "Group three has 2 tab items");
+
+    testMoreRecentlyUsedGroup(groupItemOne, groupItemTwo, function() {
+      testMoreRecentlyUsedGroup(groupItemOne, groupItemThree, function() {
+        testRemoveGroupAndCheckMoreRecentlyUsedGroup(groupItemOne, groupItemTwo);
+      });
+    });
+  });
+}
+
+function testMoreRecentlyUsedGroup(groupItemOne, otherGroupItem, callback) {
+  let tabItem = otherGroupItem.getChild(1);
+  cw.UI.setActive(tabItem);
+  is(otherGroupItem.getActiveTab(), tabItem, "The second item in the other group is active");
+  is(cw.GroupItems.getActiveGroupItem(), otherGroupItem, "The other group is active");
+
+  let tabItemInGroupItemOne = groupItemOne.getChild(0);
+  cw.UI.setActive(tabItemInGroupItemOne);
+  is(groupItemOne.getActiveTab(), tabItemInGroupItemOne, "The first item in group one is active");
+  is(cw.GroupItems.getActiveGroupItem(), groupItemOne, "The group one is active");
+
+  groupItemOne.addSubscriber("groupHidden", function onHide() {
+    groupItemOne.removeSubscriber("groupHidden", onHide);
+
+    // group item three should have the focus
+    is(otherGroupItem.getActiveTab(), tabItem, "The second item in the other group is active after group one is hidden");
+    is(cw.GroupItems.getActiveGroupItem(), otherGroupItem, "The other group is active active after group one is hidden");
+
+    groupItemOne.addSubscriber("groupShown", function onShown() {
+      groupItemOne.removeSubscriber("groupShown", onShown);
+
+      is(groupItemOne.getActiveTab(), tabItemInGroupItemOne, "The first item in group one is active after it is shown");
+      is(cw.GroupItems.getActiveGroupItem(), groupItemOne, "The group one is active after it is shown");
+
+      callback();
+    });
+    // click on the undo button
+    EventUtils.sendMouseEvent(
+      { type: "click" }, groupItemOne.$undoContainer[0], cw);
+  });
+  // click on the close button of group item one
+  let closeButton = groupItemOne.container.getElementsByClassName("close");
+  ok(closeButton[0], "Group item one close button exists");
+  EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], cw);
+}
+
+function testRemoveGroupAndCheckMoreRecentlyUsedGroup(groupItemOne, groupItemTwo) {
+  let tabItem = groupItemTwo.getChild(0);
+  cw.UI.setActive(tabItem);
+
+  is(groupItemTwo.getActiveTab(), tabItem, "The first item in the group two is active");
+  is(cw.GroupItems.getActiveGroupItem(), groupItemTwo, "The group two is active");
+
+  let tabItemInGroupItemOne = groupItemOne.getChild(0);
+
+  tabItemInGroupItemOne.addSubscriber("close", function onClose() {
+    tabItemInGroupItemOne.removeSubscriber("close", onClose);
+
+    is(groupItemTwo.getActiveTab(), tabItem, "The first item in the group two is still active after group one is closed");
+    is(cw.GroupItems.getActiveGroupItem(), groupItemTwo, "The group two is still active after group one is closed");
+
+    finish();
+  });
+  // close the tab item and the group item
+  let closeButton = tabItemInGroupItemOne.container.getElementsByClassName("close");
+  ok(closeButton[0], "Tab item close button exists");
+  EventUtils.sendMouseEvent({ type: "mousedown" }, closeButton[0], cw);
+  EventUtils.sendMouseEvent({ type: "mouseup" }, closeButton[0], cw);
+}
+
--- a/browser/components/wintaskbar/WindowsJumpLists.jsm
+++ b/browser/components/wintaskbar/WindowsJumpLists.jsm
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Jim Mathies <jmathies@mozilla.com> (Original author)
  *   Marco Bonardo <mak77@bonardo.net>
+ *   Brian R. Bondy <netzen@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -326,17 +327,17 @@ var WinTaskbarJumpList =
 
   _buildTasks: function WTBJL__buildTasks() {
     var items = Cc["@mozilla.org/array;1"].
                 createInstance(Ci.nsIMutableArray);
     this._tasks.forEach(function (task) {
       if ((this._shuttingDown && !task.close) || (!this._shuttingDown && !task.open))
         return;
       var item = this._getHandlerAppItem(task.title, task.description,
-                                         task.args, task.iconIndex);
+                                         task.args, task.iconIndex, null);
       items.appendElement(item, false);
     }, this);
     
     if (items.length > 0)
       this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_TASKS, items);
   },
 
   _buildCustom: function WTBJL__buildCustom(title, items) {
@@ -369,17 +370,19 @@ var WinTaskbarJumpList =
           delete this._pendingStatements[LIST_TYPE.FREQUENT];
           // The are no more results, build the list.
           this._buildCustom(_getString("taskbar.frequent.label"), items);
           this._commitBuild();
           return;
         }
 
         let title = aResult.title || aResult.uri;
-        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1);
+        let faviconPageUri = Services.io.newURI(aResult.uri, null, null);
+        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1, 
+                                               faviconPageUri);
         items.appendElement(shortcut, false);
         this._frequentHashList.push(aResult.uri);
       },
       this
     );
   },
 
   _buildRecent: function WTBJL__buildRecent() {
@@ -412,33 +415,37 @@ var WinTaskbarJumpList =
 
         // Do not add items to recent that have already been added to frequent.
         if (this._frequentHashList &&
             this._frequentHashList.indexOf(aResult.uri) != -1) {
           return;
         }
 
         let title = aResult.title || aResult.uri;
-        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1);
+        let faviconPageUri = Services.io.newURI(aResult.uri, null, null);
+        let shortcut = this._getHandlerAppItem(title, title, aResult.uri, 1,
+                                               faviconPageUri);
         items.appendElement(shortcut, false);
         count++;
       },
       this
     );
   },
 
   _deleteActiveJumpList: function WTBJL__deleteAJL() {
     this._builder.deleteActiveList();
   },
 
   /**
    * Jump list item creation helpers
    */
 
-  _getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description, args, icon) {
+  _getHandlerAppItem: function WTBJL__getHandlerAppItem(name, description, 
+                                                        args, iconIndex, 
+                                                        faviconPageUri) {
     var file = Services.dirsvc.get("XCurProcD", Ci.nsILocalFile);
 
     // XXX where can we grab this from in the build? Do we need to?
     file.append("firefox.exe");
 
     var handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
                      createInstance(Ci.nsILocalHandlerApp);
     handlerApp.executable = file;
@@ -446,17 +453,18 @@ var WinTaskbarJumpList =
     if (name && name.length != 0)
       handlerApp.name = name;
     handlerApp.detailedDescription = description;
     handlerApp.appendParameter(args);
 
     var item = Cc["@mozilla.org/windows-jumplistshortcut;1"].
                createInstance(Ci.nsIJumpListShortcut);
     item.app = handlerApp;
-    item.iconIndex = icon;
+    item.iconIndex = iconIndex;
+    item.faviconPageUri = faviconPageUri;
     return item;
   },
 
   _getSeparatorItem: function WTBJL__getSeparatorItem() {
     var item = Cc["@mozilla.org/windows-jumplistseparator;1"].
                createInstance(Ci.nsIJumpListSeparator);
     return item;
   },
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -42,17 +42,17 @@
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PluralForm.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource:///modules/devtools/CssLogic.jsm");
 Cu.import("resource:///modules/devtools/Templater.jsm");
 
-var EXPORTED_SYMBOLS = ["CssHtmlTree"];
+var EXPORTED_SYMBOLS = ["CssHtmlTree", "PropertyView"];
 
 /**
  * CssHtmlTree is a panel that manages the display of a table sorted by style.
  * There should be one instance of CssHtmlTree per style display (of which there
  * will generally only be one).
  *
  * @params {Document} aStyleWin The main XUL browser document
  * @params {CssLogic} aCssLogic How we dig into the CSS. See CssLogic.jsm
@@ -337,42 +337,42 @@ PropertyView.prototype = {
    */
   get propertyInfo()
   {
     return this.tree.cssLogic.getPropertyInfo(this.name);
   },
 
   /**
    * Compute the title of the property view. The title includes the number of
-   * rules that hold the current property.
+   * selectors that match the currently selected element.
    *
    * @param {nsIDOMElement} aElement reference to the DOM element where the rule
    * title needs to be displayed.
    * @return {string} The rule title.
    */
   ruleTitle: function PropertyView_ruleTitle(aElement)
   {
     let result = "";
-    let matchedRuleCount = this.propertyInfo.matchedRuleCount;
+    let matchedSelectorCount = this.propertyInfo.matchedSelectors.length;
 
-    if (matchedRuleCount > 0) {
+    if (matchedSelectorCount > 0) {
       aElement.classList.add("rule-count");
       aElement.firstElementChild.className = "expander";
 
-      let str = CssHtmlTree.l10n("property.numberOfRules");
-      result = PluralForm.get(matchedRuleCount, str)
-          .replace("#1", matchedRuleCount);
+      let str = CssHtmlTree.l10n("property.numberOfSelectors");
+      result = PluralForm.get(matchedSelectorCount, str)
+          .replace("#1", matchedSelectorCount);
     } else if (this.showUnmatchedLink) {
       aElement.classList.add("rule-unmatched");
       aElement.firstElementChild.className = "expander";
 
-      let unmatchedRuleCount = this.propertyInfo.unmatchedRuleCount;
-      let str = CssHtmlTree.l10n("property.numberOfUnmatchedRules");
-      result = PluralForm.get(unmatchedRuleCount, str)
-          .replace("#1", unmatchedRuleCount);
+      let unmatchedSelectorCount = this.propertyInfo.unmatchedSelectors.length;
+      let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
+      result = PluralForm.get(unmatchedSelectorCount, str)
+          .replace("#1", unmatchedSelectorCount);
     }
     return result;
   },
 
   /**
    * Close the property view.
    */
   close: function PropertyView_close()
@@ -424,18 +424,19 @@ PropertyView.prototype = {
 
   /**
    * The UI has a link to allow the user to display unmatched selectors.
    * This provides localized link text.
    */
   get showUnmatchedLinkText()
   {
     let smur = CssHtmlTree.l10n("rule.showUnmatchedLink");
-    let plural = PluralForm.get(this.propertyInfo.unmatchedRuleCount, smur);
-    return plural.replace("#1", this.propertyInfo.unmatchedRuleCount);
+    let unmatchedSelectorCount = this.propertyInfo.unmatchedSelectors.length;
+    let plural = PluralForm.get(unmatchedSelectorCount, smur);
+    return plural.replace("#1", unmatchedSelectorCount);
   },
 
   /**
    * The action when a user clicks the 'show unmatched' link.
    */
   showUnmatchedLinkClick: function PropertyView_showUnmatchedLinkClick(aEvent)
   {
     this.showUnmatched = true;
--- a/browser/devtools/styleinspector/CssLogic.jsm
+++ b/browser/devtools/styleinspector/CssLogic.jsm
@@ -736,16 +736,18 @@ function CssSheet(aCssLogic, aDomSheet, 
 
   // Cached CssRules from the given stylesheet.
   this._rules = {};
 
   this._ruleCount = -1;
 }
 
 CssSheet.prototype = {
+  _passId: null,
+
   /**
    * Get a source for a stylesheet, taking into account embedded stylesheets
    * for which we need to use document.defaultView.location.href rather than
    * sheet.href
    *
    * @return {string} the address of the stylesheet.
    */
   get href()
@@ -945,16 +947,18 @@ function CssRule(aCssSheet, aDomRule, aE
     this.source = CssLogic.l10n("rule.sourceElement");
     this.href = "#";
     this.systemRule = false;
     this.sourceElement = aElement;
   }
 }
 
 CssRule.prototype = {
+  _passId: null,
+
   /**
    * Check if the parent stylesheet is allowed by the CssLogic.sourceFilter.
    *
    * @return {boolean} true if the parent stylesheet is allowed by the current
    * sourceFilter, or false otherwise.
    */
   get sheetAllowed()
   {
@@ -1086,16 +1090,18 @@ function CssSelector(aCssRule, aSelector
 {
   this._cssRule = aCssRule;
   this.text = aSelector;
   this.elementStyle = this.text == "@element.style";
   this._specificity = null;
 }
 
 CssSelector.prototype = {
+  _matchId: null,
+
   /**
    * Retrieve the CssSelector source, which is the source of the CssSheet owning
    * the selector.
    *
    * @return {string} the selector source.
    */
   get source()
   {
--- a/browser/devtools/styleinspector/StyleInspector.jsm
+++ b/browser/devtools/styleinspector/StyleInspector.jsm
@@ -84,43 +84,58 @@ var StyleInspector = {
     let vbox = win.document.createElement("vbox");
     vbox.setAttribute("flex", "1");
     panel.appendChild(vbox);
 
     let iframe = win.document.createElementNS(ns, "iframe");
     iframe.setAttribute("flex", "1");
     iframe.setAttribute("tooltip", "aHTMLTooltip");
     iframe.setAttribute("src", "chrome://browser/content/csshtmltree.xhtml");
+    iframe.addEventListener("load", SI_iframeOnload, true);
     vbox.appendChild(iframe);
 
     let hbox = win.document.createElement("hbox");
     hbox.setAttribute("class", "resizerbox");
     vbox.appendChild(hbox);
 
     let spacer = win.document.createElement("spacer");
     spacer.setAttribute("flex", "1");
     hbox.appendChild(spacer);
 
     let resizer = win.document.createElement("resizer");
     resizer.setAttribute("dir", "bottomend");
     hbox.appendChild(resizer);
     popupSet.appendChild(panel);
 
     /**
+     * Iframe's onload event
+     */
+    let iframeReady = false;
+    function SI_iframeOnload() {
+      iframe.removeEventListener("load", SI_iframeOnload, true);
+      panel.cssLogic = new CssLogic();
+      panel.cssHtmlTree = new CssHtmlTree(iframe, panel.cssLogic, panel);
+      iframeReady = true;
+      if (panelReady) {
+        SI_popupShown.call(panel);
+      }
+    }
+
+    /**
      * Initialize the popup when it is first shown
      */
+    let panelReady = false;
     function SI_popupShown() {
-      if (!this.cssHtmlTree) {
-        this.cssLogic = new CssLogic();
-        this.cssHtmlTree = new CssHtmlTree(iframe, this.cssLogic, this);
+      panelReady = true;
+      if (iframeReady) {
+        let selectedNode = this.selectedNode || null;
+        this.cssLogic.highlight(selectedNode);
+        this.cssHtmlTree.highlight(selectedNode);
+        Services.obs.notifyObservers(null, "StyleInspector-opened", null);
       }
-
-      this.cssLogic.highlight(this.selectedNode);
-      this.cssHtmlTree.highlight(this.selectedNode);
-      Services.obs.notifyObservers(null, "StyleInspector-opened", null);
     }
 
     /**
      * Hide the popup and conditionally destroy it
      */
     function SI_popupHidden() {
       if (panel.preserveOnHide) {
         Services.obs.notifyObservers(null, "StyleInspector-closed", null);
--- a/browser/devtools/styleinspector/test/browser/Makefile.in
+++ b/browser/devtools/styleinspector/test/browser/Makefile.in
@@ -43,20 +43,22 @@ VPATH     = @srcdir@
 relativesrcdir  = browser/devtools/styleinspector/test/browser
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
   browser_styleinspector.js \
   browser_styleinspector_webconsole.js \
+  browser_bug683672.js \
   head.js \
   $(NULL)
 
 _BROWSER_TEST_PAGES = \
   browser_styleinspector_webconsole.htm \
+  browser_bug683672.html \
   $(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
 
 libs:: $(_BROWSER_TEST_PAGES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser/browser_bug683672.html
@@ -0,0 +1,32 @@
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+  <head>
+    <style>
+      .matched1, .matched2, .matched3, .matched4, .matched5 {
+        color: #000;
+      }
+
+      .unmatched1, .unmatched2, .unmatched3, .unmatched4, .unmatched5, .unmatched6, .unmatched7 {
+        color: #f00;
+      }
+
+      div {
+        position: absolute;
+        top: 40px;
+        left: 20px;
+        border: 1px solid #000;
+        color: #111;
+        width: 100px;
+        height: 50px;
+      }
+    </style>
+  </head>
+  <body>
+    inspectstyle($("test"));
+    <div id="test" class="matched1 matched2 matched3 matched4 matched5">Test div</div>
+    <div id="dummy">
+      <div></div>
+    </div>
+  </body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser/browser_bug683672.js
@@ -0,0 +1,115 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests that the style inspector works properly
+
+let doc;
+let stylePanel;
+
+const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/test/browser/browser_bug683672.html";
+
+Cu.import("resource:///modules/devtools/CssHtmlTree.jsm");
+
+function test()
+{
+  waitForExplicitFinish();
+  addTab(TEST_URI);
+  browser.addEventListener("load", tabLoaded, true);
+}
+
+function tabLoaded()
+{
+  ok(window.StyleInspector, "StyleInspector exists");
+  ok(StyleInspector.isEnabled, "style inspector preference is enabled");
+  stylePanel = StyleInspector.createPanel();
+  Services.obs.addObserver(runTests, "StyleInspector-opened", false);
+  stylePanel.openPopup();
+}
+
+function runTests()
+{
+  Services.obs.removeObserver(runTests, "StyleInspector-opened", false);
+
+  ok(stylePanel.isOpen(), "style inspector is open");
+
+  testMatchedSelectors();
+  testUnmatchedSelectors();
+
+  info("finishing up");
+  Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
+  stylePanel.hidePopup();
+}
+
+function testMatchedSelectors()
+{
+  info("checking selector counts, matched rules and titles");
+  let div = content.document.getElementById("test");
+  ok(div, "captain, we have the div");
+
+  info("selecting the div");
+  stylePanel.selectNode(div);
+
+  let htmlTree = stylePanel.cssHtmlTree;
+
+  is(div, htmlTree.viewedElement,
+      "style inspector node matches the selected node");
+
+  let propertyView = new PropertyView(htmlTree, "color");
+  let numMatchedSelectors = propertyView.propertyInfo.matchedSelectors.length;
+
+  is(numMatchedSelectors, 6,
+      "CssLogic returns the correct number of matched selectors for div");
+
+  let dummy = content.document.getElementById("dummy");
+  let returnedRuleTitle = propertyView.ruleTitle(dummy);
+  let str = CssHtmlTree.l10n("property.numberOfSelectors");
+  let calculatedRuleTitle = PluralForm.get(numMatchedSelectors, str)
+                                      .replace("#1", numMatchedSelectors);
+
+  info("returnedRuleTitle: '" + returnedRuleTitle + "'");
+
+  is(returnedRuleTitle, calculatedRuleTitle,
+      "returned title for matched rules is correct");
+}
+
+function testUnmatchedSelectors()
+{
+  info("checking selector counts, unmatched rules and titles");
+  let body = content.document.body;
+  ok(body, "captain, we have a body");
+
+  info("selecting content.document.body");
+  stylePanel.selectNode(body);
+
+  let htmlTree = stylePanel.cssHtmlTree;
+
+  is(body, htmlTree.viewedElement,
+      "style inspector node matches the selected node");
+
+  let propertyView = new PropertyView(htmlTree, "color");
+  let numUnmatchedSelectors = propertyView.propertyInfo.unmatchedSelectors.length;
+
+  is(numUnmatchedSelectors, 13,
+      "CssLogic returns the correct number of unmatched selectors for body");
+
+  let dummy = content.document.getElementById("dummy");
+  let returnedRuleTitle = propertyView.ruleTitle(dummy);
+  let str = CssHtmlTree.l10n("property.numberOfUnmatchedSelectors");
+  let calculatedRuleTitle = PluralForm.get(numUnmatchedSelectors, str)
+                                      .replace("#1", numUnmatchedSelectors);
+
+  info("returnedRuleTitle: '" + returnedRuleTitle + "'");
+
+  is(returnedRuleTitle, calculatedRuleTitle,
+      "returned title for unmatched rules is correct");
+}
+
+function finishUp()
+{
+  Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
+  ok(!stylePanel.isOpen(), "style inspector is closed");
+  doc = stylePanel = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -3610,30 +3610,36 @@ HeadsUpDisplay.prototype = {
         ]
       }
     ];
 
     let toolbar = this.makeXULNode("toolbar");
     toolbar.setAttribute("class", "hud-console-filter-toolbar");
     toolbar.setAttribute("mode", "full");
 
+#ifdef XP_MAC
     this.makeCloseButton(toolbar);
+#endif
 
     for (let i = 0; i < BUTTONS.length; i++) {
       this.makeFilterButton(toolbar, BUTTONS[i]);
     }
 
     toolbar.appendChild(this.filterSpacer);
 
     let positionUI = this.createPositionUI();
     toolbar.appendChild(positionUI);
 
     toolbar.appendChild(this.filterBox);
     this.makeClearConsoleButton(toolbar);
 
+#ifndef XP_MAC
+    this.makeCloseButton(toolbar);
+#endif
+
     return toolbar;
   },
 
   /**
    * Creates the UI for re-positioning the console
    *
    * @return nsIDOMNode
    *         The toolbarbutton which holds the menu that allows the user to
--- a/browser/devtools/webconsole/Makefile.in
+++ b/browser/devtools/webconsole/Makefile.in
@@ -40,22 +40,25 @@
 DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 EXTRA_JS_MODULES = \
-		HUDService.jsm \
 		PropertyPanel.jsm \
 		NetworkHelper.jsm \
 		AutocompletePopup.jsm \
 		gcli.jsm \
 		$(NULL)
 
+EXTRA_PP_JS_MODULES = \
+		HUDService.jsm \
+		$(NULL)
+
 ifdef ENABLE_TESTS
 ifneq (mobile,$(MOZ_BUILD_APP))
 	DIRS += test
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/locales/en-US/chrome/browser/styleinspector.properties
+++ b/browser/locales/en-US/chrome/browser/styleinspector.properties
@@ -1,26 +1,25 @@
 # LOCALIZATION NOTE These strings are used inside the Style Inspector.
 
 # LOCALIZATION NOTE (panelTitle): This is the panel title
 panelTitle=Style Inspector
 
-# LOCALIZATION NOTE (property.numberOfRules): For each style property the panel
-# shows the number of rules which hold that specific property, counted from all
-# of the stylesheets in the web page inspected.
+# LOCALIZATION NOTE (property.numberOfSelectors): For each style property the
+# panel shows the number of selectors which match the currently selected
+# element, counted from all stylesheets in the web page inspected.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-property.numberOfRules=#1 rule;#1 rules
+property.numberOfSelectors=1 selector;#1 selectors
 
-# LOCALIZATION NOTE (property.numberOfUnmatchedRules): Each style property is
-# inside a rule. A rule is a selector that can match (or not) the highlighted
-# element in the web page. The property view shows no unmatched rules. If the
-# user wants to expand the property to view unmatched rules, he/she must click
-# this link displayed to the right of each property.
+# LOCALIZATION NOTE (property.numberOfUnmatchedSelectors): For each style
+# property the panel shows the number of selectors which do not match the
+# currently selected element, counted from all stylesheets in the web page
+# inspected.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-property.numberOfUnmatchedRules=One unmatched rule;#1 unmatched rules
+property.numberOfUnmatchedSelectors=1 unmatched selector;#1 unmatched selectors
 
 # LOCALIZATION NOTE (rule.status): For each style property the panel shows
 # the rules which hold that specific property. For every rule, the rule status
 # is also displayed: a rule can be the best match, a match, a parent match, or a
 # rule did not match the element the user has highlighted.
 rule.status.BEST=Best Match
 rule.status.MATCHED=Matched
 rule.status.PARENT_MATCH=Parent Match
@@ -28,24 +27,22 @@ rule.status.UNMATCHED=Unmatched
 
 # LOCALIZATION NOTE (rule.sourceElement, rule.sourceInline): For each
 # style property the panel shows the rules which hold that specific property.
 # For every rule, the rule source is also displayed: a rule can come from a
 # file, from the same page (inline), or from the element itself (element).
 rule.sourceInline=inline
 rule.sourceElement=element
 
-# LOCALIZATION NOTE (rule.showUnmatchedLink): Each style property
-# is inside a rule. A rule is a selector that can match (or not) the highlighted
-# element in the web page. The property view shows only a few of the unmatched
-# rules. If the user wants to see all of the unmatched rules, he/she must click
-# the link displayed at the bottom of the rules table. That link shows how many
-# rules are not displayed. This is the string used when the link is generated.
+# LOCALIZATION NOTE (rule.showUnmatchedLink): For each style
+# property the panel shows the number of selectors which do not match the
+# currently selected element, counted from all stylesheets in the web page
+# inspected.
 # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
-rule.showUnmatchedLink=One unmatched rule...;#1 unmatched rules...
+rule.showUnmatchedLink=1 unmatched selector…;#1 unmatched selectors…
 
 # LOCALIZATION NOTE (group): Style properties are displayed in categories and
 # these are the category names.
 group.Text_Fonts_and_Color=Text, Fonts & Color
 group.Background=Background
 group.Dimensions=Dimensions
 group.Positioning_and_Page_Flow=Positioning and Page Flow
 group.Borders=Borders
--- a/browser/locales/en-US/searchplugins/list.txt
+++ b/browser/locales/en-US/searchplugins/list.txt
@@ -1,6 +1,7 @@
 amazondotcom
 bing
 eBay
 google
+twitter
 wikipedia
 yahoo
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/searchplugins/twitter.xml
@@ -0,0 +1,11 @@
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Twitter</ShortName>
+<Description>Realtime Twitter Search</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A/v7+D/7+/j/+/v5g/v7+YP7+/mD+/v5I/v7+KP///wD///8A////AP///wD///8A////AP///wD+/v4H/v7+UPbv4pHgx47B1K9Y3tWwWN7Ur1je3sKCx+rbuKj+/v5n/v7+GP///wD///8A////AP///wD+/v4Y+fbweM2ycMe2iB7/vI0f/8STIf/KlyL/zJki/8yZIv/LmCL/0ahK5/Hp1JH+/v4Y////AP///wD///8A7OTTaquHN+CujkXPs5ZTv6N6G/+2iB7/xpUh/8yZIv/MmSL/zJki/8yZIv/Kmy738OjUi////wD///8A////AMKtfY7w6+Ef////AP///wD///8A3sqbp8iWIf/MmSL/zJki/8yZIv/MmSL/y5gi/8mePO7+/v4w////AP///wD///8A////AP///wD+/v4H/v7+V9CtWN3KmCL/zJki/8yZIv/MmSL/zJki/8yZIv/JlyH/5tSqp/7+/mD+/v4/////AP///wD///8A+PXvJtGyZdXNnS/3y5gi/8qYIv/LmCL/zJki/8yZIv/MmSL/y5gi/82iPO7LqVfe0byMmf///wD///8A/v7+D/Do1JHKmy73ypci/8KSIP+/jyD/xpQh/8uYIv/MmSL/zJki/8qYIv+/jyD/rIEd/9nKqH7///8A////APPu4TzAlSz3wZEg/7mLH/+sgR3/uZdGz7mLH//JlyH/zJki/8yZIv/GlSH/to0r9eXbxD/Vx6dg////AP7+/h/p38WhtIsq9al/HP+kfyjuybaKgf///wCzjzjlwJAg/8qYIv/JlyH/u4wf/8CkYrn///8A////AP///wDj2sRMnHUa/7meYa7Vx6dg////AP///wD///8A2MmnYK6DHf++jiD/vo4g/62CHf/k2sQ/////AP///wD///8A8OvhH/f07w////8A////AP///wD///8A////AP///wC/p3Cfpnwc/66GKvPg1LZ8////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////ANXHp2DJtoqByLWKgf///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AADgPwAAwA8AAIAHAAB4BwAA+AMAAPAAAADgAQAA4AMAAMEDAADPhwAA/48AAP/nAAD//wAA//8AAA==</Image>
+<SearchForm>https://twitter.com/search/</SearchForm>
+<Url type="text/html" method="GET" template="https://twitter.com/search/{searchTerms}">
+  <Param name="partner" value="Firefox"/>
+  <Param name="source" value="desktop-search"/>
+</Url>
+</SearchPlugin>
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1979,12 +1979,12 @@ panel[dimmed="true"] {
 }
 
 #highlighter-veil-transparentbox {
   box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
   outline: 1px dashed rgba(255,255,255,0.5);
   outline-offset: -1px;
 }
 
-#highlighter-veil-transparentbox[locked] {
+#highlighter-veil-container[locked] > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
   box-shadow: 0 0 0 1px black;
   outline-color: white;
 }
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -2570,17 +2570,17 @@ panel[dimmed="true"] {
 }
 
 #highlighter-veil-transparentbox {
   box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
   outline: 1px dashed rgba(255,255,255,0.5);
   outline-offset: -1px;
 }
 
-#highlighter-veil-transparentbox[locked] {
+#highlighter-veil-container[locked] > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
   box-shadow: 0 0 0 1px black;
   outline-color: white;
 }
 
 /* Highlighter toolbar */
 
 #inspector-toolbar {
   -moz-appearance: none;
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -2547,12 +2547,12 @@ panel[dimmed="true"] {
 }
 
 #highlighter-veil-transparentbox {
   box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
   outline: 1px dashed rgba(255,255,255,0.5);
   outline-offset: -1px;
 }
 
-#highlighter-veil-transparentbox[locked] {
+#highlighter-veil-container[locked] > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
   box-shadow: 0 0 0 1px black;
   outline-color: white;
 }
--- a/build/autoconf/mozconfig-find
+++ b/build/autoconf/mozconfig-find
@@ -35,18 +35,20 @@
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 # mozconfigfind - Loads options from .mozconfig onto configure's
 #    command-line. The .mozconfig file is searched for in the 
 #    order:
-#       if $MOZCONFIG is set, use that.
-#       Otherwise, use $TOPSRCDIR/.mozconfig
+#       If $MOZCONFIG is set, use that.
+#       If one of $TOPSRCDIR/.mozconfig or $TOPSRCDIR/mozconfig exists, use it.
+#       If both exist, or if various legacy locations contain a mozconfig, error.
+#       Otherwise, use the default build options.
 #
 topsrcdir=$1
 
 abspath() {
   if uname -s | grep -q MINGW; then
     # We have no way to figure out whether we're in gmake or pymake right
     # now. gmake gives us Unix-style paths while pymake gives us Windows-style
     # paths, so attempt to handle both.
@@ -71,30 +73,35 @@ if [ -n "$MOZCONFIG" ] && ! [ -f "$MOZCO
   exit 1
 fi
 
 if [ -n "$MOZ_MYCONFIG" ]; then
   echo "Your environment currently has the MOZ_MYCONFIG variable set to \"$MOZ_MYCONFIG\". MOZ_MYCONFIG is no longer supported. Please use MOZCONFIG instead."
   exit 1
 fi
 
+if [ -z "$MOZCONFIG" ] && [ -f "$topsrcdir/.mozconfig" ] && [ -f "$topsrcdir/mozconfig" ]; then
+  echo "Both \$topsrcdir/.mozconfig and \$topsrcdir/mozconfig are supported, but you must choose only one. Please remove the other."
+  exit 1
+fi
+
 for _config in "$MOZCONFIG" \
-               "$topsrcdir/.mozconfig"
+               "$topsrcdir/.mozconfig" \
+               "$topsrcdir/mozconfig"
 do
   if test -f "$_config"; then
     echo `abspath $_config`
     exit 0
   fi
 done
 
 # We used to support a number of other implicit .mozconfig locations. We now
 # detect if we were about to use any of these locations and issue an error if we
 # find any.
-for _config in "$topsrcdir/mozconfig" \
-               "$topsrcdir/mozconfig.sh" \
+for _config in "$topsrcdir/mozconfig.sh" \
                "$topsrcdir/myconfig.sh" \
                "$HOME/.mozconfig" \
                "$HOME/.mozconfig.sh" \
                "$HOME/.mozmyconfig.sh"
 do
   if test -f "$_config"; then
     echo "You currently have a mozconfig at \"$_config\". This implicit location is no longer supported. Please move it to $topsrcdir/.mozconfig or specify it explicitly via \$MOZCONFIG.";
     exit 1
--- a/client.mk
+++ b/client.mk
@@ -263,16 +263,17 @@ configure depend realbuild install expor
 else
 
 # MOZ_CURRENT_PROJECT: either doing a single-project build, or building an
 # individual project in a multi-project build.
 
 ####################################
 # Configure
 
+MAKEFILE      = $(wildcard $(OBJDIR)/Makefile)
 CONFIG_STATUS = $(wildcard $(OBJDIR)/config.status)
 CONFIG_CACHE  = $(wildcard $(OBJDIR)/config.cache)
 
 EXTRA_CONFIG_DEPS := \
 	$(TOPSRCDIR)/aclocal.m4 \
 	$(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
 	$(TOPSRCDIR)/js/src/aclocal.m4 \
 	$(NULL)
@@ -311,17 +312,23 @@ endif
 	@if test ! -d $(OBJDIR); then $(MKDIR) $(OBJDIR); else true; fi
 	@echo cd $(OBJDIR);
 	@echo $(CONFIGURE) $(CONFIGURE_ARGS)
 	@cd $(OBJDIR) && $(BUILD_PROJECT_ARG) $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
 	  || ( echo "*** Fix above errors and then restart with\
                \"$(MAKE) -f client.mk build\"" && exit 1 )
 	@touch $(OBJDIR)/Makefile
 
-$(OBJDIR)/Makefile $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
+ifneq (,$(MAKEFILE))
+$(OBJDIR)/Makefile: $(OBJDIR)/config.status
+
+$(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
+else
+$(OBJDIR)/Makefile: $(CONFIG_STATUS_DEPS)
+endif
 	@$(MAKE) -f $(TOPSRCDIR)/client.mk configure
 
 ifneq (,$(CONFIG_STATUS))
 $(OBJDIR)/config/autoconf.mk: $(TOPSRCDIR)/config/autoconf.mk.in
 	cd $(OBJDIR); \
 	  CONFIG_FILES=config/autoconf.mk ./config.status
 endif
 
--- a/config/optimizejars.py
+++ b/config/optimizejars.py
@@ -298,16 +298,17 @@ def optimizejar(jar, outjar, inlog = Non
 
     if inlog is None:
         dirend.cdir_offset = out_offset
 
     if dups_found > 0:
         print("WARNING: Found %d duplicate files taking %d bytes"%(dups_found, dupe_bytes))
 
     dirend.cdir_size = len(cdir_data)
+    dirend.disk_entries = dirend.cdir_entries
     dirend_data = dirend.pack()
     assert_true(size_of(cdir_end) == len(dirend_data), "Failed to serialize directory end correctly. Serialized size;%d, expected:%d"%(len(dirend_data), size_of(cdir_end)));
 
     outfd.seek(dirend.cdir_offset)
     outfd.write(cdir_data)
     outfd.write(dirend_data)
 
     # for ordered jars the central directory is written in the begining of the file, so a second central-directory
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -78,16 +78,17 @@ static fp_except_t oldmask = fpsetmask(~
 #include "nsReadableUtils.h"
 #include "mozilla/AutoRestore.h"
 #include "nsINode.h"
 #include "nsHashtable.h"
 #include "nsIDOMNode.h"
 #include "nsHtml5Parser.h"
 #include "nsIFragmentContentSink.h"
 #include "nsMathUtils.h"
+#include "mozilla/TimeStamp.h"
 
 struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
 
 class nsIDOMScriptObjectFactory;
 class nsIXPConnect;
 class nsIContent;
 class nsIDOMKeyEvent;
 class nsIDocument;
@@ -184,16 +185,17 @@ struct nsShortcutCandidate {
   PRUint32 mCharCode;
   PRBool   mIgnoreShift;
 };
 
 class nsContentUtils
 {
   friend class nsAutoScriptBlockerSuppressNodeRemoved;
   typedef mozilla::dom::Element Element;
+  typedef mozilla::TimeDuration TimeDuration;
 
 public:
   static nsresult Init();
 
   /**
    * Get a JSContext from the document's scope object.
    */
   static JSContext* GetContextFromDocument(nsIDocument *aDocument);
@@ -1715,16 +1717,23 @@ public:
 
   /**
    * Returns PR_TRUE if key input is restricted in DOM full-screen mode
    * to non-alpha-numeric key codes only. This mirrors the
    * "full-screen-api.key-input-restricted" pref.
    */
   static PRBool IsFullScreenKeyInputRestricted();
 
+  /**
+   * Returns the time limit on handling user input before
+   * nsEventStateManager::IsHandlingUserInput() stops returning PR_TRUE.
+   * This enables us to detect long running user-generated event handlers.
+   */
+  static TimeDuration HandlingUserInputTimeout();
+
   static void GetShiftText(nsAString& text);
   static void GetControlText(nsAString& text);
   static void GetMetaText(nsAString& text);
   static void GetAltText(nsAString& text);
   static void GetModifierSeparatorText(nsAString& text);
 
   /**
    * Returns if aContent has a tabbable subdocument.
@@ -1882,16 +1891,17 @@ private:
 
   static nsIInterfaceRequestor* sSameOriginChecker;
 
   static PRBool sIsHandlingKeyBoardEvent;
   static PRBool sAllowXULXBL_for_file;
   static PRBool sIsFullScreenApiEnabled;
   static PRBool sTrustedFullScreenOnly;
   static PRBool sFullScreenKeyInputRestricted;
+  static PRUint32 sHandlingInputTimeout;
 
   static nsHtml5Parser* sHTMLFragmentParser;
   static nsIParser* sXMLFragmentParser;
   static nsIFragmentContentSink* sXMLFragmentSink;
 
   static nsString* sShiftText;
   static nsString* sControlText;
   static nsString* sMetaText;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -196,16 +196,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentDLF.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
 #endif
 #include "nsDOMTouchEvent.h"
 #include "nsIScriptElement.h"
+#include "prdtoa.h"
 
 #include "mozilla/Preferences.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla;
 
 const char kLoadAsData[] = "loadAsData";
@@ -261,16 +262,18 @@ nsString* nsContentUtils::sMetaText = ns
 nsString* nsContentUtils::sAltText = nsnull;
 nsString* nsContentUtils::sModifierSeparator = nsnull;
 
 PRBool nsContentUtils::sInitialized = PR_FALSE;
 PRBool nsContentUtils::sIsFullScreenApiEnabled = PR_FALSE;
 PRBool nsContentUtils::sTrustedFullScreenOnly = PR_TRUE;
 PRBool nsContentUtils::sFullScreenKeyInputRestricted = PR_TRUE;
 
+PRUint32 nsContentUtils::sHandlingInputTimeout = 1000;
+
 nsHtml5Parser* nsContentUtils::sHTMLFragmentParser = nsnull;
 nsIParser* nsContentUtils::sXMLFragmentParser = nsnull;
 nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nsnull;
 
 static PLDHashTable sEventListenerManagersHash;
 
 class EventListenerManagerMapEntry : public PLDHashEntryHdr
 {
@@ -314,16 +317,23 @@ EventListenerManagerHashClearEntry(PLDHa
 class nsSameOriginChecker : public nsIChannelEventSink,
                             public nsIInterfaceRequestor
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
 };
 
+/* static */
+TimeDuration
+nsContentUtils::HandlingUserInputTimeout()
+{
+  return TimeDuration::FromMilliseconds(sHandlingInputTimeout);
+}
+
 // static
 nsresult
 nsContentUtils::Init()
 {
   if (sInitialized) {
     NS_WARNING("Init() called twice");
 
     return NS_OK;
@@ -392,16 +402,20 @@ nsContentUtils::Init()
                                "full-screen-api.enabled");
 
   Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
                                "full-screen-api.allow-trusted-requests-only");
 
   Preferences::AddBoolVarCache(&sFullScreenKeyInputRestricted,
                                "full-screen-api.key-input-restricted");
 
+  Preferences::AddUintVarCache(&sHandlingInputTimeout,
+                               "dom.event.handling-user-input-time-limit",
+                               1000);
+
   sInitialized = PR_TRUE;
 
   return NS_OK;
 }
 
 void
 nsContentUtils::GetShiftText(nsAString& text)
 {
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -5529,18 +5529,20 @@ nsGenericElement::SizeOf() const
 #define TOUCH_EVENT EVENT
 #include "nsEventNameList.h"
 #undef TOUCH_EVENT
 #undef EVENT
 
 PRBool
 nsINode::Contains(const nsINode* aOther) const
 {
+  if (aOther == this) {
+    return PR_TRUE;
+  }
   if (!aOther ||
-      aOther == this ||
       GetOwnerDoc() != aOther->GetOwnerDoc() ||
       IsInDoc() != aOther->IsInDoc() ||
       !(aOther->IsElement() ||
         aOther->IsNodeOfType(nsINode::eCONTENT)) ||
       !GetFirstChild()) {
     return PR_FALSE;
   }
 
--- a/content/base/test/chrome/test_bug683852.xul
+++ b/content/base/test/chrome/test_bug683852.xul
@@ -16,23 +16,25 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
   /** Test for Bug 683852 **/
   SimpleTest.waitForExplicitFinish();
 
   function startTest() {
-    is(document.contains(document), false, "Document should not contain itself!");
+    is(document.contains(document), true, "Document should contain itself!");
 
     var tb = document.getElementById("testbutton");
     is(document.contains(tb), true, "Document should contain element in it!");
+    is(tb.contains(tb), true, "Element should contain itself.")
     var anon = document.getAnonymousElementByAttribute(tb, "anonid", "button-box");
     is(document.contains(anon), false, "Document should not contain anonymous element in it!");
     is(tb.contains(anon), false, "Element should not contain anonymous element in it!");
+    is(anon.contains(anon), true, "Anonymous element should contain itself.")
     is(document.documentElement.contains(tb), true, "Element should contain element in it!");
     is(document.contains(document.createElement("foo")), false, "Document shouldn't contain element which is't in the document");
     is(document.contains(document.createTextNode("foo")), false, "Document shouldn't contain text node which is't in the document");
 
     var link = document.getElementById("link");
     is(document.contains(link.firstChild), true,
        "Document should contain a text node in it.");
     is(link.contains(link.firstChild), true,
@@ -45,17 +47,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     is(pi.contains(document), false, "Processing instruction shouldn't contain document");
     document.documentElement.appendChild(pi);
     document.contains(pi, true, "Document should contain processing instruction");
 
     var df = document.createRange().createContextualFragment("<div>foo</div>");
     is(df.contains(df.firstChild), true, "Document fragment should contain its child");
     is(df.contains(df.firstChild.firstChild), true,
        "Document fragment should contain its descendant");
-    is(df.contains(df), false, "Document fragment shouldn't contain itself.");
+    is(df.contains(df), true, "Document fragment should contain itself.");
 
     var d = document.implementation.createHTMLDocument("");
     is(document.contains(d), false,
        "Document shouldn't contain another document.");
     is(document.contains(d.createElement("div")), false,
        "Document shouldn't contain an element from another document.");
 
     SimpleTest.finish();
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -170,16 +170,18 @@ static nsITimerCallback* gUserInteractio
 // Pixel scroll accumulation for synthetic line scrolls
 static nscoord gPixelScrollDeltaX = 0;
 static nscoord gPixelScrollDeltaY = 0;
 static PRUint32 gPixelScrollDeltaTimeout = 0;
 
 static nscoord
 GetScrollableLineHeight(nsIFrame* aTargetFrame);
 
+TimeStamp nsEventStateManager::sHandlingInputStart;
+
 static inline PRBool
 IsMouseEventReal(nsEvent* aEvent)
 {
   NS_ABORT_IF_FALSE(NS_IS_MOUSE_EVENT_STRUCT(aEvent), "Not a mouse event");
   // Return true if not synthesized.
   return static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal;
 }
 
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -52,16 +52,18 @@
 #include "nsIFrameLoader.h"
 #include "nsIFrame.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIScrollableFrame.h"
 #include "nsFocusManager.h"
 #include "nsIDocument.h"
 #include "nsEventStates.h"
+#include "mozilla/TimeStamp.h"
+#include "nsContentUtils.h"
 
 class nsIPresShell;
 class nsIDocShell;
 class nsIDocShellTreeNode;
 class nsIDocShellTreeItem;
 class imgIContainer;
 class nsDOMDataTransfer;
 
@@ -75,16 +77,20 @@ class TabParent;
  * Event listener manager
  */
 
 class nsEventStateManager : public nsSupportsWeakReference,
                             public nsIObserver
 {
   friend class nsMouseWheelTransaction;
 public:
+
+  typedef mozilla::TimeStamp TimeStamp;
+  typedef mozilla::TimeDuration TimeDuration;
+
   nsEventStateManager();
   virtual ~nsEventStateManager();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   nsresult Init();
   nsresult Shutdown();
@@ -164,34 +170,48 @@ public:
 
   nsresult SetCursor(PRInt32 aCursor, imgIContainer* aContainer,
                      PRBool aHaveHotspot, float aHotspotX, float aHotspotY,
                      nsIWidget* aWidget, PRBool aLockCursor); 
 
   static void StartHandlingUserInput()
   {
     ++sUserInputEventDepth;
+    if (sUserInputEventDepth == 1) {
+      sHandlingInputStart = TimeStamp::Now();
+    }
   }
 
   static void StopHandlingUserInput()
   {
     --sUserInputEventDepth;
+    if (sUserInputEventDepth == 0) {
+      sHandlingInputStart = TimeStamp();
+    }
   }
 
   static PRBool IsHandlingUserInput()
   {
-    return sUserInputEventDepth > 0;
+    if (sUserInputEventDepth <= 0) {
+      return PR_FALSE;
+    }
+    TimeDuration timeout = nsContentUtils::HandlingUserInputTimeout();
+    return timeout <= TimeDuration(0) ||
+           (TimeStamp::Now() - sHandlingInputStart) <= timeout;
   }
 
   /**
    * Returns true if the current code is being executed as a result of user input.
    * This includes timers or anything else that is initiated from user input.
    * However, mouse hover events are not counted as user input, nor are
    * page load events. If this method is called from asynchronously executed code,
-   * such as during layout reflows, it will return false.
+   * such as during layout reflows, it will return false. If more time has elapsed
+   * since the user input than is specified by the
+   * dom.event.handling-user-input-time-limit pref (default 1 second), this
+   * function also returns false.
    */
   NS_IMETHOD_(PRBool) IsHandlingUserInputExternal() { return IsHandlingUserInput(); }
   
   nsPresContext* GetPresContext() { return mPresContext; }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsEventStateManager,
                                            nsIObserver)
 
@@ -502,16 +522,18 @@ private:
   nsCOMPtr<nsIDocument> mDocument;   // Doesn't necessarily need to be owner
 
   PRUint32 mLClickCount;
   PRUint32 mMClickCount;
   PRUint32 mRClickCount;
 
   PRPackedBool m_haveShutdown;
 
+  // Time at which we began handling user input.
+  static TimeStamp sHandlingInputStart;
 
 public:
   static nsresult UpdateUserActivityTimer(void);
   // Array for accesskey support
   nsCOMArray<nsIContent> mAccessKeys;
 
   // Unlocks pixel scrolling
   PRPackedBool mLastLineScrollConsumedX;
--- a/content/html/content/src/nsHTMLFrameSetElement.cpp
+++ b/content/html/content/src/nsHTMLFrameSetElement.cpp
@@ -317,17 +317,17 @@ nsHTMLFrameSetElement::ParseRowCol(const
       // Treat 0* as 1* in quirks mode (bug 40383)
       if (isInQuirks) {
         if ((eFramesetUnit_Relative == specs[i].mUnit) &&
           (0 == specs[i].mValue)) {
           specs[i].mValue = 1;
         }
       }
         
-      // Catch zero and negative frame sizes for Nav compatability
+      // Catch zero and negative frame sizes for Nav compatibility
       // Nav resized absolute and relative frames to "1" and
       // percent frames to an even percentage of the width
       //
       //if (isInQuirks && (specs[i].mValue <= 0)) {
       //  if (eFramesetUnit_Percent == specs[i].mUnit) {
       //    specs[i].mValue = 100 / count;
       //  } else {
       //    specs[i].mValue = 1;
--- a/content/html/content/test/test_fullscreen-api.html
+++ b/content/html/content/test/test_fullscreen-api.html
@@ -1,15 +1,16 @@
  <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for Bug 545812</title>
   <script type="application/javascript" src="/MochiKit/packed.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=545812">Mozilla Bug 545812</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
@@ -33,16 +34,33 @@ function run() {
   document.addEventListener("mozfullscreenchange",
     function(){ok(false, "Should never receive a mozfullscreenchange event in the main window.");},
     false);
 
   // Ensure the full-screen api is enabled, and will be disabled on test exit.
   prevEnabled = SpecialPowers.getBoolPref("full-screen-api.enabled");
   SpecialPowers.setBoolPref("full-screen-api.enabled", true);
 
+  // Test requesting full-screen mode in a long-running user-generated event handler.
+  // The request in the key handler should not be granted.
+  window.addEventListener("keypress", keyHandler, false);
+  synthesizeKey("VK_A", {});
+}
+
+function keyHandler(event) {
+  window.removeEventListener("keypress", keyHandler, false);
+  
+  // Busy loop until 2s has passed. We should then be past the 1 second threshold, and so
+  // our request for full-screen mode should be rejected.
+  var end = (new Date()).getTime() + 2000;
+  while ((new Date()).getTime() < end) {
+    ; // Wait...
+  }
+  document.body.mozRequestFullScreen();
+
   prevTrusted = SpecialPowers.getBoolPref("full-screen-api.allow-trusted-requests-only");
 
   // Request full-screen from a non trusted context (this script isn't a user
   // generated event!). We should not receive a "mozfullscreenchange" event.
   SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", true);
   document.body.mozRequestFullScreen();
 
   // Disable the requirement for trusted contexts only, so the tests are easier
--- a/content/html/document/test/browser_bug592641.js
+++ b/content/html/document/test/browser_bug592641.js
@@ -12,17 +12,17 @@ function test() {
   ctx.tab1 = gBrowser.addTab(testPath + "bug592641_img.jpg");
   ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
   ctx.tab1Browser.addEventListener("load", load1Soon, true);
 }
 
 function checkTitle(title) {
 
   ctx.loadsDone++;
-  ok(/^bug592641_img\.jpg \(JPEG Image, 1500x1500 pixels\)/.test(title),
+  ok(/^bug592641_img\.jpg \(JPEG Image, 1500\u00A0\u00D7\u00A01500 pixels\)/.test(title),
      "Title should be correct on load #" + ctx.loadsDone);
 }
 
 function load1Soon() {
   ctx.tab1Browser.removeEventListener("load", load1Soon, true);
   // onload is fired in OnStopDecode, so let's use executeSoon() to make sure
   // that any other OnStopDecode event handlers get the chance to fire first.
   executeSoon(load1Done);
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -392,17 +392,17 @@ nsTheoraState::PageIn(ogg_page* aPage)
       mPackets.Append(packet);
     }
     mUnstamped.Clear();
   }
   return NS_OK;
 }
 
 // Returns 1 if the Theora info struct is decoding a media of Theora
-// verion (maj,min,sub) or later, otherwise returns 0.
+// version (maj,min,sub) or later, otherwise returns 0.
 int
 TheoraVersion(th_info* info,
               unsigned char maj,
               unsigned char min,
               unsigned char sub)
 {
   ogg_uint32_t ver = (maj << 16) + (min << 8) + sub;
   ogg_uint32_t th_ver = (info->version_major << 16) +
--- a/content/media/ogg/nsOggCodecState.h
+++ b/content/media/ogg/nsOggCodecState.h
@@ -268,17 +268,17 @@ public:
   // Asserts that the number of samples predicted for aPacket is aSamples.
   // This function has no effect if VALIDATE_VORBIS_SAMPLE_CALCULATION
   // is not defined.
   void ValidateVorbisPacketSamples(ogg_packet* aPacket, long aSamples);
 
 };
 
 // Returns 1 if the Theora info struct is decoding a media of Theora
-// verion (maj,min,sub) or later, otherwise returns 0.
+// version (maj,min,sub) or later, otherwise returns 0.
 int TheoraVersion(th_info* info,
                   unsigned char maj,
                   unsigned char min,
                   unsigned char sub);
 
 class nsTheoraState : public nsOggCodecState {
 public:
   nsTheoraState(ogg_page* aBosPage);
--- a/content/smil/nsSMILAnimationController.cpp
+++ b/content/smil/nsSMILAnimationController.cpp
@@ -587,17 +587,17 @@ nsSMILAnimationController::DoMilestoneSa
       nsSMILTimeContainer* container = elem->GetTimeContainer();
       if (!container)
         // The container may be nsnull if the element has been detached from its
         // parent since registering a milestone.
         continue;
 
       nsSMILTimeValue containerTimeValue =
         container->ParentToContainerTime(sampleTime);
-      if (!containerTimeValue.IsResolved())
+      if (!containerTimeValue.IsDefinite())
         continue;
 
       // Clamp the converted container time to non-negative values.
       nsSMILTime containerTime = NS_MAX<nsSMILTime>(0, containerTimeValue.GetMillis());
 
       if (nextMilestone.mIsEnd) {
         elem->TimedElement().SampleEndAt(containerTime);
       } else {
--- a/content/smil/nsSMILAnimationFunction.cpp
+++ b/content/smil/nsSMILAnimationFunction.cpp
@@ -247,18 +247,17 @@ nsSMILAnimationFunction::ComposeResult(c
   // Check that we have the right number of keySplines and keyTimes
   CheckValueListDependentAttrs(values.Length());
   if (mErrorFlags != 0)
     return;
 
   // If this interval is active, we must have a non-negative mSampleTime
   NS_ABORT_IF_FALSE(mSampleTime >= 0 || !mIsActive,
       "Negative sample time for active animation");
-  NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() ||
-      mSimpleDuration.IsIndefinite() || mLastValue,
+  NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() || mLastValue,
       "Unresolved simple duration for active or frozen animation");
 
   // If we want to add but don't have a base value then just fail outright.
   // This can happen when we skipped getting the base value because there's an
   // animation function in the sandwich that should replace it but that function
   // failed unexpectedly.
   PRBool isAdditive = IsAdditive();
   if (isAdditive && aResult.IsNull())
@@ -403,17 +402,17 @@ nsSMILAnimationFunction::InterpolateResu
 
   // Get the normalised progress through the simple duration.
   //
   // If we have an indefinite simple duration, just set the progress to be
   // 0 which will give us the expected behaviour of the animation being fixed at
   // its starting point.
   double simpleProgress = 0.0;
 
-  if (mSimpleDuration.IsResolved()) {
+  if (mSimpleDuration.IsDefinite()) {
     nsSMILTime dur = mSimpleDuration.GetMillis();
 
     NS_ABORT_IF_FALSE(dur >= 0, "Simple duration should not be negative");
     NS_ABORT_IF_FALSE(mSampleTime >= 0, "Sample time should not be negative");
 
     if (mSampleTime >= dur || mSampleTime < 0) {
       NS_ERROR("Animation sampled outside interval");
       return NS_ERROR_FAILURE;
--- a/content/smil/nsSMILInterval.cpp
+++ b/content/smil/nsSMILInterval.cpp
@@ -105,18 +105,18 @@ nsSMILInterval::End()
   NS_ABORT_IF_FALSE(mBegin && mEnd,
       "Requesting End() on un-initialized interval.");
   return mEnd;
 }
 
 void
 nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin)
 {
-  NS_ABORT_IF_FALSE(aBegin.Time().IsResolved(),
-      "Attempting to set unresolved begin time on interval");
+  NS_ABORT_IF_FALSE(aBegin.Time().IsDefinite(),
+      "Attempting to set unresolved or indefinite begin time on interval");
   NS_ABORT_IF_FALSE(!mBeginFixed,
       "Attempting to set begin time but the begin point is fixed");
   // Check that we're not making an instance time dependent on itself. Such an
   // arrangement does not make intuitive sense and should be detected when
   // creating or updating intervals.
   NS_ABORT_IF_FALSE(!mBegin || aBegin.GetBaseTime() != mBegin,
       "Attempting to make self-dependent instance time");
 
--- a/content/smil/nsSMILTimeContainer.cpp
+++ b/content/smil/nsSMILTimeContainer.cpp
@@ -256,17 +256,17 @@ PRBool
 nsSMILTimeContainer::GetNextMilestoneInParentTime(
     nsSMILMilestone& aNextMilestone) const
 {
   if (mMilestoneEntries.IsEmpty())
     return PR_FALSE;
 
   nsSMILTimeValue parentTime =
     ContainerToParentTime(mMilestoneEntries.Top().mMilestone.mTime);
-  if (!parentTime.IsResolved())
+  if (!parentTime.IsDefinite())
     return PR_FALSE;
 
   aNextMilestone = nsSMILMilestone(parentTime.GetMillis(),
                                    mMilestoneEntries.Top().mMilestone.mIsEnd);
 
   return PR_TRUE;
 }
 
@@ -274,17 +274,17 @@ PRBool
 nsSMILTimeContainer::PopMilestoneElementsAtMilestone(
       const nsSMILMilestone& aMilestone,
       AnimElemArray& aMatchedElements)
 {
   if (mMilestoneEntries.IsEmpty())
     return PR_FALSE;
 
   nsSMILTimeValue containerTime = ParentToContainerTime(aMilestone.mTime);
-  if (!containerTime.IsResolved())
+  if (!containerTime.IsDefinite())
     return PR_FALSE;
 
   nsSMILMilestone containerMilestone(containerTime.GetMillis(),
                                      aMilestone.mIsEnd);
 
   NS_ABORT_IF_FALSE(mMilestoneEntries.Top().mMilestone >= containerMilestone,
       "Trying to pop off earliest times but we have earlier ones that were "
       "overlooked");
--- a/content/smil/nsSMILTimeValue.cpp
+++ b/content/smil/nsSMILTimeValue.cpp
@@ -48,22 +48,22 @@ Cmp(PRInt64 aA, PRInt64 aB)
   return aA == aB ? 0 : (aA > aB ? 1 : -1);
 }
 
 PRInt8
 nsSMILTimeValue::CompareTo(const nsSMILTimeValue& aOther) const
 {
   PRInt8 result;
 
-  if (mState == STATE_RESOLVED) {
-    result = (aOther.mState == STATE_RESOLVED)
+  if (mState == STATE_DEFINITE) {
+    result = (aOther.mState == STATE_DEFINITE)
            ? Cmp(mMilliseconds, aOther.mMilliseconds)
            : -1;
   } else if (mState == STATE_INDEFINITE) {
-    if (aOther.mState == STATE_RESOLVED)
+    if (aOther.mState == STATE_DEFINITE)
       result = 1;
     else if (aOther.mState == STATE_INDEFINITE)
       result = 0;
     else
       result = -1;
   } else {
     result = (aOther.mState != STATE_UNRESOLVED) ? 1 : 0;
   }
--- a/content/smil/nsSMILTimeValue.h
+++ b/content/smil/nsSMILTimeValue.h
@@ -61,61 +61,45 @@
  * nsSMILTimeValueSpec -- a component of a begin or end attribute, such as the
  *                        '5s' or 'a.end+2m' in begin="5s; a.end+2m". Acts as
  *                        a broker between an nsSMILTimedElement and its
  *                        nsSMILInstanceTimes by generating new instance times
  *                        and handling changes to existing times.
  *
  * Objects of this class may be in one of three states:
  *
- * 1) The time is resolved and has a millisecond value
- * 2) The time is indefinite
- * 3) The time in unresolved
- *
- * There is considerable chance for confusion with regards to the indefinite
- * state. Is it resolved? We adopt the convention that it is NOT resolved (but
- * nor is it unresolved). This simplifies implementation as you can then write:
- *
- * if (time.IsResolved())
- *    x = time.GetMillis()
- *
- * instead of:
- *
- * if (time.IsResolved() && !time.IsIndefinite())
- *    x = time.GetMillis()
- *
- * Testing if a time is unresolved becomes more complicated but this is tested
- * much less often.
+ * 1) The time is resolved and has a definite millisecond value
+ * 2) The time is resolved and indefinite
+ * 3) The time is unresolved
  *
  * In summary:
  *
- * State         |  GetMillis         |  IsResolved        |  IsIndefinite
- * --------------+--------------------+--------------------+-------------------
- * Resolved      |  The millisecond   |  PR_TRUE           |  PR_FALSE
- *               |  time              |                    |
- * --------------+--------------------+--------------------+-------------------
- * Indefinite    |  LL_MAXINT         |  PR_FALSE          |  PR_TRUE
- * --------------+--------------------+--------------------+-------------------
- * Unresolved    |  LL_MAXINT         |  PR_FALSE          |  PR_FALSE
+ * State      | GetMillis       | IsDefinite | IsIndefinite | IsResolved
+ * -----------+-----------------+------------+--------------+------------
+ * Definite   | nsSMILTimeValue | PR_TRUE    | PR_FALSE     | PR_TRUE
+ * -----------+-----------------+------------+--------------+------------
+ * Indefinite | --              | PR_FALSE   | PR_TRUE      | PR_TRUE
+ * -----------+-----------------+------------+--------------+------------
+ * Unresolved | --              | PR_FALSE   | PR_FALSE     | PR_FALSE
  *
  */
 
 class nsSMILTimeValue
 {
 public:
   // Creates an unresolved time value
   nsSMILTimeValue()
   : mMilliseconds(kUnresolvedMillis),
     mState(STATE_UNRESOLVED)
   { }
 
   // Creates a resolved time value
   explicit nsSMILTimeValue(nsSMILTime aMillis)
   : mMilliseconds(aMillis),
-    mState(STATE_RESOLVED)
+    mState(STATE_DEFINITE)
   { }
 
   // Named constructor to create an indefinite time value
   static nsSMILTimeValue Indefinite()
   {
     nsSMILTimeValue value;
     value.SetIndefinite();
     return value;
@@ -123,34 +107,35 @@ public:
 
   PRBool IsIndefinite() const { return mState == STATE_INDEFINITE; }
   void SetIndefinite()
   {
     mState = STATE_INDEFINITE;
     mMilliseconds = kUnresolvedMillis;
   }
 
-  PRBool IsResolved() const { return mState == STATE_RESOLVED; }
+  PRBool IsResolved() const { return mState != STATE_UNRESOLVED; }
   void SetUnresolved()
   {
     mState = STATE_UNRESOLVED;
     mMilliseconds = kUnresolvedMillis;
   }
 
+  PRBool IsDefinite() const { return mState == STATE_DEFINITE; }
   nsSMILTime GetMillis() const
   {
-    NS_ABORT_IF_FALSE(mState == STATE_RESOLVED,
-       "GetMillis() called for unresolved time");
+    NS_ABORT_IF_FALSE(mState == STATE_DEFINITE,
+       "GetMillis() called for unresolved or indefinite time");
 
-    return mState == STATE_RESOLVED ? mMilliseconds : kUnresolvedMillis;
+    return mState == STATE_DEFINITE ? mMilliseconds : kUnresolvedMillis;
   }
 
   void SetMillis(nsSMILTime aMillis)
   {
-    mState = STATE_RESOLVED;
+    mState = STATE_DEFINITE;
     mMilliseconds = aMillis;
   }
 
   PRInt8 CompareTo(const nsSMILTimeValue& aOther) const;
 
   PRBool operator==(const nsSMILTimeValue& aOther) const
   { return CompareTo(aOther) == 0; }
 
@@ -167,17 +152,17 @@ public:
   { return CompareTo(aOther) <= 0; }
 
   PRBool operator>=(const nsSMILTimeValue& aOther) const
   { return CompareTo(aOther) >= 0; }
 
 private:
   static nsSMILTime kUnresolvedMillis;
 
-  nsSMILTime        mMilliseconds;
+  nsSMILTime mMilliseconds;
   enum {
-    STATE_RESOLVED,
+    STATE_DEFINITE,
     STATE_INDEFINITE,
     STATE_UNRESOLVED
   } mState;
 };
 
 #endif // NS_SMILTIMEVALUE_H_
--- a/content/smil/nsSMILTimeValueSpec.cpp
+++ b/content/smil/nsSMILTimeValueSpec.cpp
@@ -177,17 +177,17 @@ nsSMILTimeValueSpec::HandleNewInterval(n
                                        const nsSMILTimeContainer* aSrcContainer)
 {
   const nsSMILInstanceTime& baseInstance = mParams.mSyncBegin
     ? *aInterval.Begin() : *aInterval.End();
   nsSMILTimeValue newTime =
     ConvertBetweenTimeContainers(baseInstance.Time(), aSrcContainer);
 
   // Apply offset
-  if (newTime.IsResolved()) {
+  if (newTime.IsDefinite()) {
     newTime.SetMillis(newTime.GetMillis() + mParams.mOffset.GetMillis());
   }
 
   // Create the instance time and register it with the interval
   nsRefPtr<nsSMILInstanceTime> newInstance =
     new nsSMILInstanceTime(newTime, nsSMILInstanceTime::SOURCE_SYNCBASE, this,
                            &aInterval);
   mOwner->AddInstanceTime(newInstance, mIsBegin);
@@ -213,17 +213,17 @@ nsSMILTimeValueSpec::HandleChangedInstan
   // time of an active or postactive interval) we just ignore the change.
   if (aInstanceTimeToUpdate.IsFixedTime())
     return;
 
   nsSMILTimeValue updatedTime =
     ConvertBetweenTimeContainers(aBaseTime.Time(), aSrcContainer);
 
   // Apply offset
-  if (updatedTime.IsResolved()) {
+  if (updatedTime.IsDefinite()) {
     updatedTime.SetMillis(updatedTime.GetMillis() +
                           mParams.mOffset.GetMillis());
   }
 
   // The timed element that owns the instance time does the updating so it can
   // re-sort its array of instance times more efficiently
   if (aInstanceTimeToUpdate.Time() != updatedTime || aObjectChanged) {
     mOwner->UpdateInstanceTime(&aInstanceTimeToUpdate, updatedTime, mIsBegin);
@@ -504,17 +504,17 @@ nsSMILTimeValueSpec::CheckAccessKeyEvent
 
 nsSMILTimeValue
 nsSMILTimeValueSpec::ConvertBetweenTimeContainers(
     const nsSMILTimeValue& aSrcTime,
     const nsSMILTimeContainer* aSrcContainer)
 {
   // If the source time is either indefinite or unresolved the result is going
   // to be the same
-  if (!aSrcTime.IsResolved())
+  if (!aSrcTime.IsDefinite())
     return aSrcTime;
 
   // Convert from source time container to our parent time container
   const nsSMILTimeContainer* dstContainer = mOwner->GetTimeContainer();
   if (dstContainer == aSrcContainer)
     return aSrcTime;
 
   // If one of the elements is not attached to a time container then we can't do
@@ -525,13 +525,13 @@ nsSMILTimeValueSpec::ConvertBetweenTimeC
   nsSMILTimeValue docTime =
     aSrcContainer->ContainerToParentTime(aSrcTime.GetMillis());
 
   if (docTime.IsIndefinite())
     // This will happen if the source container is paused and we have a future
     // time. Just return the indefinite time.
     return docTime;
 
-   NS_ABORT_IF_FALSE(docTime.IsResolved(),
-       "ContainerToParentTime gave us an unresolved time");
+  NS_ABORT_IF_FALSE(docTime.IsDefinite(),
+    "ContainerToParentTime gave us an unresolved or indefinite time");
 
   return dstContainer->ParentToContainerTime(docTime.GetMillis());
 }
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -913,31 +913,31 @@ nsSMILTimedElement::SetSimpleDuration(co
   rv = nsSMILParserUtils::ParseClockValue(aDurSpec, &duration,
           nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
 
   if (NS_FAILED(rv)) {
     mSimpleDur.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
-  if (duration.IsResolved() && duration.GetMillis() == 0L) {
+  if (duration.IsDefinite() && duration.GetMillis() == 0L) {
     mSimpleDur.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
   //
   // SVG-specific: "For SVG's animation elements, if "media" is specified, the
   // attribute will be ignored." (SVG 1.1, section 19.2.6)
   //
   if (isMedia)
     duration.SetIndefinite();
 
   // mSimpleDur should never be unresolved. ParseClockValue will either set
   // duration to resolved/indefinite/media or will return a failure code.
-  NS_ASSERTION(duration.IsResolved() || duration.IsIndefinite(),
+  NS_ABORT_IF_FALSE(duration.IsResolved(),
     "Setting unresolved simple duration");
 
   mSimpleDur = duration;
   UpdateCurrentInterval();
 
   return NS_OK;
 }
 
@@ -956,17 +956,17 @@ nsSMILTimedElement::SetMin(const nsAStri
   nsresult rv;
 
   rv = nsSMILParserUtils::ParseClockValue(aMinSpec, &duration, 0, &isMedia);
 
   if (isMedia) {
     duration.SetMillis(0L);
   }
 
-  if (NS_FAILED(rv) || !duration.IsResolved()) {
+  if (NS_FAILED(rv) || !duration.IsDefinite()) {
     mMin.SetMillis(0L);
     return NS_ERROR_FAILURE;
   }
 
   if (duration.GetMillis() < 0L) {
     mMin.SetMillis(0L);
     return NS_ERROR_FAILURE;
   }
@@ -992,22 +992,22 @@ nsSMILTimedElement::SetMax(const nsAStri
   nsresult rv;
 
   rv = nsSMILParserUtils::ParseClockValue(aMaxSpec, &duration,
           nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
 
   if (isMedia)
     duration.SetIndefinite();
 
-  if (NS_FAILED(rv) || (!duration.IsResolved() && !duration.IsIndefinite())) {
+  if (NS_FAILED(rv) || !duration.IsResolved()) {
     mMax.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
-  if (duration.IsResolved() && duration.GetMillis() <= 0L) {
+  if (duration.IsDefinite() && duration.GetMillis() <= 0L) {
     mMax.SetIndefinite();
     return NS_ERROR_FAILURE;
   }
 
   mMax = duration;
   UpdateCurrentInterval();
 
   return NS_OK;
@@ -1069,17 +1069,17 @@ nsresult
 nsSMILTimedElement::SetRepeatDur(const nsAString& aRepeatDurSpec)
 {
   nsresult rv;
   nsSMILTimeValue duration;
 
   rv = nsSMILParserUtils::ParseClockValue(aRepeatDurSpec, &duration,
           nsSMILParserUtils::kClockValueAllowIndefinite);
 
-  if (NS_FAILED(rv) || (!duration.IsResolved() && !duration.IsIndefinite())) {
+  if (NS_FAILED(rv) || !duration.IsResolved()) {
     mRepeatDur.SetUnresolved();
     return NS_ERROR_FAILURE;
   }
 
   mRepeatDur = duration;
   UpdateCurrentInterval();
 
   return NS_OK;
@@ -1603,18 +1603,18 @@ nsSMILTimedElement::FilterInstanceTimes(
 // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start
 //
 PRBool
 nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
                                     const nsSMILInterval* aReplacedInterval,
                                     const nsSMILInstanceTime* aFixedBeginTime,
                                     nsSMILInterval& aResult) const
 {
-  NS_ABORT_IF_FALSE(!aFixedBeginTime || aFixedBeginTime->Time().IsResolved(),
-      "Unresolved begin time specified for interval start");
+  NS_ABORT_IF_FALSE(!aFixedBeginTime || aFixedBeginTime->Time().IsDefinite(),
+      "Unresolved or indefinite begin time specified for interval start");
   static const nsSMILTimeValue zeroTime(0L);
 
   if (mRestartMode == RESTART_NEVER && aPrevInterval)
     return PR_FALSE;
 
   // Calc starting point
   nsSMILTimeValue beginAfter;
   PRBool prevIntervalWasZeroDur = PR_FALSE;
@@ -1650,23 +1650,23 @@ nsSMILTimedElement::GetNextInterval(cons
       // If we're updating the current interval then skip any begin time that is
       // dependent on the current interval's begin time. e.g.
       //   <animate id="a" begin="b.begin; a.begin+2s"...
       // If b's interval disappears whilst 'a' is in the waiting state the begin
       // time at "a.begin+2s" should be skipped since 'a' never begun.
       do {
         tempBegin =
           GetNextGreaterOrEqual(mBeginInstances, beginAfter, beginPos);
-        if (!tempBegin || !tempBegin->Time().IsResolved()) {
+        if (!tempBegin || !tempBegin->Time().IsDefinite()) {
           return PR_FALSE;
         }
       } while (aReplacedInterval &&
                tempBegin->GetBaseTime() == aReplacedInterval->Begin());
     }
-    NS_ABORT_IF_FALSE(tempBegin && tempBegin->Time().IsResolved() &&
+    NS_ABORT_IF_FALSE(tempBegin && tempBegin->Time().IsDefinite() &&
         tempBegin->Time() >= beginAfter,
         "Got a bad begin time while fetching next interval");
 
     // Calculate end time
     {
       PRInt32 endPos = 0;
       // As above with begin times, avoid creating self-referential loops
       // between instance times by checking that the newly found end instance
@@ -1683,25 +1683,24 @@ nsSMILTimedElement::GetNextInterval(cons
           prevIntervalWasZeroDur) {
         tempEnd = GetNextGreater(mEndInstances, tempBegin->Time(), endPos);
       }
 
       // If all the ends are before the beginning we have a bad interval UNLESS:
       // a) We never had any end attribute to begin with (and hence we should
       //    just use the active duration after allowing for the possibility of
       //    an end instance provided by a DOM call), OR
-      // b) We have no resolved (not incl. indefinite) end instances
-      //    (SMIL only says "if the instance list is empty"--but if we have
-      //    indefinite/unresolved instance times then there must be a good
-      //    reason we haven't used them (since they'll be >= tempBegin) such as
-      //    avoiding creating a self-referential loop. In any case, the interval
-      //    should be allowed to be open.), OR
+      // b) We have no definite end instances (SMIL only says "if the instance
+      //    list is empty"--but if we have indefinite/unresolved instance times
+      //    then there must be a good reason we haven't used them (since they
+      //    will be >= tempBegin) such as avoiding creating a self-referential
+      //    loop. In any case, the interval should be allowed to be open.), OR
       // c) We have end events which leave the interval open-ended.
       PRBool openEndedIntervalOk = mEndSpecs.IsEmpty() ||
-                                   !HaveResolvedEndTimes() ||
+                                   !HaveDefiniteEndTimes() ||
                                    EndHasEventConditions();
       if (!tempEnd && !openEndedIntervalOk)
         return PR_FALSE; // Bad interval
 
       nsSMILTimeValue intervalEnd = tempEnd
                                   ? tempEnd->Time() : nsSMILTimeValue();
       nsSMILTimeValue activeEnd = CalcActiveEnd(tempBegin->Time(), intervalEnd);
 
@@ -1709,17 +1708,17 @@ nsSMILTimedElement::GetNextInterval(cons
         tempEnd = new nsSMILInstanceTime(activeEnd);
       }
     }
     NS_ABORT_IF_FALSE(tempEnd, "Failed to get end point for next interval");
 
     // If we get two zero-length intervals in a row we will potentially have an
     // infinite loop so we break it here by searching for the next begin time
     // greater than tempEnd on the next time around.
-    if (tempEnd->Time().IsResolved() && tempBegin->Time() == tempEnd->Time()) {
+    if (tempEnd->Time().IsDefinite() && tempBegin->Time() == tempEnd->Time()) {
       if (prevIntervalWasZeroDur) {
         beginAfter.SetMillis(tempEnd->Time().GetMillis() + 1);
         prevIntervalWasZeroDur = PR_FALSE;
         continue;
       }
       prevIntervalWasZeroDur = PR_TRUE;
     }
 
@@ -1776,79 +1775,79 @@ nsSMILTimedElement::GetNextGreaterOrEqua
  * @see SMILANIM 3.3.4
  */
 nsSMILTimeValue
 nsSMILTimedElement::CalcActiveEnd(const nsSMILTimeValue& aBegin,
                                   const nsSMILTimeValue& aEnd) const
 {
   nsSMILTimeValue result;
 
-  NS_ABORT_IF_FALSE(mSimpleDur.IsResolved() || mSimpleDur.IsIndefinite(),
+  NS_ABORT_IF_FALSE(mSimpleDur.IsResolved(),
     "Unresolved simple duration in CalcActiveEnd");
-  NS_ABORT_IF_FALSE(aBegin.IsResolved(),
-    "Unresolved begin time in CalcActiveEnd");
+  NS_ABORT_IF_FALSE(aBegin.IsDefinite(),
+    "Indefinite or unresolved begin time in CalcActiveEnd");
 
   if (mRepeatDur.IsIndefinite()) {
     result.SetIndefinite();
   } else {
     result = GetRepeatDuration();
   }
 
-  if (aEnd.IsResolved()) {
+  if (aEnd.IsDefinite()) {
     nsSMILTime activeDur = aEnd.GetMillis() - aBegin.GetMillis();
 
-    if (result.IsResolved()) {
+    if (result.IsDefinite()) {
       result.SetMillis(NS_MIN(result.GetMillis(), activeDur));
     } else {
       result.SetMillis(activeDur);
     }
   }
 
   result = ApplyMinAndMax(result);
 
-  if (result.IsResolved()) {
+  if (result.IsDefinite()) {
     nsSMILTime activeEnd = result.GetMillis() + aBegin.GetMillis();
     result.SetMillis(activeEnd);
   }
 
   return result;
 }
 
 nsSMILTimeValue
 nsSMILTimedElement::GetRepeatDuration() const
 {
   nsSMILTimeValue result;
 
-  if (mRepeatCount.IsDefinite() && mRepeatDur.IsResolved()) {
-    if (mSimpleDur.IsResolved()) {
+  if (mRepeatCount.IsDefinite() && mRepeatDur.IsDefinite()) {
+    if (mSimpleDur.IsDefinite()) {
       nsSMILTime activeDur =
         nsSMILTime(mRepeatCount * double(mSimpleDur.GetMillis()));
       result.SetMillis(NS_MIN(activeDur, mRepeatDur.GetMillis()));
     } else {
       result = mRepeatDur;
     }
-  } else if (mRepeatCount.IsDefinite() && mSimpleDur.IsResolved()) {
+  } else if (mRepeatCount.IsDefinite() && mSimpleDur.IsDefinite()) {
     nsSMILTime activeDur =
       nsSMILTime(mRepeatCount * double(mSimpleDur.GetMillis()));
     result.SetMillis(activeDur);
-  } else if (mRepeatDur.IsResolved()) {
+  } else if (mRepeatDur.IsDefinite()) {
     result = mRepeatDur;
   } else if (mRepeatCount.IsIndefinite()) {
     result.SetIndefinite();
   } else {
     result = mSimpleDur;
   }
 
   return result;
 }
 
 nsSMILTimeValue
 nsSMILTimedElement::ApplyMinAndMax(const nsSMILTimeValue& aDuration) const
 {
-  if (!aDuration.IsResolved() && !aDuration.IsIndefinite()) {
+  if (!aDuration.IsResolved()) {
     return aDuration;
   }
 
   if (mMax < mMin) {
     return aDuration;
   }
 
   nsSMILTimeValue result;
@@ -1866,17 +1865,17 @@ nsSMILTimedElement::ApplyMinAndMax(const
 }
 
 nsSMILTime
 nsSMILTimedElement::ActiveTimeToSimpleTime(nsSMILTime aActiveTime,
                                            PRUint32& aRepeatIteration)
 {
   nsSMILTime result;
 
-  NS_ASSERTION(mSimpleDur.IsResolved() || mSimpleDur.IsIndefinite(),
+  NS_ASSERTION(mSimpleDur.IsResolved(),
       "Unresolved simple duration in ActiveTimeToSimpleTime");
   NS_ASSERTION(aActiveTime >= 0, "Expecting non-negative active time");
   // Note that a negative aActiveTime will give us a negative value for
   // aRepeatIteration, which is bad because aRepeatIteration is unsigned
 
   if (mSimpleDur.IsIndefinite() || mSimpleDur.GetMillis() == 0L) {
     aRepeatIteration = 0;
     result = aActiveTime;
@@ -2030,17 +2029,17 @@ void
 nsSMILTimedElement::SampleFillValue()
 {
   if (mFillMode != FILL_FREEZE || !mClient)
     return;
 
   const nsSMILInterval* prevInterval = GetPreviousInterval();
   NS_ABORT_IF_FALSE(prevInterval,
       "Attempting to sample fill value but there is no previous interval");
-  NS_ABORT_IF_FALSE(prevInterval->End()->Time().IsResolved() &&
+  NS_ABORT_IF_FALSE(prevInterval->End()->Time().IsDefinite() &&
       prevInterval->End()->IsFixedTime(),
       "Attempting to sample fill value but the endpoint of the previous "
       "interval is not resolved and fixed");
 
   nsSMILTime activeTime = prevInterval->End()->Time().GetMillis() -
                           prevInterval->Begin()->Time().GetMillis();
 
   PRUint32 repeatIteration;
@@ -2131,33 +2130,33 @@ nsSMILTimedElement::GetNextMilestone(nsS
     aNextMilestone.mIsEnd = PR_FALSE;
     aNextMilestone.mTime = mCurrentInterval->Begin()->Time().GetMillis();
     return PR_TRUE;
 
   case STATE_ACTIVE:
     {
       // Work out what comes next: the interval end or the next repeat iteration
       nsSMILTimeValue nextRepeat;
-      if (mSeekState == SEEK_NOT_SEEKING && mSimpleDur.IsResolved()) {
+      if (mSeekState == SEEK_NOT_SEEKING && mSimpleDur.IsDefinite()) {
         nextRepeat.SetMillis(mCurrentInterval->Begin()->Time().GetMillis() +
             (mCurrentRepeatIteration + 1) * mSimpleDur.GetMillis());
       }
       nsSMILTimeValue nextMilestone =
         NS_MIN(mCurrentInterval->End()->Time(), nextRepeat);
 
       // Check for an early end before that time
       nsSMILInstanceTime* earlyEnd = CheckForEarlyEnd(nextMilestone);
       if (earlyEnd) {
         aNextMilestone.mIsEnd = PR_TRUE;
         aNextMilestone.mTime = earlyEnd->Time().GetMillis();
         return PR_TRUE;
       }
 
       // Apply the previously calculated milestone
-      if (nextMilestone.IsResolved()) {
+      if (nextMilestone.IsDefinite()) {
         aNextMilestone.mIsEnd = nextMilestone != nextRepeat;
         aNextMilestone.mTime = nextMilestone.GetMillis();
         return PR_TRUE;
       }
 
       return PR_FALSE;
     }
 
@@ -2249,24 +2248,24 @@ const nsSMILInterval*
 nsSMILTimedElement::GetPreviousInterval() const
 {
   return mOldIntervals.IsEmpty()
     ? nsnull
     : mOldIntervals[mOldIntervals.Length()-1].get();
 }
 
 PRBool
-nsSMILTimedElement::HaveResolvedEndTimes() const
+nsSMILTimedElement::HaveDefiniteEndTimes() const
 {
   if (mEndInstances.IsEmpty())
     return PR_FALSE;
 
-  // mEndInstances is sorted so if the first time is not resolved then none of
+  // mEndInstances is sorted so if the first time is not definite then none of
   // them are
-  return mEndInstances[0]->Time().IsResolved();
+  return mEndInstances[0]->Time().IsDefinite();
 }
 
 PRBool
 nsSMILTimedElement::EndHasEventConditions() const
 {
   for (PRUint32 i = 0; i < mEndSpecs.Length(); ++i) {
     if (mEndSpecs[i]->IsEventBased())
       return PR_TRUE;
--- a/content/smil/nsSMILTimedElement.h
+++ b/content/smil/nsSMILTimedElement.h
@@ -520,17 +520,17 @@ protected:
   void              NotifyChangedInterval(nsSMILInterval* aInterval,
                                           PRBool aBeginObjectChanged,
                                           PRBool aEndObjectChanged);
 
   void              FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail);
   const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
   const nsSMILInterval* GetPreviousInterval() const;
   PRBool            HasPlayed() const { return !mOldIntervals.IsEmpty(); }
-  PRBool            HaveResolvedEndTimes() const;
+  PRBool            HaveDefiniteEndTimes() const;
   PRBool            EndHasEventConditions() const;
 
   // Reset the current interval by first passing ownership to a temporary
   // variable so that if Unlink() results in us receiving a callback,
   // mCurrentInterval will be nsnull and we will be in a consistent state.
   void ResetCurrentInterval()
   {
     if (mCurrentInterval) {
--- a/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp
+++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp
@@ -378,16 +378,28 @@ SVGMotionSMILAnimationFunction::
 {
   // Call superclass method.
   nsSMILAnimationFunction::CheckValueListDependentAttrs(aNumValues);
 
   // Added behavior: Do checks specific to keyPoints.
   CheckKeyPoints();
 }
 
+PRBool
+SVGMotionSMILAnimationFunction::IsToAnimation() const
+{
+  // Rely on inherited method, but not if we have an <mpath> child or a |path|
+  // attribute, because they'll override any 'to' attr we might have.
+  // NOTE: We can't rely on mPathSourceType, because it might not have been
+  // set to a useful value yet (or it might be stale).
+  return !GetFirstMpathChild(&mAnimationElement->AsElement()) &&
+    !HasAttr(nsGkAtoms::path) &&
+    nsSMILAnimationFunction::IsToAnimation();
+}
+
 void
 SVGMotionSMILAnimationFunction::CheckKeyPoints()
 {
   if (!HasAttr(nsGkAtoms::keyPoints))
     return;
 
   // attribute is ignored for calcMode="paced" (even if it's got errors)
   if (GetCalcMode() == CALC_PACED) {
@@ -480,20 +492,9 @@ SVGMotionSMILAnimationFunction::SetRotat
 void
 SVGMotionSMILAnimationFunction::UnsetRotate()
 {
   mRotateAngle = 0.0f; // default value
   mRotateType = eRotateType_Explicit;
   mHasChanged = PR_TRUE;
 }
 
-PRBool
-SVGMotionSMILAnimationFunction::TreatSingleValueAsStatic() const
-{
-  // <animateMotion> has two more ways that we could be just sampling a single
-  // value -- via path attribute and the <mpath> element, with a path
-  // description that just includes a single "move" command.
-  return (mPathSourceType == ePathSourceType_ValuesAttr ||
-          mPathSourceType == ePathSourceType_PathAttr ||
-          mPathSourceType == ePathSourceType_Mpath);
-}
-
 } // namespace mozilla
--- a/content/svg/content/src/SVGMotionSMILAnimationFunction.h
+++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.h
@@ -80,17 +80,18 @@ protected:
     ePathSourceType_PathAttr,
     ePathSourceType_Mpath
   };
 
   NS_OVERRIDE virtual nsSMILCalcMode GetCalcMode() const;
   NS_OVERRIDE virtual nsresult GetValues(const nsISMILAttr& aSMILAttr,
                                          nsSMILValueArray& aResult);
   NS_OVERRIDE virtual void CheckValueListDependentAttrs(PRUint32 aNumValues);
-  NS_OVERRIDE virtual PRBool TreatSingleValueAsStatic() const;
+
+  NS_OVERRIDE virtual PRBool IsToAnimation() const;
 
   void     CheckKeyPoints();
   nsresult SetKeyPoints(const nsAString& aKeyPoints, nsAttrValue& aResult);
   void     UnsetKeyPoints();
   nsresult SetRotate(const nsAString& aRotate, nsAttrValue& aResult);
   void     UnsetRotate();
 
   // Helpers for GetValues
--- a/content/svg/content/src/nsSVGAnimationElement.cpp
+++ b/content/svg/content/src/nsSVGAnimationElement.cpp
@@ -211,17 +211,17 @@ nsSVGAnimationElement::GetTargetElement(
 
 /* float getStartTime() raises( DOMException ); */
 NS_IMETHODIMP
 nsSVGAnimationElement::GetStartTime(float* retval)
 {
   FlushAnimations();
 
   nsSMILTimeValue startTime = mTimedElement.GetStartTime();
-  if (!startTime.IsResolved())
+  if (!startTime.IsDefinite())
     return NS_ERROR_DOM_INVALID_STATE_ERR;
 
   *retval = float(double(startTime.GetMillis()) / PR_MSEC_PER_SEC);
 
   return NS_OK;
 }
 
 /* float getCurrentTime(); */
@@ -241,17 +241,17 @@ nsSVGAnimationElement::GetCurrentTime(fl
 
 /* float getSimpleDuration() raises( DOMException ); */
 NS_IMETHODIMP
 nsSVGAnimationElement::GetSimpleDuration(float* retval)
 {
   // Not necessary to call FlushAnimations() for this
 
   nsSMILTimeValue simpleDur = mTimedElement.GetSimpleDuration();
-  if (!simpleDur.IsResolved()) {
+  if (!simpleDur.IsDefinite()) {
     *retval = 0.f;
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
   *retval = float(double(simpleDur.GetMillis()) / PR_MSEC_PER_SEC);
   return NS_OK;
 }
 
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -5430,17 +5430,17 @@ nsSVGFEImageElement::LoadSVGImage(PRBool
   nsAutoString href;
   mStringAttributes[HREF].GetAnimValue(href, this);
   href.Trim(" \t\n\r");
 
   if (baseURI && !href.IsEmpty())
     NS_MakeAbsoluteURI(href, href, baseURI);
 
   // Make sure we don't get in a recursive death-spiral
-  nsIDocument* doc = GetOurDocument();
+  nsIDocument* doc = GetOwnerDoc();
   if (doc) {
     nsCOMPtr<nsIURI> hrefAsURI;
     if (NS_SUCCEEDED(StringToURI(href, doc, getter_AddRefs(hrefAsURI)))) {
       PRBool isEqual;
       if (NS_SUCCEEDED(hrefAsURI->Equals(baseURI, &isEqual)) && isEqual) {
         // Image URI matches our URI exactly! Bail out.
         return NS_OK;
       }
--- a/content/xbl/crashtests/crashtests.list
+++ b/content/xbl/crashtests/crashtests.list
@@ -26,12 +26,12 @@ load 421997-1.xhtml
 load 432813-1.xhtml
 load 454820-1.html
 load 460665-1.xhtml
 load 463511-1.xhtml
 load 464863-1.xhtml
 load 472260-1.xhtml
 load 477878-1.html
 load 492978-1.xul
-load 493123-1.xhtml
+asserts-if(Android,2) load 493123-1.xhtml
 load 495354-1.xhtml
 load 507628-1.xhtml
 load 507991-1.xhtml
--- a/docshell/base/crashtests/crashtests.list
+++ b/docshell/base/crashtests/crashtests.list
@@ -1,13 +1,13 @@
 load 40929-1.html
 load 369126-1.html
 load 403574-1.xhtml
 load 430124-1.html
 load 430628-1.html
 load 432114-1.html
 load 432114-2.html
-load 436900-1.html
-asserts(0-2) load 436900-2.html # bug 566159
+asserts-if(Android,2) load 436900-1.html
+asserts(0-3) load 436900-2.html # bug 566159
 load 500328-1.html
 load 514779-1.xhtml
 load 614499-1.html
 load 678872-1.html
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -1,9 +1,9 @@
-load 90613-1.html
+asserts-if(Android,1) load 90613-1.html
 load 244933-1.html
 load 275912-1.html
 load 327571-1.html
 load 327695-1.html
 load 329481-1.xhtml
 load 338674-1.xhtml
 load 346381-1.html
 load 359432-1.xhtml
@@ -16,16 +16,16 @@ load 375399-1.html
 load 404869-1.xul
 load 417852-1.html
 load 462947.html
 load 439206-1.html
 load 473284.xul
 load 499006-1.html
 load 499006-2.html
 load 502617.html
-asserts(1) load 504224.html # bug 564098
+asserts(1-2) load 504224.html # bug 564098
 load 603531.html
 load 601247.html
 load 609560-1.xhtml
 load 612018-1.html
 load 637116.html
 load 666869.html
 load 675621-1.html
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -521,16 +521,17 @@ static const char kDOMStringBundleURL[] 
   nsIXPCScriptable::WANT_FINALIZE |                                           \
   nsIXPCScriptable::WANT_EQUALITY |                                           \
   nsIXPCScriptable::WANT_ENUMERATE |                                          \
   nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |                               \
   nsIXPCScriptable::WANT_OUTER_OBJECT)
 
 #define NODE_SCRIPTABLE_FLAGS                                                 \
  ((DOM_DEFAULT_SCRIPTABLE_FLAGS |                                             \
+   nsIXPCScriptable::USE_STUB_EQUALITY_HOOK |                                 \
    nsIXPCScriptable::WANT_GETPROPERTY |                                       \
    nsIXPCScriptable::WANT_ADDPROPERTY |                                       \
    nsIXPCScriptable::WANT_SETPROPERTY) &                                      \
   ~nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY)
 
 // We need to let JavaScript QI elements to interfaces that are not in
 // the classinfo since XBL can be used to dynamically implement new
 // unknown interfaces on elements, accessibility relies on this being
@@ -660,17 +661,18 @@ static nsDOMClassInfoData sClassInfoData
                            (DOM_DEFAULT_SCRIPTABLE_FLAGS &
                             ~nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE))
 
   NS_DEFINE_CLASSINFO_DATA(CaretPosition, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(Navigator, nsNavigatorSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                           nsIXPCScriptable::WANT_PRECREATE)
+                           nsIXPCScriptable::WANT_PRECREATE |
+                           nsIXPCScriptable::WANT_NEWRESOLVE)
   NS_DEFINE_CLASSINFO_DATA(Plugin, nsPluginSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PluginArray, nsPluginArraySH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MimeType, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MimeTypeArray, nsMimeTypeArraySH,
                            ARRAY_SCRIPTABLE_FLAGS)
@@ -2009,33 +2011,35 @@ CutPrefix(const char *aName) {
 
   return aName;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
 {
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
                                       aClassInfoID,
                                       sClassInfoData[aClassInfoID].mChromeOnly,
                                       sClassInfoData[aClassInfoID].mDisabled,
                                       &sClassInfoData[aClassInfoID].mNameUTF16);
 
   return NS_OK;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterClassProtos(PRInt32 aClassInfoID)
 {
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
   PRBool found_old;
 
   const nsIID *primary_iid = sClassInfoData[aClassInfoID].mProtoChainInterface;
 
   if (!primary_iid || primary_iid == &NS_GET_IID(nsISupports)) {
     return NS_OK;
   }
@@ -2077,17 +2081,18 @@ nsDOMClassInfo::RegisterClassProtos(PRIn
 
   return NS_OK;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterExternalClasses()
 {
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nsCOMPtr<nsIComponentRegistrar> registrar;
   nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsICategoryManager> cm =
     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
@@ -5526,17 +5531,18 @@ private:
     return nameStruct;
   }
 
   static nsresult GetNameStruct(const nsAString& aName,
                                 const nsGlobalNameStruct **aNameStruct)
   {
     *aNameStruct = nsnull;
 
-    nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+    nsScriptNameSpaceManager *nameSpaceManager =
+      nsJSRuntime::GetNameSpaceManager();
     if (!nameSpaceManager) {
       NS_ERROR("Can't get namespace manager.");
       return NS_ERROR_UNEXPECTED;
     }
 
     nameSpaceManager->LookupName(aName, aNameStruct);
 
     // Return NS_OK here, aName just isn't a DOM class but nothing failed.
@@ -5734,17 +5740,18 @@ nsDOMConstructor::HasInstance(nsIXPConne
   NS_ENSURE_TRUE(class_name_struct, NS_ERROR_FAILURE);
 
   if (name_struct == class_name_struct) {
     *bp = JS_TRUE;
 
     return NS_OK;
   }
 
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ASSERTION(nameSpaceManager, "Can't get namespace manager?");
 
   const nsIID *class_iid;
   if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
       class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
     class_iid = &class_name_struct->mIID;
   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     class_iid =
@@ -6087,17 +6094,18 @@ ResolvePrototype(nsIXPConnect *aXPConnec
 
 // static
 nsresult
 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                           JSObject *obj, jsid id, PRBool *did_resolve)
 {
   *did_resolve = PR_FALSE;
 
-  nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nsDependentJSString name(id);
 
   const nsGlobalNameStruct *name_struct = nsnull;
   const PRUnichar *class_name = nsnull;
 
   nameSpaceManager->LookupName(name, &name_struct, &class_name);
@@ -6373,29 +6381,40 @@ LocationSetterGuts(JSContext *cx, JSObje
 
   nsCOMPtr<Interface> xpcomObj = do_QueryWrappedNative(wrapper);
   NS_ENSURE_TRUE(xpcomObj, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIDOMLocation> location;
   nsresult rv = xpcomObj->GetLocation(getter_AddRefs(location));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Grab the value we're being set to before we stomp on |vp|
   JSString *val = ::JS_ValueToString(cx, *vp);
   NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
 
+  // Make sure |val| stays alive below
+  JS::Anchor<JSString *> anchor(val);
+
+  // We have to wrap location into vp before null-checking location, to
+  // avoid assigning the wrong thing into the slot.
+  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+  rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), location,
+                  &NS_GET_IID(nsIDOMLocation), PR_TRUE, vp,
+                  getter_AddRefs(holder));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!location) {
+    // Make this a no-op
+    return NS_OK;
+  }
+
   nsDependentJSString depStr;
   NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
   
-  rv = location->SetHref(depStr);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-  return WrapNative(cx, JS_GetGlobalForScopeChain(cx), location,
-                    &NS_GET_IID(nsIDOMLocation), PR_TRUE, vp,
-                    getter_AddRefs(holder));
+  return location->SetHref(depStr);
 }
 
 template<class Interface>
 static JSBool
 LocationSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
                jsval *vp)
 {
   nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
@@ -7015,16 +7034,87 @@ nsLocationSH::PreCreate(nsISupports *nat
     return NS_ERROR_UNEXPECTED;
   }
 
   *parentObj = sgo->GetGlobalJSObject();
   return NS_OK;
 }
 
 // DOM Navigator helper
+
+NS_IMETHODIMP
+nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                          JSObject *obj, jsid id, PRUint32 flags,
+                          JSObject **objp, PRBool *_retval)
+{
+  if (!JSID_IS_STRING(id) || (flags & JSRESOLVE_ASSIGNING)) {
+    return NS_OK;
+  }
+
+  nsScriptNameSpaceManager *nameSpaceManager =
+    nsJSRuntime::GetNameSpaceManager();
+  NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
+
+  nsDependentJSString name(id);
+
+  const nsGlobalNameStruct *name_struct = nsnull;
+
+  nameSpaceManager->LookupNavigatorName(name, &name_struct);
+
+  if (!name_struct) {
+    return NS_OK;
+  }
+  NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty,
+               "unexpected type");
+
+  nsresult rv = NS_OK;
+
+  nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  jsval prop_val = JSVAL_VOID; // Property value.
+
+  nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
+
+  if (gpi) {
+    JSObject *global = JS_GetGlobalForObject(cx, obj);
+
+    nsISupports *globalNative = XPConnect()->GetNativeOfWrapper(cx, global);
+    nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(globalNative);
+
+    if (!window) {
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    rv = gpi->Init(window, &prop_val);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (JSVAL_IS_PRIMITIVE(prop_val)) {
+    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+    rv = WrapNative(cx, obj, native, PR_TRUE, &prop_val,
+                    getter_AddRefs(holder));
+
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (!JS_WrapValue(cx, &prop_val)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val, nsnull, nsnull,
+                                      JSPROP_ENUMERATE);
+
+  *_retval = PR_TRUE;
+  *objp = obj;
+
+  return ok ? NS_OK : NS_ERROR_FAILURE;
+}
+
+// static
 nsresult
 nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                          JSObject *globalObj, JSObject **parentObj)
 {
   // window.navigator is persisted across document transitions if
   // we're loading a page from the same origin. Because of that we
   // need to parent the navigator wrapper at the outer window to avoid
   // holding on to the inner window where the navigator was initially
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -476,16 +476,19 @@ protected:
 
   virtual ~nsNavigatorSH()
   {
   }
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
                        JSObject *globalObj, JSObject **parentObj);
+  NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                        JSObject *obj, jsid id, PRUint32 flags,
+                        JSObject **objp, PRBool *_retval);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNavigatorSH(aData);
   }
 };
 
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -532,16 +532,20 @@ public:
                                     const nsAString &aPopupWindowName,
                                     const nsAString &aPopupWindowFeatures);
 
   virtual PRUint32 GetSerial() {
     return mSerial;
   }
 
   static nsGlobalWindow* GetOuterWindowWithId(PRUint64 aWindowID) {
+    if (!sWindowsById) {
+      return nsnull;
+    }
+
     nsGlobalWindow* outerWindow = sWindowsById->Get(aWindowID);
     return outerWindow && !outerWindow->IsInnerWindow() ? outerWindow : nsnull;
   }
 
   static nsGlobalWindow* GetInnerWindowWithId(PRUint64 aInnerWindowID) {
     if (!sWindowsById) {
       return nsnull;
     }
--- a/dom/base/nsIScriptNameSpaceManager.h
+++ b/dom/base/nsIScriptNameSpaceManager.h
@@ -46,16 +46,19 @@
 
 #define JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY \
   "JavaScript-global-property"
 
 // a global property that is only accessible to privileged script 
 #define JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY \
   "JavaScript-global-privileged-property"
 
+#define JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY \
+  "JavaScript-navigator-property"
+
 #define JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY \
   "JavaScript-global-static-nameset"
 
 #define JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY \
   "JavaScript-global-dynamic-nameset"
 
 #define JAVASCRIPT_DOM_CLASS \
   "JavaScript-DOM-class"
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -143,28 +143,29 @@ nsScriptNameSpaceManager::nsScriptNameSp
   MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
 }
 
 nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
 {
   if (mIsInitialized) {
     // Destroy the hash
     PL_DHashTableFinish(&mGlobalNames);
+    PL_DHashTableFinish(&mNavigatorNames);
   }
   MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
 }
 
 nsGlobalNameStruct *
-nsScriptNameSpaceManager::AddToHash(const char *aKey,
+nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const char *aKey,
                                     const PRUnichar **aClassName)
 {
   NS_ConvertASCIItoUTF16 key(aKey);
   GlobalNameMapEntry *entry =
     static_cast<GlobalNameMapEntry *>
-               (PL_DHashTableOperate(&mGlobalNames, &key, PL_DHASH_ADD));
+               (PL_DHashTableOperate(aTable, &key, PL_DHASH_ADD));
 
   if (!entry) {
     return nsnull;
   }
 
   if (aClassName) {
     *aClassName = entry->mKey.get();
   }
@@ -366,17 +367,17 @@ nsScriptNameSpaceManager::RegisterExtern
 
 nsresult
 nsScriptNameSpaceManager::RegisterInterface(const char* aIfName,
                                             const nsIID *aIfIID,
                                             PRBool* aFoundOld)
 {
   *aFoundOld = PR_FALSE;
 
-  nsGlobalNameStruct *s = AddToHash(aIfName);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aIfName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType != nsGlobalNameStruct::eTypeNotInitialized) {
     *aFoundOld = PR_TRUE;
 
     return NS_OK;
   }
 
@@ -403,16 +404,25 @@ nsScriptNameSpaceManager::Init()
     GlobalNameHashInitEntry
   };
 
   mIsInitialized = PL_DHashTableInit(&mGlobalNames, &hash_table_ops, nsnull,
                                      sizeof(GlobalNameMapEntry), 
                                      GLOBALNAME_HASHTABLE_INITIAL_SIZE);
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_OUT_OF_MEMORY);
 
+  mIsInitialized = PL_DHashTableInit(&mNavigatorNames, &hash_table_ops, nsnull,
+                                     sizeof(GlobalNameMapEntry), 
+                                     GLOBALNAME_HASHTABLE_INITIAL_SIZE);
+  if (!mIsInitialized) {
+    PL_DHashTableFinish(&mGlobalNames);
+
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   nsresult rv = NS_OK;
 
   rv = FillHashWithDOMInterfaces();
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsICategoryManager> cm =
     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -427,16 +437,19 @@ nsScriptNameSpaceManager::Init()
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = FillHash(cm, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = FillHash(cm, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = FillHash(cm, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // Initial filling of the has table has been done.
   // Now, listen for changes.
   nsCOMPtr<nsIObserverService> serv = 
     do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
 
   if (serv) {
     serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID, PR_TRUE);
   }
@@ -505,27 +518,46 @@ nsScriptNameSpaceManager::LookupName(con
       *aClassName = nsnull;
     }
   }
 
   return NS_OK;
 }
 
 nsresult
+nsScriptNameSpaceManager::LookupNavigatorName(const nsAString& aName,
+                                              const nsGlobalNameStruct **aNameStruct)
+{
+  GlobalNameMapEntry *entry =
+    static_cast<GlobalNameMapEntry *>
+               (PL_DHashTableOperate(&mNavigatorNames, &aName,
+                                     PL_DHASH_LOOKUP));
+
+  if (PL_DHASH_ENTRY_IS_BUSY(entry) &&
+      !((&entry->mGlobalName)->mDisabled)) {
+    *aNameStruct = &entry->mGlobalName;
+  } else {
+    *aNameStruct = nsnull;
+  }
+
+  return NS_OK;
+}
+
+nsresult
 nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
                                             PRInt32 aDOMClassInfoID,
                                             PRBool aPrivileged,
                                             PRBool aDisabled,
                                             const PRUnichar **aResult)
 {
   if (!nsCRT::IsAscii(aClassName)) {
     NS_ERROR("Trying to register a non-ASCII class name");
     return NS_OK;
   }
-  nsGlobalNameStruct *s = AddToHash(aClassName, aResult);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName, aResult);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     return NS_OK;
   }
 
   // If a external constructor is already defined with aClassName we
   // won't overwrite it.
@@ -550,17 +582,17 @@ nsresult
 nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
                                              const nsIID *aConstructorProtoIID,
                                              PRBool *aFoundOld)
 {
   NS_ENSURE_ARG_POINTER(aConstructorProtoIID);
 
   *aFoundOld = PR_FALSE;
 
-  nsGlobalNameStruct *s = AddToHash(aClassName);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
       s->mType != nsGlobalNameStruct::eTypeInterface) {
     *aFoundOld = PR_TRUE;
 
     return NS_OK;
   }
@@ -570,17 +602,17 @@ nsScriptNameSpaceManager::RegisterClassP
 
   return NS_OK;
 }
 
 nsresult
 nsScriptNameSpaceManager::RegisterExternalClassName(const char *aClassName,
                                                     nsCID& aCID)
 {
-  nsGlobalNameStruct *s = AddToHash(aClassName);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   // If an external constructor is already defined with aClassName we
   // won't overwrite it.
 
   if (s->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     return NS_OK;
   }
@@ -600,17 +632,17 @@ nsScriptNameSpaceManager::RegisterDOMCID
                                             nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
                                             const nsIID *aProtoChainInterface,
                                             const nsIID **aInterfaces,
                                             PRUint32 aScriptableFlags,
                                             PRBool aHasClassInterface,
                                             const nsCID *aConstructorCID)
 {
   const PRUnichar* className;
-  nsGlobalNameStruct *s = AddToHash(aName, &className);
+  nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aName, &className);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   // If an external constructor is already defined with aClassName we
   // won't overwrite it.
 
   if (s->mType == nsGlobalNameStruct::eTypeClassConstructor ||
       s->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     return NS_OK;
@@ -652,16 +684,18 @@ nsScriptNameSpaceManager::AddCategoryEnt
   // Observe() but this way, we have only one place to update and this is
   // not performance sensitive.
   nsGlobalNameStruct::nametype type;
   if (strcmp(aCategory, JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeExternalConstructor;
   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY) == 0 ||
              strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeProperty;
+  } else if (strcmp(aCategory, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY) == 0) {
+    type = nsGlobalNameStruct::eTypeNavigatorProperty;
   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeStaticNameSet;
   } else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY) == 0) {
     type = nsGlobalNameStruct::eTypeDynamicNameSet;
   } else {
     return NS_OK;
   }
 
@@ -699,17 +733,17 @@ nsScriptNameSpaceManager::AddCategoryEnt
   nsMemory::Free(cidPtr);
 
   if (type == nsGlobalNameStruct::eTypeExternalConstructor) {
     nsXPIDLCString constructorProto;
     rv = aCategoryManager->GetCategoryEntry(JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY,
                                             categoryEntry.get(),
                                             getter_Copies(constructorProto));
     if (NS_SUCCEEDED(rv)) {
-      nsGlobalNameStruct *s = AddToHash(categoryEntry.get());
+      nsGlobalNameStruct *s = AddToHash(&mGlobalNames, categoryEntry.get());
       NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
       if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
         s->mAlias = new nsGlobalNameStruct::ConstructorAlias;
         s->mType = nsGlobalNameStruct::eTypeExternalConstructorAlias;
         s->mChromeOnly = PR_FALSE;
         s->mAlias->mCID = cid;
         AppendASCIItoUTF16(constructorProto, s->mAlias->mProtoName);
@@ -717,17 +751,24 @@ nsScriptNameSpaceManager::AddCategoryEnt
       } else {
         NS_WARNING("Global script name not overwritten!");
       }
 
       return NS_OK;
     }
   }
 
-  nsGlobalNameStruct *s = AddToHash(categoryEntry.get());
+  PLDHashTable *table;
+  if (type == nsGlobalNameStruct::eTypeNavigatorProperty) {
+    table = &mNavigatorNames;
+  } else {
+    table = &mGlobalNames;
+  }
+
+  nsGlobalNameStruct *s = AddToHash(table, categoryEntry.get());
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
 
   if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
     s->mType = type;
     s->mCID = cid;
     s->mChromeOnly =
       strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0;
   } else {
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -70,16 +70,17 @@ struct nsGlobalNameStruct
     nsString mProtoName;
     nsGlobalNameStruct* mProto;    
   };
 
   enum nametype {
     eTypeNotInitialized,
     eTypeInterface,
     eTypeProperty,
+    eTypeNavigatorProperty,
     eTypeExternalConstructor,
     eTypeStaticNameSet,
     eTypeDynamicNameSet,
     eTypeClassConstructor,
     eTypeClassProto,
     eTypeExternalClassInfoCreator,
     eTypeExternalClassInfo,
     eTypeExternalConstructorAlias
@@ -123,16 +124,22 @@ public:
   // Returns a nsGlobalNameStruct for aName, or null if one is not
   // found. The returned nsGlobalNameStruct is only guaranteed to be
   // valid until the next call to any of the methods in this class.
   // It also returns a pointer to the string buffer of the classname
   // in the nsGlobalNameStruct.
   nsresult LookupName(const nsAString& aName,
                       const nsGlobalNameStruct **aNameStruct,
                       const PRUnichar **aClassName = nsnull);
+  // Returns a nsGlobalNameStruct for the navigator property aName, or
+  // null if one is not found. The returned nsGlobalNameStruct is only
+  // guaranteed to be valid until the next call to any of the methods
+  // in this class.
+  nsresult LookupNavigatorName(const nsAString& aName,
+                               const nsGlobalNameStruct **aNameStruct);
 
   nsresult RegisterClassName(const char *aClassName,
                              PRInt32 aDOMClassInfoID,
                              PRBool aPrivileged,
                              PRBool aDisabled,
                              const PRUnichar **aResult);
 
   nsresult RegisterClassProto(const char *aClassName,
@@ -156,17 +163,17 @@ public:
 
   nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct);
 
 protected:
   // Adds a new entry to the hash and returns the nsGlobalNameStruct
   // that aKey will be mapped to. If mType in the returned
   // nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
   // already existed.
-  nsGlobalNameStruct *AddToHash(const char *aKey,
+  nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const char *aKey,
                                 const PRUnichar **aClassName = nsnull);
 
   nsresult FillHash(nsICategoryManager *aCategoryManager,
                     const char *aCategory);
   nsresult FillHashWithDOMInterfaces();
   nsresult RegisterInterface(const char* aIfName,
                              const nsIID *aIfIID,
                              PRBool* aFoundOld);
@@ -179,16 +186,15 @@ protected:
    * @aCategoryManager Instance of the category manager service.
    * @aCategory        Category where the entry comes from.
    * @aEntry           The entry that should be added.
    */
   nsresult AddCategoryEntryToHash(nsICategoryManager* aCategoryManager,
                                   const char* aCategory,
                                   nsISupports* aEntry);
 
-  // Inline PLDHashTable, init with PL_DHashTableInit() and delete
-  // with PL_DHashTableFinish().
   PLDHashTable mGlobalNames;
+  PLDHashTable mNavigatorNames;
 
   PRPackedBool mIsInitialized;
 };
 
 #endif /* nsScriptNameSpaceManager_h__ */
--- a/dom/locales/en-US/chrome/layout/MediaDocument.properties
+++ b/dom/locales/en-US/chrome/layout/MediaDocument.properties
@@ -38,19 +38,19 @@
 # ***** END LICENSE BLOCK *****
 
 #LOCALIZATION NOTE (ImageTitleWithDimensionsAndFile): first %S is filename, second %S is type, third %S is width and fourth %S is height
 #LOCALIZATION NOTE (ImageTitleWithoutDimensions): first %S is filename, second %S is type
 #LOCALIZATION NOTE (ImageTitleWithDimensions): first %S is type, second %S is width and third %S is height
 #LOCALIZATION NOTE (ImageTitleWithNeitherDimensionsNorFile): first %S is type
 #LOCALIZATION NOTE (MediaTitleWithFile): first %S is filename, second %S is type
 #LOCALIZATION NOTE (MediaTitleWithNoInfo): first %S is type
-ImageTitleWithDimensionsAndFile=%S (%S Image, %Sx%S pixels)
+ImageTitleWithDimensionsAndFile=%S (%S Image, %S\u00A0\u00D7\u00A0%S pixels)
 ImageTitleWithoutDimensions=%S (%S Image)
-ImageTitleWithDimensions=(%S Image, %Sx%S pixels)
+ImageTitleWithDimensions=(%S Image, %S\u00A0\u00D7\u00A0%S pixels)
 ImageTitleWithNeitherDimensionsNorFile=(%S Image)
 MediaTitleWithFile=%S (%S Object)
 MediaTitleWithNoInfo=(%S Object)
 
 InvalidImage=The image \u201c%S\u201d cannot be displayed because it contains errors.
 ScaledImage=Scaled (%S%%)
 
 TitleWithStatus=%S - %S
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -980,17 +980,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
     mWsInfo.colormap = aWindow.colormap;
     if (!XVisualIDToInfo(mWsInfo.display, aWindow.visualID,
                          &mWsInfo.visual, &mWsInfo.depth))
         return false;
 
 #ifdef MOZ_WIDGET_GTK2
     if (gtk_check_version(2,18,7) != NULL) { // older
         if (aWindow.type == NPWindowTypeWindow) {
-            GdkWindow* socket_window = gdk_window_lookup(aWindow.window);
+            GdkWindow* socket_window = gdk_window_lookup(static_cast<GdkNativeWindow>(aWindow.window));
             if (socket_window) {
                 // A GdkWindow for the socket already exists.  Need to
                 // workaround https://bugzilla.gnome.org/show_bug.cgi?id=607061
                 // See wrap_gtk_plug_embedded in PluginModuleChild.cpp.
                 g_object_set_data(G_OBJECT(socket_window),
                                   "moz-existed-before-set-window",
                                   GUINT_TO_POINTER(1));
             }
@@ -1034,17 +1034,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
               aWindow.height == 0) {
             // Skip SetWindow call for hidden QuickTime plugins
             return true;
           }
 
           if (!CreatePluginWindow())
               return false;
 
-          ReparentPluginWindow((HWND)aWindow.window);
+          ReparentPluginWindow(reinterpret_cast<HWND>(aWindow.window));
           SizePluginWindow(aWindow.width, aWindow.height);
 
           mWindow.window = (void*)mPluginWindowHWND;
           mWindow.x = aWindow.x;
           mWindow.y = aWindow.y;
           mWindow.width = aWindow.width;
           mWindow.height = aWindow.height;
           mWindow.type = aWindow.type;
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -599,17 +599,17 @@ PluginInstanceParent::RecvShow(const NPR
     return true;
 }
 
 nsresult
 PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow)
 {
     NPRemoteWindow window;
     mWindowType = aWindow->type;
-    window.window = reinterpret_cast<uintptr_t>(aWindow->window);
+    window.window = reinterpret_cast<uint64_t>(aWindow->window);
     window.x = aWindow->x;
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
     window.clipRect = aWindow->clipRect;
     window.type = aWindow->type;
     if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
                             window))
@@ -906,25 +906,25 @@ PluginInstanceParent::NPP_SetWindow(cons
         // SharedSurfaceSetWindow will take care of NPRemoteWindow.
         if (!SharedSurfaceSetWindow(aWindow, window)) {
           return NPERR_OUT_OF_MEMORY_ERROR;
         }
     }
     else {
         SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window));
 
-        window.window = reinterpret_cast<uintptr_t>(aWindow->window);
+        window.window = reinterpret_cast<uint64_t>(aWindow->window);
         window.x = aWindow->x;
         window.y = aWindow->y;
         window.width = aWindow->width;
         window.height = aWindow->height;
         window.type = aWindow->type;
     }
 #else
-    window.window = reinterpret_cast<unsigned long>(aWindow->window);
+    window.window = reinterpret_cast<uint64_t>(aWindow->window);
     window.x = aWindow->x;
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
     window.clipRect = aWindow->clipRect; // MacOS specific
     window.type = aWindow->type;
 #endif
 
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -105,17 +105,17 @@ struct IPCByteRange
 };  
 
 typedef std::vector<IPCByteRange> IPCByteRanges;
 
 typedef nsCString Buffer;
 
 struct NPRemoteWindow
 {
-  unsigned long window;
+  uint64_t window;
   int32_t x;
   int32_t y;
   uint32_t width;
   uint32_t height;
   NPRect clipRect;
   NPWindowType type;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
   VisualID visualID;
@@ -358,17 +358,17 @@ struct ParamTraits<NPWindowType>
 
 template <>
 struct ParamTraits<mozilla::plugins::NPRemoteWindow>
 {
   typedef mozilla::plugins::NPRemoteWindow paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
-    aMsg->WriteULong(aParam.window);
+    aMsg->WriteUInt64(aParam.window);
     WriteParam(aMsg, aParam.x);
     WriteParam(aMsg, aParam.y);
     WriteParam(aMsg, aParam.width);
     WriteParam(aMsg, aParam.height);
     WriteParam(aMsg, aParam.clipRect);
     WriteParam(aMsg, aParam.type);
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     aMsg->WriteULong(aParam.visualID);
@@ -376,22 +376,22 @@ struct ParamTraits<mozilla::plugins::NPR
 #endif
 #if defined(XP_WIN)
     WriteParam(aMsg, aParam.surfaceHandle);
 #endif
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
-    unsigned long window;
+    uint64_t window;
     int32_t x, y;
     uint32_t width, height;
     NPRect clipRect;
     NPWindowType type;
-    if (!(aMsg->ReadULong(aIter, &window) &&
+    if (!(aMsg->ReadUInt64(aIter, &window) &&
           ReadParam(aMsg, aIter, &x) &&
           ReadParam(aMsg, aIter, &y) &&
           ReadParam(aMsg, aIter, &width) &&
           ReadParam(aMsg, aIter, &height) &&
           ReadParam(aMsg, aIter, &clipRect) &&
           ReadParam(aMsg, aIter, &type)))
       return false;
 
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -132,19 +132,21 @@ include $(topsrcdir)/config/rules.mk
 		test_bug593174.html \
 		file_bug593174_1.html \
 		file_bug593174_2.html \
 		test_bug612267.html \
 		test_bug617296.html \
 		test_bug620947.html \
 		test_bug622361.html \
 		test_bug633133.html \
+		test_bug641552.html \
 		test_bug642026.html \
 		test_bug648465.html \
 		test_bug654137.html \
+		test_bug684544.html \
 		test_window_bar.html \
 		file_window_bar.html \
 		test_resize_move_windows.html \
 		test_devicemotion_multiple_listeners.html \
 		devicemotion_outer.html \
 		devicemotion_inner.html \
 		$(NULL)
 
--- a/dom/tests/mochitest/bugs/test_bug597809.html
+++ b/dom/tests/mochitest/bugs/test_bug597809.html
@@ -13,24 +13,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 597809 **/
 
 SimpleTest.waitForExplicitFinish();
 
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-var cm = Components.classes["@mozilla.org/categorymanager;1"]
-                   .getService(Components.interfaces.nsICategoryManager);
-cm.addCategoryEntry("JavaScript-global-property", "testSNSM", "@mozilla.org/embedcomp/prompt-service;1",
+SpecialPowers.addCategoryEntry("JavaScript-global-property", "testSNSM", "@mozilla.org/embedcomp/prompt-service;1",
                     false, true);
 
 SimpleTest.executeSoon(function () {
-  ok(window.testSNSM, "testSNSM should returns an object");
+  ok(window.testSNSM, "testSNSM should return an object");
   SimpleTest.finish();
 });
 
 
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug641552.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=641552
+-->
+<head>
+  <title>Test for Bug 641552</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641552">Mozilla Bug 641552</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 641552 **/
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.addCategoryEntry("JavaScript-global-property", "randomname", "@mozilla.org/embedcomp/prompt-service;1",
+                    false, true);
+
+SpecialPowers.addCategoryEntry("JavaScript-navigator-property", "randomname1", "@mozilla.org/embedcomp/prompt-service;1",
+                    false, true);
+
+SpecialPowers.addCategoryEntry("JavaScript-navigator-property", "randomname2", "@mozilla.org/embedcomp/prompt-service;1",
+                    false, true);
+
+SimpleTest.executeSoon(function () {
+  ok(window.randomname, "window.randomname should return an object");
+  is(typeof(window.navigator.randomname1), 'object', "navigator.randomname1 should return an object");
+  is(typeof(window.navigator.randomname2), 'object', "navigator.randomname1 should return an object");
+  SimpleTest.finish();
+});
+
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug684544.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=
+-->
+<head>
+  <title>Test for Bug </title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug  **/
+
+var f = document.createElement("iframe");
+document.body.appendChild(f);
+var win = f.contentWindow;
+
+// Set location once to make sure it's resolved
+win.location = "data:text/html,1";
+
+// Now try to make the location object go away.
+f.parentNode.removeChild(f);
+
+// Check that location is now null.  If it's not, the test needs changing
+// (e.g. to use window.close() so that it's null).
+is("location" in win, true, "Should still have a location property");
+todo_is(win.location, null, "There should be no location object now");
+
+// Just set the location.  This should not crash.
+win.location = "data:text/html,2";
+
+// And check that we didn't override the slot in the process.
+is(typeof(win.location), "object", "Location should not have become a string");
+is(win.location, null,
+   "There should be no location object for real after the set");
+
+</script>
+</pre>
+</body>
+</html>
--- a/editor/composer/src/crashtests/crashtests.list
+++ b/editor/composer/src/crashtests/crashtests.list
@@ -1,6 +1,6 @@
-load 351236-1.html
+asserts-if(Android,2) load 351236-1.html
 load 407062-1.html
 load 419563-1.xhtml
 skip-if(winWidget) load 428844-1.html # bug 471185
 load 461049-1.html
 asserts(0-1) asserts-if(winWidget,0-2) load removing-editable-xslt.html # bug 500847
--- a/editor/composer/src/nsEditorSpellCheck.cpp
+++ b/editor/composer/src/nsEditorSpellCheck.cpp
@@ -49,22 +49,18 @@
 #include "nsISpellChecker.h"
 #include "nsISelection.h"
 #include "nsIDOMRange.h"
 #include "nsIEditor.h"
 #include "nsIHTMLEditor.h"
 
 #include "nsIComponentManager.h"
 #include "nsIContentPrefService.h"
-#include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIChromeRegistry.h"
-#include "nsIPrivateBrowsingService.h"
-#include "nsIContentURIGrouper.h"
-#include "nsNetCID.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsITextServicesFilter.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
@@ -82,26 +78,21 @@ class UpdateDictionnaryHolder {
       if (mSpellCheck) {
         mSpellCheck->EndUpdateDictionary();
       }
     }
 };
 
 #define CPS_PREF_NAME NS_LITERAL_STRING("spellcheck.lang")
 
-class LastDictionary : public nsIObserver, public nsSupportsWeakReference {
+class LastDictionary {
 public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
-
-  LastDictionary();
-
   /**
    * Store current dictionary for editor document url. Use content pref
-   * service. Or, if in private mode, store this information in memory.
+   * service.
    */
   NS_IMETHOD StoreCurrentDictionary(nsIEditor* aEditor, const nsAString& aDictionary);
 
   /**
    * Get last stored current dictionary for editor document url.
    */
   NS_IMETHOD FetchLastDictionary(nsIEditor* aEditor, nsAString& aDictionary);
 
@@ -110,36 +101,18 @@ public:
    */
   NS_IMETHOD ClearCurrentDictionary(nsIEditor* aEditor);
 
   /**
    * get uri of editor's document.
    *
    */
   static nsresult GetDocumentURI(nsIEditor* aEditor, nsIURI * *aURI);
-
-  PRBool mInPrivateBrowsing;
-
-  // During private browsing, dictionaries are stored in memory
-  nsDataHashtable<nsStringHashKey, nsString> mMemoryStorage;
 };
 
-NS_IMPL_ISUPPORTS2(LastDictionary, nsIObserver, nsISupportsWeakReference)
-
-LastDictionary::LastDictionary():
-  mInPrivateBrowsing(PR_FALSE)
-{  
-  nsCOMPtr<nsIPrivateBrowsingService> pbService =
-    do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
-  if (pbService) {
-    pbService->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
-    mMemoryStorage.Init();
-  }
-}
-
 // static
 nsresult
 LastDictionary::GetDocumentURI(nsIEditor* aEditor, nsIURI * *aURI)
 {
   NS_ENSURE_ARG_POINTER(aEditor);
   NS_ENSURE_ARG_POINTER(aURI);
 
   nsCOMPtr<nsIDOMDocument> domDoc;
@@ -163,31 +136,16 @@ LastDictionary::FetchLastDictionary(nsIE
   NS_ENSURE_ARG_POINTER(aEditor);
 
   nsresult rv;
 
   nsCOMPtr<nsIURI> docUri;
   rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (mInPrivateBrowsing) {
-    nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
-      do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
-    NS_ENSURE_TRUE(hostnameGrouperService, NS_ERROR_NOT_AVAILABLE);
-    nsString group;
-    hostnameGrouperService->Group(docUri, group);
-    nsAutoString lastDict;
-    if (mMemoryStorage.Get(group, &lastDict)) {
-      aDictionary.Assign(lastDict);
-    } else {
-      aDictionary.Truncate();
-    }
-    return NS_OK;
-  }
-
   nsCOMPtr<nsIContentPrefService> contentPrefService =
     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(contentPrefService, NS_ERROR_NOT_AVAILABLE);
 
   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
   uri->SetAsISupports(docUri);
 
@@ -209,30 +167,16 @@ LastDictionary::StoreCurrentDictionary(n
   NS_ENSURE_ARG_POINTER(aEditor);
 
   nsresult rv;
 
   nsCOMPtr<nsIURI> docUri;
   rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
- if (mInPrivateBrowsing) {
-    nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
-      do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
-    NS_ENSURE_TRUE(hostnameGrouperService, NS_ERROR_NOT_AVAILABLE);
-    nsString group;
-    hostnameGrouperService->Group(docUri, group);
-
-    if (mMemoryStorage.Put(group, nsString(aDictionary))) {
-      return NS_OK;
-    } else {
-      return NS_ERROR_FAILURE;
-    }
-  }
-
   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
   uri->SetAsISupports(docUri);
 
   nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(prefValue, NS_ERROR_OUT_OF_MEMORY);
   prefValue->SetAsAString(aDictionary);
 
@@ -249,55 +193,27 @@ LastDictionary::ClearCurrentDictionary(n
   NS_ENSURE_ARG_POINTER(aEditor);
 
   nsresult rv;
 
   nsCOMPtr<nsIURI> docUri;
   rv = GetDocumentURI(aEditor, getter_AddRefs(docUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIContentURIGrouper> hostnameGrouperService =
-      do_GetService(NS_HOSTNAME_GROUPER_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(hostnameGrouperService, NS_ERROR_NOT_AVAILABLE);
-
-  nsString group;
-  hostnameGrouperService->Group(docUri, group);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (mMemoryStorage.IsInitialized()) {
-    mMemoryStorage.Remove(group);
-  }
-
   nsCOMPtr<nsIWritableVariant> uri = do_CreateInstance(NS_VARIANT_CONTRACTID);
   NS_ENSURE_TRUE(uri, NS_ERROR_OUT_OF_MEMORY);
   uri->SetAsISupports(docUri);
 
   nsCOMPtr<nsIContentPrefService> contentPrefService =
     do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(contentPrefService, NS_ERROR_NOT_INITIALIZED);
 
   return contentPrefService->RemovePref(uri, CPS_PREF_NAME);
 }
 
-NS_IMETHODIMP
-LastDictionary::Observe(nsISupports *aSubject, char const *aTopic, PRUnichar const *aData)
-{
-  if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
-    if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(aData)) {
-      mInPrivateBrowsing = PR_TRUE;
-    } else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
-      mInPrivateBrowsing = PR_FALSE;
-      if (mMemoryStorage.IsInitialized()) {
-        mMemoryStorage.Clear();
-      }
-    }
-  } 
-  return NS_OK;
-}
-
 LastDictionary* nsEditorSpellCheck::gDictionaryStore = nsnull;
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEditorSpellCheck)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEditorSpellCheck)
 
 NS_INTERFACE_MAP_BEGIN(nsEditorSpellCheck)
   NS_INTERFACE_MAP_ENTRY(nsIEditorSpellCheck)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditorSpellCheck)
@@ -353,24 +269,16 @@ nsEditorSpellCheck::InitSpellChecker(nsI
 {
   NS_ENSURE_TRUE(aEditor, NS_ERROR_NULL_POINTER);
   mEditor = aEditor;
 
   nsresult rv;
 
   if (!gDictionaryStore) {
     gDictionaryStore = new LastDictionary();
-    if (gDictionaryStore) {
-      NS_ADDREF(gDictionaryStore);
-      nsCOMPtr<nsIObserverService> observerService =
-        mozilla::services::GetObserverService();
-      if (observerService) {
-        observerService->AddObserver(gDictionaryStore, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_TRUE);
-      }
-    }
   }
 
 
   // We can spell check with any editor type
   nsCOMPtr<nsITextServicesDocument>tsDoc =
      do_CreateInstance("@mozilla.org/textservices/textservicesdocument;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -834,10 +742,10 @@ nsEditorSpellCheck::UpdateCurrentDiction
 
   DeleteSuggestedWordList();
 
   return NS_OK;
 }
 
 void 
 nsEditorSpellCheck::ShutDown() {
-  NS_IF_RELEASE(gDictionaryStore);
+  delete gDictionaryStore;
 }
--- a/editor/composer/src/nsEditorSpellCheck.h
+++ b/editor/composer/src/nsEditorSpellCheck.h
@@ -38,17 +38,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsEditorSpellCheck_h___
 #define nsEditorSpellCheck_h___
 
 
 #include "nsIEditorSpellCheck.h"
 #include "nsISpellChecker.h"
-#include "nsIObserver.h"
 #include "nsIURI.h"
 #include "nsWeakReference.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDataHashtable.h"
 
 #define NS_EDITORSPELLCHECK_CID                     \
 { /* {75656ad9-bd13-4c5d-939a-ec6351eea0cc} */        \
--- a/editor/libeditor/base/crashtests/crashtests.list
+++ b/editor/libeditor/base/crashtests/crashtests.list
@@ -1,10 +1,10 @@
 load 336104.html
 load 382527-1.html
 load 402172-1.html
 load 407079-1.html
 load 407256-1.html
 load 430624-1.html
 load 459613.html
 load 475132-1.xhtml
-load 633709.xhtml
-asserts(6) load 636074-1.html # Bug 439258, charged to the wrong test due to bug 635550
+asserts-if(Android,6) load 633709.xhtml
+asserts-if(!Android,6) load 636074-1.html # Bug 439258, charged to the wrong test due to bug 635550
--- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
@@ -363,39 +363,41 @@ nsHTMLEditor::CheckSelectionStateForAnon
   if (mIsInlineTableEditingEnabled && mInlineEditedCell &&
       mInlineEditedCell != cellElement) {
     res = HideInlineTableEditingUI();
     NS_ENSURE_SUCCESS(res, res);
     NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUI failed");
   }
 
   // now, let's display all contextual UI for good
+  nsIContent* hostContent = GetActiveEditingHost();
+  nsCOMPtr<nsIDOMNode> hostNode = do_QueryInterface(hostContent);
 
   if (mIsObjectResizingEnabled && focusElement &&
-      IsModifiableNode(focusElement)) {
+      IsModifiableNode(focusElement) && focusElement != hostNode) {
     if (nsEditProperty::img == focusTagAtom)
       mResizedObjectIsAnImage = PR_TRUE;
     if (mResizedObject)
       res = RefreshResizers();
     else
       res = ShowResizers(focusElement);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   if (mIsAbsolutelyPositioningEnabled && absPosElement &&
-      IsModifiableNode(absPosElement)) {
+      IsModifiableNode(absPosElement) && absPosElement != hostNode) {
     if (mAbsolutelyPositionedObject)
       res = RefreshGrabber();
     else
       res = ShowGrabberOnElement(absPosElement);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   if (mIsInlineTableEditingEnabled && cellElement &&
-      IsModifiableNode(cellElement)) {
+      IsModifiableNode(cellElement) && cellElement != hostNode) {
     if (mInlineEditedCell)
       res = RefreshInlineTableEditingUI();
     else
       res = ShowInlineTableEditingUI(cellElement);
   }
 
   return res;
 }
--- a/editor/libeditor/text/nsInternetCiter.cpp
+++ b/editor/libeditor/text/nsInternetCiter.cpp
@@ -78,17 +78,17 @@ nsInternetCiter::GetCiteString(const nsA
 
   // Loop over the string:
   while (beginIter != endIter)
   {
     if (uch == nl)
     {
       aOutString.Append(gt);
       // No space between >: this is ">>> " style quoting, for
-      // compatability with RFC 2646 and format=flowed.
+      // compatibility with RFC 2646 and format=flowed.
       if (*beginIter != gt)
         aOutString.Append(space);
     }
 
     uch = *beginIter;
     ++beginIter;
 
     aOutString += uch;
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -431,17 +431,16 @@ static const char *sExtensionNames[] = {
     "GL_IMG_read_format",
     "GL_EXT_read_format_bgra",
     "GL_APPLE_client_storage",
     "GL_ARB_texture_non_power_of_two",
     "GL_ARB_pixel_buffer_object",
     "GL_ARB_ES2_compatibility",
     "GL_OES_texture_float",
     "GL_ARB_texture_float",
-    "GL_EXT_unpack_subimage",
     NULL
 };
 
 void
 GLContext::InitExtensions()
 {
     MakeCurrent();
     const GLubyte *extensions = fGetString(LOCAL_GL_EXTENSIONS);
@@ -1835,27 +1834,19 @@ GLContext::TexImage2D(GLenum target, GLi
                       GLint pixelsize, GLint border, GLenum format, 
                       GLenum type, const GLvoid *pixels)
 {
     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 
                  NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
                         GetAddressAlignment((ptrdiff_t)stride)));
 
 #ifndef USE_GLES2
-    bool useUnpackRowLength = true;
+    fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, stride/pixelsize);
 #else
-    // A Khronos extension, GL_EXT_unpack_subimage, that restores support
-    // for GL_UNPACK_ROW_LENGTH, GL_UNPACK_SKIP_ROWS and GL_UNPACK_SKIP_PIXELS
-    // exists on Tegra 2 (and possibly other chipsets)
-    bool useUnpackRowLength = IsExtensionSupported(EXT_unpack_subimage);
-#endif
-
-    if (useUnpackRowLength)
-        fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, stride/pixelsize);
-    else if (stride != width * pixelsize) {
+    if (stride != width * pixelsize) {
         // Not using the whole row of texture data and GLES doesn't 
         // support GL_UNPACK_ROW_LENGTH. We need to upload each row
         // separately.
         fTexImage2D(target,
                     border,
                     internalformat,
                     width,
                     height,
@@ -1877,29 +1868,31 @@ GLContext::TexImage2D(GLenum target, GLi
                            row);
 
             row += stride;
         }
 
         fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
         return;
     }
+#endif
 
     fTexImage2D(target,
                 level,
                 internalformat,
                 width,
                 height,
                 border,
                 format,
                 type,
                 pixels);
 
-    if (useUnpackRowLength)
-        fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
+#ifndef USE_GLES2
+    fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
+#endif
     fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
 }
 
 void
 GLContext::TexSubImage2D(GLenum target, GLint level, 
                          GLint xoffset, GLint yoffset, 
                          GLsizei width, GLsizei height, GLsizei stride,
                          GLint pixelsize, GLenum format, 
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -975,17 +975,16 @@ public:
         IMG_read_format,
         EXT_read_format_bgra,
         APPLE_client_storage,
         ARB_texture_non_power_of_two,
         ARB_pixel_buffer_object,
         ARB_ES2_compatibility,
         OES_texture_float,
         ARB_texture_float,
-        EXT_unpack_subimage,
         Extensions_Max
     };
 
     PRBool IsExtensionSupported(GLExtensions aKnownExtension) {
         return mAvailableExtensions[aKnownExtension];
     }
 
     // for unknown extensions
--- a/intl/lwbrk/src/nsJISx4501LineBreaker.cpp
+++ b/intl/lwbrk/src/nsJISx4501LineBreaker.cpp
@@ -455,17 +455,17 @@ GetClass(PRUnichar u)
      c = GETCLASSFROMTABLE(gLBClass20, l);
    } else if (0x2100 == h) {
      c = GETCLASSFROMTABLE(gLBClass21, l);
    } else if (0x3000 == h) {
      c = GETCLASSFROMTABLE(gLBClass30, l);
    } else if (((0x3200 <= u) && (u <= 0xA4CF)) || // CJK and Yi
               ((0xAC00 <= h) && (h <= 0xD7FF)) || // Hangul
               ((0xf900 <= h) && (h <= 0xfaff))) {
-     c = CLASS_BREAKABLE; // CJK character, Han, and Han Compatability
+     c = CLASS_BREAKABLE; // CJK character, Han, and Han Compatibility
    } else if (0xff00 == h) {
      if (l < 0x0060) { // Fullwidth ASCII variant
        c = GETCLASSFROMTABLE(gLBClass00, (l+0x20));
      } else if (l < 0x00a0) {
        switch (l) {
          case 0x61: c = GetClass(0x3002); break;
          case 0x62: c = GetClass(0x300c); break;
          case 0x63: c = GetClass(0x300d); break;
--- a/intl/uconv/src/nsUnicodeToUTF8.cpp
+++ b/intl/uconv/src/nsUnicodeToUTF8.cpp
@@ -48,17 +48,17 @@ NS_IMPL_ISUPPORTS1(nsUnicodeToUTF8, nsIU
 
 NS_IMETHODIMP nsUnicodeToUTF8::GetMaxLength(const PRUnichar * aSrc, 
                                               PRInt32 aSrcLength,
                                               PRInt32 * aDestLength)
 {
   // aSrc is interpreted as UTF16, 3 is normally enough.
   // But when previous buffer only contains part of the surrogate pair, we 
   // need to complete it here. If the first word in following buffer is not
-  // in valid surrogate rang, we need to convert the remaining of last buffer 
+  // in valid surrogate range, we need to convert the remaining of last buffer
   // to 3 bytes.
   *aDestLength = 3*aSrcLength + 3;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsUnicodeToUTF8::Convert(const PRUnichar * aSrc, 
                                 PRInt32 * aSrcLength, 
                                 char * aDest, 
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -150,30 +150,30 @@ void GetPathToBinary(FilePath& exePath)
     NS_ASSERTION(directoryService, "Expected XPCOM to be available");
     if (directoryService) {
       nsCOMPtr<nsIFile> greDir;
       nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir));
       if (NS_SUCCEEDED(rv)) {
         nsCString path;
         greDir->GetNativePath(path);
         exePath = FilePath(path.get());
+#ifdef OS_MACOSX
+        // We need to use an App Bundle on OS X so that we can hide
+        // the dock icon. See Bug 557225.
+        exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_BUNDLE);
+#endif
       }
     }
   }
+
   if (exePath.empty()) {
     exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
     exePath = exePath.DirName();
   }
 
-#ifdef OS_MACOSX
-  // We need to use an App Bundle on OS X so that we can hide
-  // the dock icon. See Bug 557225
-  exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_BUNDLE);
-#endif
-
   exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
 #endif
 }
 
 #ifdef XP_MACOSX
 class AutoCFTypeObject {
 public:
   AutoCFTypeObject(CFTypeRef object)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug684796.js
@@ -0,0 +1,2 @@
+if (typeof mjitdatastats == "function")
+    mjitdatastats();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/closures/bug684178.js
@@ -0,0 +1,9 @@
+var obj = {};
+(function() {
+    if (obj) {
+        function f() { obj.x = 1; }
+        obj.m = function() { f(); };
+    }
+})();
+obj.m();
+assertEq(obj.x, 1);
--- a/js/src/jit-test/tests/sunspider/check-3d-raytrace.js
+++ b/js/src/jit-test/tests/sunspider/check-3d-raytrace.js
@@ -307,17 +307,16 @@ Camera.prototype.render = function(scene
     var row = 0;
     renderRows(cam, scene, pixels, width, height, 0, height);
 }
 
 
 
 function raytraceScene()
 {
-    var startDate = new Date().getTime();
     var numTriangles = 2 * 6;
     var triangles = new Array();//numTriangles);
     var tfl = createVector(-10,  10, -10);
     var tfr = createVector( 10,  10, -10);
     var tbl = createVector(-10,  10,  10);
     var tbr = createVector( 10,  10,  10);
     var bfl = createVector(-10, -10, -10);
     var bfr = createVector( 10, -10, -10);
--- a/js/src/jit-test/tests/sunspider/check-crypto-aes.js
+++ b/js/src/jit-test/tests/sunspider/check-crypto-aes.js
@@ -171,17 +171,18 @@ function AESEncryptCtr(plaintext, passwo
   for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
   var key = Cipher(pwBytes, KeyExpansion(pwBytes));
   key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
 
   // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
   // block counter in 2nd 8 bytes
   var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
   var counterBlock = new Array(blockSize);  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
-  var nonce = (new Date()).getTime();  // milliseconds since 1-Jan-1970
+  var nonce = (new Date("2000-01-01")).getTime();  // milliseconds since 1-Jan-1970;
+                                                   // fixed for repeatability
 
   // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
   for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
   for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
 
   // generate key schedule - an expansion of the key into distinct Key Rounds for each round
   var keySchedule = KeyExpansion(key);
 
--- a/js/src/jit-test/tests/sunspider/check-math-cordic.js
+++ b/js/src/jit-test/tests/sunspider/check-math-cordic.js
@@ -79,22 +79,16 @@ function cordicsincos() {
     return CurrAngle;
 }
 
 ///// End CORDIC
 
 function cordic( runs ) {
   var actual;
 
-  var start = new Date();
-
   for ( var i = 0 ; i < runs ; i++ ) {
     actual = cordicsincos();
   }
 
-  var end = new Date();
-
   assertEq(actual, 1834995.3515519998)
-
-  return end.getTime() - start.getTime();
 }
 
 cordic(25000);
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -60,17 +60,17 @@ CPPSRCS = \
   testDebugger.cpp \
   testDeepFreeze.cpp \
   testDefineGetterSetterNonEnumerable.cpp \
   testDefineProperty.cpp \
   testExtendedEq.cpp \
   testExternalStrings.cpp \
   testFuncCallback.cpp \
   testFunctionProperties.cpp \
-  testGCChunkAlloc.cpp \
+  testGCOutOfMemory.cpp \
   testGetPropertyDefault.cpp \
   testIndexToString.cpp \
   testIntString.cpp \
   testIntern.cpp \
   testLookup.cpp \
   testLooselyEqual.cpp \
   testNewObject.cpp \
   testOps.cpp \
rename from js/src/jsapi-tests/testGCChunkAlloc.cpp
rename to js/src/jsapi-tests/testGCOutOfMemory.cpp
--- a/js/src/jsapi-tests/testGCChunkAlloc.cpp
+++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp
@@ -5,127 +5,64 @@
  * http://creativecommons.org/licenses/publicdomain/
  * Contributor: Igor Bukanov
  */
 
 #include "tests.h"
 #include "jsgcchunk.h"
 #include "jscntxt.h"
 
-/* We allow to allocate 2 (system/user) chunks. */
-
-static const int SYSTEM  = 0;
-static const int USER    = 1;
-static const int N_POOLS = 2;
-
-class CustomGCChunkAllocator: public js::GCChunkAllocator {
-  public:
-    CustomGCChunkAllocator() { pool[SYSTEM] = NULL; pool[USER] = NULL; }
-    void *pool[N_POOLS];
-    
-  private:
-
-    virtual void *doAlloc() {
-        if (!pool[SYSTEM] && !pool[USER])
-            return NULL;
-        void *chunk = NULL;
-        if (pool[SYSTEM]) {
-            chunk = pool[SYSTEM];
-            pool[SYSTEM] = NULL;
-        } else {
-            chunk = pool[USER];
-            pool[USER] = NULL;
-        }
-        return chunk;
-    }
-        
-    virtual void doFree(void *chunk) {
-        JS_ASSERT(!pool[SYSTEM] || !pool[USER]);
-        if (!pool[SYSTEM]) {
-            pool[SYSTEM] = chunk;
-        } else {
-            pool[USER] = chunk;
-        }
-    }
-};
-
-static CustomGCChunkAllocator customGCChunkAllocator;
-
 static unsigned errorCount = 0;
 
 static void
 ErrorCounter(JSContext *cx, const char *message, JSErrorReport *report)
 {
     ++errorCount;
 }
 
-BEGIN_TEST(testGCChunkAlloc)
+BEGIN_TEST(testGCOutOfMemory)
 {
     JS_SetErrorReporter(cx, ErrorCounter);
 
     jsvalRoot root(cx);
 
     /*
-     * We loop until out-of-memory happens during the chunk allocation. But
-     * we have to disable the jit since it cannot tolerate OOM during the
-     * chunk allocation.
+     * We loop until we get out-of-memory. We have to disable the jit since it
+     * ignores the runtime allocation limits during execution.
      */
     JS_ToggleOptions(cx, JSOPTION_JIT);
 
     static const char source[] =
         "var max = 0; (function() {"
         "    var array = [];"
         "    for (; ; ++max)"
         "        array.push({});"
+        "    array = []; array.push(0);"
         "})();";
     JSBool ok = JS_EvaluateScript(cx, global, source, strlen(source), "", 1,
                                   root.addr());
 
     /* Check that we get OOM. */
     CHECK(!ok);
     CHECK(!JS_IsExceptionPending(cx));
     CHECK_EQUAL(errorCount, 1);
-    CHECK(!customGCChunkAllocator.pool[SYSTEM]);
-    CHECK(!customGCChunkAllocator.pool[USER]);
     JS_GC(cx);
     JS_ToggleOptions(cx, JSOPTION_JIT);
     EVAL("(function() {"
          "    var array = [];"
-         "    for (var i = max >> 1; i != 0;) {"
+         "    for (var i = max >> 2; i != 0;) {"
          "        --i;"
          "        array.push({});"
          "    }"
          "})();", root.addr());
     CHECK_EQUAL(errorCount, 1);
     return true;
 }
 
 virtual JSRuntime * createRuntime() {
-    /*
-     * To test failure of chunk allocation allow to use GC twice the memory
-     * the single chunk contains.
-     */
-    JSRuntime *rt = JS_NewRuntime(2 * js::GC_CHUNK_SIZE);
-    if (!rt)
-        return NULL;
-
-    customGCChunkAllocator.pool[SYSTEM] = js::AllocGCChunk();
-    customGCChunkAllocator.pool[USER] = js::AllocGCChunk();
-    JS_ASSERT(customGCChunkAllocator.pool[SYSTEM]);
-    JS_ASSERT(customGCChunkAllocator.pool[USER]);
-
-    rt->setCustomGCChunkAllocator(&customGCChunkAllocator);
-    return rt;
+    return JS_NewRuntime(256 * 1024);
 }
 
 virtual void destroyRuntime() {
     JS_DestroyRuntime(rt);
-
-    /* We should get the initial chunk back at this point. */
-    JS_ASSERT(customGCChunkAllocator.pool[SYSTEM]);
-    JS_ASSERT(customGCChunkAllocator.pool[USER]);
-    js::FreeGCChunk(customGCChunkAllocator.pool[SYSTEM]);
-    js::FreeGCChunk(customGCChunkAllocator.pool[USER]);
-    customGCChunkAllocator.pool[SYSTEM] = NULL;
-    customGCChunkAllocator.pool[USER] = NULL;
 }
 
-END_TEST(testGCChunkAlloc)
+END_TEST(testGCOutOfMemory)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -633,18 +633,17 @@ JS_IsBuiltinFunctionConstructor(JSFuncti
 /*
  * Has a new runtime ever been created?  This flag is used to detect unsafe
  * changes to js_CStringsAreUTF8 after a runtime has been created, and to
  * control things that should happen only once across all runtimes.
  */
 static JSBool js_NewRuntimeWasCalled = JS_FALSE;
 
 JSRuntime::JSRuntime()
-  : gcChunkAllocator(&defaultGCChunkAllocator),
-    trustedPrincipals_(NULL)
+  : trustedPrincipals_(NULL)
 {
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
     JS_INIT_CLIST(&contextList);
     JS_INIT_CLIST(&debuggerList);
 }
 
 bool
 JSRuntime::init(uint32 maxbytes)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1990,17 +1990,17 @@ struct JSClass {
     JSCheckAccessOp     checkAccess;
     JSNative            call;
     JSNative            construct;
     JSXDRObjectOp       xdrObject;
     JSHasInstanceOp     hasInstance;
     JSTraceOp           trace;
 
     JSClassInternal     reserved1;
-    void                *reserved[19];
+    void                *reserved[26];
 };
 
 #define JSCLASS_HAS_PRIVATE             (1<<0)  /* objects have private slot */
 #define JSCLASS_NEW_ENUMERATE           (1<<1)  /* has JSNewEnumerateOp hook */
 #define JSCLASS_NEW_RESOLVE             (1<<2)  /* has JSNewResolveOp hook */
 #define JSCLASS_PRIVATE_IS_NSISUPPORTS  (1<<3)  /* private is (nsISupports *) */
 #define JSCLASS_CONCURRENT_FINALIZER    (1<<4)  /* finalize is called on background thread */
 #define JSCLASS_NEW_RESOLVE_GETS_START  (1<<5)  /* JSNewResolveOp gets starting
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -718,16 +718,26 @@ array_lookupProperty(JSContext *cx, JSOb
     if (!proto) {
         *objp = NULL;
         *propp = NULL;
         return JS_TRUE;
     }
     return proto->lookupProperty(cx, id, objp, propp);
 }
 
+static JSBool
+array_lookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
+                    JSProperty **propp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return array_lookupProperty(cx, obj, id, objp, propp);
+}
+
 JSBool
 js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32 i;
     if (!js_IdIsIndex(id, &i)) {
         JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
@@ -785,16 +795,25 @@ array_getProperty(JSContext *cx, JSObjec
     /* Type information for dense array elements must be correct. */
     JS_ASSERT_IF(!obj->hasSingletonType(),
                  js::types::TypeHasProperty(cx, obj->type(), JSID_VOID, *vp));
 
     return JS_TRUE;
 }
 
 static JSBool
+array_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return array_getProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 slowarray_addProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     jsuint index, length;
 
     if (!js_IdIsIndex(id, &index))
         return JS_TRUE;
     length = obj->getArrayLength();
     if (index >= length)
@@ -839,16 +858,25 @@ array_setProperty(JSContext *cx, JSObjec
         return true;
     } while (false);
 
     if (!obj->makeDenseArraySlow(cx))
         return false;
     return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
 }
 
+static JSBool
+array_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return array_setProperty(cx, obj, id, vp, strict);
+}
+
 JSBool
 js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
 {
     /*
      * Walk up the prototype chain and see if this indexed element already
      * exists. If we hit the end of the prototype chain, it's safe to set the
      * element on the original object.
      */
@@ -863,16 +891,17 @@ js_PrototypeHasIndexedProperties(JSConte
         if (obj->isIndexed())
             return JS_TRUE;
     }
     return JS_FALSE;
 }
 
 namespace js {
 
+/* non-static for direct definition of array elements within the engine */
 JSBool
 array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                      PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
         return JS_TRUE;
 
     if (!obj->isDenseArray())
@@ -898,36 +927,66 @@ array_defineProperty(JSContext *cx, JSOb
         return true;
     } while (false);
 
     if (!obj->makeDenseArraySlow(cx))
         return false;
     return js_DefineProperty(cx, obj, id, value, getter, setter, attrs);
 }
 
+/* non-static for direct definition of array elements within the engine */
+JSBool
+array_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *value,
+                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return array_defineProperty(cx, obj, id, value, getter, setter, attrs);
+}
+
 } // namespace js
 
 static JSBool
 array_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)
         ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
     return JS_TRUE;
 }
 
 static JSBool
+array_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return array_getAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 array_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                          JSMSG_CANT_SET_ARRAY_ATTRS);
     return JS_FALSE;
 }
 
+static JSBool
+array_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return array_setAttributes(cx, obj, id, attrsp);
+}
+
 namespace js {
 
+/* non-static for direct deletion of array elements within the engine */
 JSBool
 array_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     uint32 i;
 
     if (!obj->isDenseArray())
         return js_DeleteProperty(cx, obj, id, rval, strict);
 
@@ -943,16 +1002,26 @@ array_deleteProperty(JSContext *cx, JSOb
 
     if (!js_SuppressDeletedProperty(cx, obj, id))
         return false;
 
     rval->setBoolean(true);
     return JS_TRUE;
 }
 
+/* non-static for direct deletion of array elements within the engine */
+JSBool
+array_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return array_deleteProperty(cx, obj, id, rval, strict);
+}
+
 } // namespace js
 
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32 initLength = obj->getDenseArrayInitializedLength();
@@ -992,22 +1061,29 @@ Class js::ArrayClass = {
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* xdrObject   */
     NULL,           /* hasInstance */
     array_trace,    /* trace       */
     JS_NULL_CLASS_EXT,
     {
         array_lookupProperty,
+        array_lookupElement,
         array_defineProperty,
+        array_defineElement,
         array_getProperty,
+        array_getElement,
         array_setProperty,
+        array_setElement,
         array_getAttributes,
+        array_getElementAttributes,
         array_setAttributes,
+        array_setElementAttributes,
         array_deleteProperty,
+        array_deleteElement,
         NULL,       /* enumerate      */
         array_typeOf,
         array_fix,
         NULL,       /* thisObject     */
         NULL,       /* clear          */
     }
 };
 
@@ -1831,20 +1907,21 @@ js_MergeSort(void *src, size_t nel, size
         memcpy(src, tmp, nel * elsize);
 
     return JS_TRUE;
 }
 
 struct CompareArgs
 {
     JSContext          *context;
-    InvokeSessionGuard session;
-
-    CompareArgs(JSContext *cx)
-      : context(cx)
+    InvokeArgsGuard    args;
+    Value              fval;
+
+    CompareArgs(JSContext *cx, Value fval)
+      : context(cx), fval(fval)
     {}
 };
 
 static JS_REQUIRES_STACK JSBool
 sort_compare(void *arg, const void *a, const void *b, int *result)
 {
     const Value *av = (const Value *)a, *bv = (const Value *)b;
     CompareArgs *ca = (CompareArgs *) arg;
@@ -1855,25 +1932,31 @@ sort_compare(void *arg, const void *a, c
      * come here.
      */
     JS_ASSERT(!av->isMagic() && !av->isUndefined());
     JS_ASSERT(!av->isMagic() && !bv->isUndefined());
 
     if (!JS_CHECK_OPERATION_LIMIT(cx))
         return JS_FALSE;
 
-    InvokeSessionGuard &session = ca->session;
-    session[0] = *av;
-    session[1] = *bv;
-
-    if (!session.invoke(cx))
+    InvokeArgsGuard &args = ca->args;
+    if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, 2, &args))
+        return JS_FALSE;
+        
+    args.calleeHasBeenReset();
+    args.calleev() = ca->fval;
+    args.thisv() = UndefinedValue();
+    args[0] = *av;
+    args[1] = *bv;
+
+    if (!Invoke(cx, args))
         return JS_FALSE;
 
     jsdouble cmp;
-    if (!ToNumber(cx, session.rval(), &cmp))
+    if (!ToNumber(cx, args.rval(), &cmp))
         return JS_FALSE;
 
     /* Clamp cmp to -1, 0, 1. */
     *result = 0;
     if (!JSDOUBLE_IS_NaN(cmp) && cmp != 0)
         *result = cmp > 0 ? 1 : -1;
 
     /*
@@ -2100,20 +2183,17 @@ js::array_sort(JSContext *cx, uintN argc
                  * not call JS_CHECK_OPERATION_LIMIT in the loop.
                  */
                 i = 0;
                 do {
                     vec[i] = vec[2 * i + 1];
                 } while (++i != newlen);
             }
         } else {
-            CompareArgs ca(cx);
-            if (!ca.session.start(cx, fval, UndefinedValue(), 2))
-                return false;
-
+            CompareArgs ca(cx, fval);
             if (!js_MergeSort(vec, size_t(newlen), sizeof(Value),
                               comparator_stack_cast(sort_compare),
                               &ca, mergesort_tmp,
                               JS_SORTING_VALUES)) {
                 return false;
             }
         }
 
@@ -2957,52 +3037,55 @@ array_extra(JSContext *cx, ArrayExtraMod
     Value thisv = (argc > 1 && !REDUCE_MODE(mode)) ? argv[1] : UndefinedValue();
 
     /*
      * For all but REDUCE, we call with 3 args (value, index, array). REDUCE
      * requires 4 args (accum, value, index, array).
      */
     argc = 3 + REDUCE_MODE(mode);
 
-    InvokeSessionGuard session;
-    if (!session.start(cx, ObjectValue(*callable), thisv, argc))
-        return JS_FALSE;
-
     MUST_FLOW_THROUGH("out");
     JSBool ok = JS_TRUE;
     JSBool cond;
 
     Value objv = ObjectValue(*obj);
     AutoValueRooter tvr(cx);
+    InvokeArgsGuard args;
     for (jsuint i = start; i != end; i += step) {
         JSBool hole;
         ok = JS_CHECK_OPERATION_LIMIT(cx) &&
              GetElement(cx, obj, i, &hole, tvr.addr());
         if (!ok)
             goto out;
         if (hole)
             continue;
 
+        if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, argc, &args))
+            return false;
+
         /*
          * Push callable and 'this', then args. We must do this for every
          * iteration around the loop since Invoke clobbers its arguments.
          */
+        args.calleeHasBeenReset();
+        args.calleev() = ObjectValue(*callable);
+        args.thisv() = thisv;
         uintN argi = 0;
         if (REDUCE_MODE(mode))
-            session[argi++] = *vp;
-        session[argi++] = tvr.value();
-        session[argi++] = Int32Value(i);
-        session[argi]   = objv;
+            args[argi++] = *vp;
+        args[argi++] = tvr.value();
+        args[argi++] = Int32Value(i);
+        args[argi]   = objv;
 
         /* Do the call. */
-        ok = session.invoke(cx);
+        ok = Invoke(cx, args);
         if (!ok)
             break;
 
-        const Value &rval = session.rval();
+        const Value &rval = args.rval();
 
         if (mode > MAP)
             cond = js_ValueToBoolean(rval);
 #ifdef __GNUC__ /* quell GCC overwarning */
         else
             cond = JS_FALSE;
 #endif
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -644,17 +644,17 @@ ReportError(JSContext *cx, const char *m
         reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
         reportp->flags |= JSREPORT_EXCEPTION;
 
     /*
      * Call the error reporter only if an exception wasn't raised.
      *
      * If an exception was raised, then we call the debugErrorHook
      * (if present) to give it a chance to see the error before it
-     * propagates out of scope.  This is needed for compatability
+     * propagates out of scope.  This is needed for compatibility
      * with the old scheme.
      */
     if (!JS_IsRunning(cx) ||
         !js_ErrorToException(cx, message, reportp, callback, userRef)) {
         js_ReportErrorAgain(cx, message, reportp);
     } else if (cx->debugHooks->debugErrorHook && cx->errorReporter) {
         JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
         /* test local in case debugErrorHook changed on another thread */
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -507,24 +507,16 @@ struct JSRuntime {
   private:
     /*
      * Malloc counter to measure memory pressure for GC scheduling. It runs
      * from gcMaxMallocBytes down to zero.
      */
     volatile ptrdiff_t  gcMallocBytes;
 
   public:
-    js::GCChunkAllocator    *gcChunkAllocator;
-
-    void setCustomGCChunkAllocator(js::GCChunkAllocator *allocator) {
-        JS_ASSERT(allocator);
-        JS_ASSERT(state == JSRTS_DOWN);
-        gcChunkAllocator = allocator;
-    }
-
     /*
      * The trace operation and its data argument to trace embedding-specific
      * GC roots.
      */
     JSTraceDataOp       gcExtraRootsTraceOp;
     void                *gcExtraRootsData;
 
     /* Well-known numbers held for use by this runtime's contexts. */
@@ -1095,17 +1087,17 @@ struct JSContext
             clearVersionOverride();
         }
     }
 
     /*
      * Return:
      * - The override version, if there is an override version.
      * - The newest scripted frame's version, if there is such a frame.
-     * - The default verion.
+     * - The default version.
      *
      * Note: if this ever shows up in a profile, just add caching!
      */
     JSVersion findVersion() const {
         if (hasVersionOverride)
             return versionOverride;
 
         if (stack.hasfp()) {
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -591,22 +591,24 @@ JSCompartment::sweep(JSContext *cx, uint
 #endif
 
     if (activeAnalysis) {
         /*
          * Analysis information is in use, so don't clear the analysis pool.
          * jitcode still needs to be released, if this is a shape-regenerating
          * GC then shape numbers baked into the code may change.
          */
+#ifdef JS_METHODJIT
         if (types.inferenceEnabled) {
             for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
                 JSScript *script = i.get<JSScript>();
                 mjit::ReleaseScriptCode(cx, script);
             }
         }
+#endif
     } else {
         /*
          * Clear the analysis pool, but don't release its data yet. While
          * sweeping types any live data will be allocated into the pool.
          */
         JSArenaPool oldPool;
         MoveArenaPool(&pool, &oldPool);
 
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -280,19 +280,19 @@ struct TraceMonitor {
     void sweep(JSContext *cx);
 
     /* Mark any tracer stacks that are active. */
     void mark(JSTracer *trc);
 
     bool outOfMemory() const;
 
     JS_FRIEND_API(void) getCodeAllocStats(size_t &total, size_t &frag_size, size_t &free_size) const;
-    JS_FRIEND_API(size_t) getVMAllocatorsMainSize() const;
-    JS_FRIEND_API(size_t) getVMAllocatorsReserveSize() const;
-    JS_FRIEND_API(size_t) getTraceMonitorSize() const;
+    JS_FRIEND_API(size_t) getVMAllocatorsMainSize(JSUsableSizeFun usf) const;
+    JS_FRIEND_API(size_t) getVMAllocatorsReserveSize(JSUsableSizeFun usf) const;
+    JS_FRIEND_API(size_t) getTraceMonitorSize(JSUsableSizeFun usf) const;
 };
 
 namespace mjit {
 class JaegerCompartment;
 }
 }
 
 /* Defined in jsapi.cpp */
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -72,24 +72,22 @@
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseMaps-inl.h"
 
 /* Allocation chunk counts, must be powers of two in general. */
-#define BYTECODE_CHUNK  256     /* code allocation increment */
-#define SRCNOTE_CHUNK   64      /* initial srcnote allocation increment */
-#define TRYNOTE_CHUNK   64      /* trynote allocation increment */
+#define BYTECODE_CHUNK_LENGTH  1024    /* initial bytecode chunk length */
+#define SRCNOTE_CHUNK_LENGTH   1024    /* initial srcnote chunk length */
 
 /* Macros to compute byte sizes from typed element counts. */
 #define BYTECODE_SIZE(n)        ((n) * sizeof(jsbytecode))
 #define SRCNOTE_SIZE(n)         ((n) * sizeof(jssrcnote))
-#define TRYNOTE_SIZE(n)         ((n) * sizeof(JSTryNote))
 
 using namespace js;
 using namespace js::gc;
 
 static JSBool
 NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
            uintN stackDepth, size_t start, size_t end);
 
@@ -101,22 +99,18 @@ static JSBool
 EmitLeaveBlock(JSContext *cx, JSCodeGenerator *cg, JSOp op, JSObjectBox *box);
 
 void
 JSTreeContext::trace(JSTracer *trc)
 {
     bindings.trace(trc);
 }
 
-JSCodeGenerator::JSCodeGenerator(Parser *parser,
-                                 JSArenaPool *cpool, JSArenaPool *npool,
-                                 uintN lineno)
+JSCodeGenerator::JSCodeGenerator(Parser *parser, uintN lineno)
   : JSTreeContext(parser),
-    codePool(cpool), notePool(npool),
-    codeMark(JS_ARENA_MARK(cpool)), noteMark(JS_ARENA_MARK(npool)),
     atomIndices(parser->context),
     stackDepth(0), maxStackDepth(0),
     ntrynotes(0), lastTryNode(NULL),
     spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL),
     numSpanDeps(0), numJumpTargets(0), spanDepTodo(0),
     arrayCompDepth(0),
     emitLevel(0),
     constMap(parser->context),
@@ -130,69 +124,72 @@ JSCodeGenerator::JSCodeGenerator(Parser 
     traceIndex(0),
     typesetCount(0)
 {
     flags = TCF_COMPILING;
     memset(&prolog, 0, sizeof prolog);
     memset(&main, 0, sizeof main);
     current = &main;
     firstLine = prolog.currentLine = main.currentLine = lineno;
-    prolog.noteMask = main.noteMask = SRCNOTE_CHUNK - 1;
 }
 
 bool
 JSCodeGenerator::init(JSContext *cx, JSTreeContext::InitBehavior ib)
 {
     roLexdeps.init();
     return JSTreeContext::init(cx, ib) && constMap.init() && atomIndices.ensureMap(cx);
 }
 
 JSCodeGenerator::~JSCodeGenerator()
 {
-    JS_ARENA_RELEASE(codePool, codeMark);
-    JS_ARENA_RELEASE(notePool, noteMark);
-
     JSContext *cx = parser->context;
 
+    cx->free_(prolog.base);
+    cx->free_(prolog.notes);
+    cx->free_(main.base);
+    cx->free_(main.notes);
+
     /* NB: non-null only after OOM. */
     if (spanDeps)
         cx->free_(spanDeps);
 }
 
 static ptrdiff_t
-EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta)
+EmitCheck(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t delta)
 {
-    jsbytecode *base, *limit, *next;
-    ptrdiff_t offset, length;
-    size_t incr, size;
-
-    base = CG_BASE(cg);
-    next = CG_NEXT(cg);
-    limit = CG_LIMIT(cg);
-    offset = next - base;
+    jsbytecode *base = CG_BASE(cg);
+    jsbytecode *newbase;
+    jsbytecode *next = CG_NEXT(cg);
+    jsbytecode *limit = CG_LIMIT(cg);
+    ptrdiff_t offset = next - base;
+    size_t minlength = offset + delta;
+
     if (next + delta > limit) {
-        length = offset + delta;
-        length = (length <= BYTECODE_CHUNK)
-                 ? BYTECODE_CHUNK
-                 : JS_BIT(JS_CeilingLog2(length));
-        incr = BYTECODE_SIZE(length);
+        size_t newlength;
         if (!base) {
-            JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr);
+            JS_ASSERT(!next && !limit);
+            newlength = BYTECODE_CHUNK_LENGTH;
+            if (newlength < minlength)     /* make it bigger if necessary */
+                newlength = RoundUpPow2(minlength);
+            newbase = (jsbytecode *) cx->malloc_(BYTECODE_SIZE(newlength));
         } else {
-            size = BYTECODE_SIZE(limit - base);
-            incr -= size;
-            JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
-        }
-        if (!base) {
+            JS_ASSERT(base <= next && next <= limit);
+            newlength = (limit - base) * 2;
+            if (newlength < minlength)     /* make it bigger if necessary */
+                newlength = RoundUpPow2(minlength);
+            newbase = (jsbytecode *) cx->realloc_(base, BYTECODE_SIZE(newlength));
+        }
+        if (!newbase) {
             js_ReportOutOfMemory(cx);
             return -1;
         }
-        CG_BASE(cg) = base;
-        CG_LIMIT(cg) = base + length;
-        CG_NEXT(cg) = base + offset;
+        JS_ASSERT(newlength >= size_t(offset + delta));
+        CG_BASE(cg) = newbase;
+        CG_LIMIT(cg) = newbase + newlength;
+        CG_NEXT(cg) = newbase + offset;
     }
     return offset;
 }
 
 static void
 UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
 {
     jsbytecode *pc;
@@ -258,61 +255,61 @@ UpdateDecomposeLength(JSCodeGenerator *c
     uintN end = CG_OFFSET(cg);
     JS_ASSERT(uintN(end - start) < 256);
     CG_CODE(cg, start)[-1] = end - start;
 }
 
 ptrdiff_t
 js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 1);
+    ptrdiff_t offset = EmitCheck(cx, cg, 1);
 
     if (offset >= 0) {
         *CG_NEXT(cg)++ = (jsbytecode)op;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
 js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 2);
+    ptrdiff_t offset = EmitCheck(cx, cg, 2);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = op1;
         CG_NEXT(cg) = next + 2;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
 js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
          jsbytecode op2)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 3);
+    ptrdiff_t offset = EmitCheck(cx, cg, 3);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = op1;
         next[2] = op2;
         CG_NEXT(cg) = next + 3;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
 js_Emit5(JSContext *cx, JSCodeGenerator *cg, JSOp op, uint16 op1, uint16 op2)
 {
-    ptrdiff_t offset = EmitCheck(cx, cg, op, 5);
+    ptrdiff_t offset = EmitCheck(cx, cg, 5);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = UINT16_HI(op1);
         next[2] = UINT16_LO(op1);
         next[3] = UINT16_HI(op2);
         next[4] = UINT16_LO(op2);
@@ -321,17 +318,17 @@ js_Emit5(JSContext *cx, JSCodeGenerator 
     }
     return offset;
 }
 
 ptrdiff_t
 js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra)
 {
     ptrdiff_t length = 1 + (ptrdiff_t)extra;
-    ptrdiff_t offset = EmitCheck(cx, cg, op, length);
+    ptrdiff_t offset = EmitCheck(cx, cg, length);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         *next = (jsbytecode)op;
         memset(next + 1, 0, BYTECODE_SIZE(extra));
         CG_NEXT(cg) = next + length;
 
         /*
@@ -837,17 +834,16 @@ static JSBool
 OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg)
 {
     jsbytecode *pc, *oldpc, *base, *limit, *next;
     JSSpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard;
     ptrdiff_t offset, growth, delta, top, pivot, span, length, target;
     JSBool done;
     JSOp op;
     uint32 type;
-    size_t size, incr;
     jssrcnote *sn, *snlimit;
     JSSrcNoteSpec *spec;
     uintN i, n, noteIndex;
     JSTryNode *tryNode;
     DebugOnly<int> passes = 0;
 
     base = CG_BASE(cg);
     sdbase = cg->spanDeps;
@@ -967,20 +963,17 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGe
         /*
          * Ensure that we have room for the extended jumps, but don't round up
          * to a power of two -- we're done generating code, so we cut to fit.
          */
         limit = CG_LIMIT(cg);
         length = offset + growth;
         next = base + length;
         if (next > limit) {
-            JS_ASSERT(length > BYTECODE_CHUNK);
-            size = BYTECODE_SIZE(limit - base);
-            incr = BYTECODE_SIZE(length) - size;
-            JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
+            base = (jsbytecode *) cx->realloc_(base, BYTECODE_SIZE(length));
             if (!base) {
                 js_ReportOutOfMemory(cx);
                 return JS_FALSE;
             }
             CG_BASE(cg) = base;
             CG_LIMIT(cg) = next = base + length;
         }
         CG_NEXT(cg) = next;
@@ -1052,17 +1045,17 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGe
 
         /*
          * Don't bother copying the jump offset we're about to reset, but do
          * copy the bytecode at oldpc (which comes just before its immediate
          * jump offset operand), on the next iteration through the loop, by
          * including it in offset's new value.
          */
         offset = sd->before + 1;
-        size = BYTECODE_SIZE(delta - (1 + JUMP_OFFSET_LEN));
+        size_t size = BYTECODE_SIZE(delta - (1 + JUMP_OFFSET_LEN));
         if (size) {
             memmove(pc + 1 + JUMPX_OFFSET_LEN,
                     oldpc + 1 + JUMP_OFFSET_LEN,
                     size);
         }
 
         SET_JUMPX_OFFSET(pc, span);
     }
@@ -1222,17 +1215,16 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGe
   }
 #endif
 
     /*
      * Reset so we optimize at most once -- cg may be used for further code
      * generation of successive, independent, top-level statements.  No jump
      * can span top-level statements, because JS lacks goto.
      */
-    size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps)));
     cx->free_(cg->spanDeps);
     cg->spanDeps = NULL;
     FreeJumpTargets(cg, cg->jumpTargets);
     cg->jumpTargets = NULL;
     cg->numSpanDeps = cg->numJumpTargets = 0;
     cg->spanDepTodo = CG_OFFSET(cg);
     return JS_TRUE;
 }
@@ -3707,18 +3699,17 @@ EmitSwitch(JSContext *cx, JSCodeGenerato
             if (off < 0)
                 return JS_FALSE;
             pn3->pn_offset = off;
             if (beforeCases) {
                 uintN noteCount, noteCountDelta;
 
                 /* Switch note's second offset is to first JSOP_CASE. */
                 noteCount = CG_NOTE_COUNT(cg);
-                if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
-                                         off - top)) {
+                if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, off - top)) {
                     return JS_FALSE;
                 }
                 noteCountDelta = CG_NOTE_COUNT(cg) - noteCount;
                 if (noteCountDelta != 0)
                     caseNoteIndex += noteCountDelta;
                 beforeCases = JS_FALSE;
             }
         }
@@ -5020,28 +5011,21 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
                 return JS_FALSE;
             break;
         }
 
         JS_ASSERT_IF(pn->pn_funbox->tcflags & TCF_FUN_HEAVYWEIGHT,
                      fun->kind() == JSFUN_INTERPRETED);
 
         /* Generate code for the function's body. */
-        void *cg2mark = JS_ARENA_MARK(cg->codePool);
-        void *cg2space;
-        JS_ARENA_ALLOCATE_TYPE(cg2space, JSCodeGenerator, cg->codePool);
-        if (!cg2space) {
+        JSCodeGenerator *cg2 = cx->new_<JSCodeGenerator>(cg->parser, pn->pn_pos.begin.lineno);
+        if (!cg2) {
             js_ReportOutOfMemory(cx);
             return JS_FALSE;
         }
-        JSCodeGenerator *cg2 =
-            new (cg2space) JSCodeGenerator(cg->parser,
-                                           cg->codePool, cg->notePool,
-                                           pn->pn_pos.begin.lineno);
-
         if (!cg2->init(cx))
             return JS_FALSE;
 
         cg2->flags = pn->pn_funbox->tcflags | TCF_COMPILING | TCF_IN_FUNCTION |
                      (cg->flags & TCF_FUN_MIGHT_ALIAS_LOCALS);
         cg2->bindings.transfer(cx, &pn->pn_funbox->bindings);
 #if JS_HAS_SHARP_VARS
         if (cg2->flags & TCF_HAS_SHARPS) {
@@ -5061,18 +5045,17 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
          */
         JS_ASSERT(cg->staticLevel < JS_BITMASK(16) - 1);
         cg2->staticLevel = cg->staticLevel + 1;
 
         /* We measured the max scope depth when we parsed the function. */
         if (!js_EmitFunctionScript(cx, cg2, pn->pn_body))
             pn = NULL;
 
-        cg2->~JSCodeGenerator();
-        JS_ARENA_RELEASE(cg->codePool, cg2mark);
+        cx->delete_(cg2);
         cg2 = NULL;
         if (!pn)
             return JS_FALSE;
 
         /* Make the function object a literal in the outer script's pool. */
         index = cg->objectList.index(pn->pn_funbox);
 
         /* Emit a bytecode pointing to the closure object in its immediate. */
@@ -7440,41 +7423,42 @@ JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNote
     {"newline",         0,      0,      0},
     {"setline",         1,      0,      0},
     {"xdelta",          0,      0,      0},
 };
 
 static intN
 AllocSrcNote(JSContext *cx, JSCodeGenerator *cg)
 {
-    intN index;
-    JSArenaPool *pool;
-    size_t size;
-
-    index = CG_NOTE_COUNT(cg);
-    if (((uintN)index & CG_NOTE_MASK(cg)) == 0) {
-        pool = cg->notePool;
-        size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
-        if (!CG_NOTES(cg)) {
-            /* Allocate the first note array lazily; leave noteMask alone. */
-            JS_ARENA_ALLOCATE_CAST(CG_NOTES(cg), jssrcnote *, pool, size);
+    jssrcnote *notes = CG_NOTES(cg);
+    jssrcnote *newnotes;
+    uintN index = CG_NOTE_COUNT(cg);
+    uintN max = CG_NOTE_LIMIT(cg);
+
+    if (index == max) {
+        size_t newlength;
+        if (!notes) {
+            JS_ASSERT(!index && !max);
+            newlength = SRCNOTE_CHUNK_LENGTH;
+            newnotes = (jssrcnote *) cx->malloc_(SRCNOTE_SIZE(newlength));
         } else {
-            /* Grow by doubling note array size; update noteMask on success. */
-            JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
-            if (CG_NOTES(cg))
-                CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
-        }
-        if (!CG_NOTES(cg)) {
+            JS_ASSERT(index <= max);
+            newlength = max * 2;
+            newnotes = (jssrcnote *) cx->realloc_(notes, SRCNOTE_SIZE(newlength));
+        }
+        if (!newnotes) {
             js_ReportOutOfMemory(cx);
             return -1;
         }
+        CG_NOTES(cg) = newnotes;
+        CG_NOTE_LIMIT(cg) = newlength;
     }
 
     CG_NOTE_COUNT(cg) = index + 1;
-    return index;
+    return (intN)index;
 }
 
 intN
 js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type)
 {
     intN index, n;
     jssrcnote *sn;
     ptrdiff_t offset, delta, xdelta;
@@ -7548,28 +7532,24 @@ js_NewSrcNote3(JSContext *cx, JSCodeGene
             return -1;
     }
     return index;
 }
 
 static JSBool
 GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg)
 {
-    JSArenaPool *pool;
-    size_t size;
-
-    /* Grow by doubling note array size; update noteMask on success. */
-    pool = cg->notePool;
-    size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
-    JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
-    if (!CG_NOTES(cg)) {
+    size_t newlength = CG_NOTE_LIMIT(cg) * 2;
+    jssrcnote *newnotes = (jssrcnote *) cx->realloc_(CG_NOTES(cg), newlength);
+    if (!newnotes) {
         js_ReportOutOfMemory(cx);
         return JS_FALSE;
     }
-    CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
+    CG_NOTES(cg) = newnotes;
+    CG_NOTE_LIMIT(cg) = newlength;
     return JS_TRUE;
 }
 
 jssrcnote *
 js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
                      ptrdiff_t delta)
 {
     ptrdiff_t base, limit, newdelta, diff;
@@ -7584,17 +7564,17 @@ js_AddToSrcNoteDelta(JSContext *cx, JSCo
 
     base = SN_DELTA(sn);
     limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
     newdelta = base + delta;
     if (newdelta < limit) {
         SN_SET_DELTA(sn, newdelta);
     } else {
         index = sn - cg->main.notes;
-        if ((cg->main.noteCount & cg->main.noteMask) == 0) {
+        if (cg->main.noteCount == cg->main.noteLimit) {
             if (!GrowSrcNotes(cx, cg))
                 return NULL;
             sn = cg->main.notes + index;
         }
         diff = cg->main.noteCount - index;
         cg->main.noteCount++;
         memmove(sn + 1, sn, SRCNOTE_SIZE(diff));
         SN_MAKE_XDELTA(sn, delta);
@@ -7659,21 +7639,21 @@ js_SetSrcNoteOffset(JSContext *cx, JSCod
     /* See if the new offset requires three bytes. */
     if (offset > (ptrdiff_t)SN_3BYTE_OFFSET_MASK) {
         /* Maybe this offset was already set to a three-byte value. */
         if (!(*sn & SN_3BYTE_OFFSET_FLAG)) {
             /* Losing, need to insert another two bytes for this offset. */
             index = sn - CG_NOTES(cg);
 
             /*
-             * Simultaneously test to see if the source note array must grow to
-             * accommodate either the first or second byte of additional storage
-             * required by this 3-byte offset.
+             * Test to see if the source note array must grow to accommodate
+             * either the first or second byte of additional storage required
+             * by this 3-byte offset.
              */
-            if (((CG_NOTE_COUNT(cg) + 1) & CG_NOTE_MASK(cg)) <= 1) {
+            if (CG_NOTE_COUNT(cg) + 1 >= CG_NOTE_LIMIT(cg)) {
                 if (!GrowSrcNotes(cx, cg))
                     return JS_FALSE;
                 sn = CG_NOTES(cg) + index;
             }
             CG_NOTE_COUNT(cg) += 2;
 
             diff = CG_NOTE_COUNT(cg) - (index + 3);
             JS_ASSERT(diff >= 0);
--- a/js/src/jsemit.h
+++ b/js/src/jsemit.h
@@ -257,17 +257,17 @@ struct JSStmtInfo {
  */
 #define TCF_HAS_SINGLETONS       0x8000000
 
 /*
  * Some enclosing scope is a with-statement or E4X filter-expression.
  */
 #define TCF_IN_WITH             0x10000000
 
-/* 
+/*
  * This function does something that can extend the set of bindings in its
  * call objects --- it does a direct eval in non-strict code, or includes a
  * function statement (as opposed to a function definition).
  *
  * This flag is *not* inherited by enclosed or enclosing functions; it
  * applies only to the function in whose flags it appears.
  */
 #define TCF_FUN_EXTENSIBLE_SCOPE 0x20000000
@@ -421,17 +421,17 @@ struct JSTreeContext {              /* t
     bool inStatement(JSStmtType type);
 
     bool inStrictMode() const {
         return flags & TCF_STRICT_MODE_CODE;
     }
 
     inline bool needStrictChecks();
 
-    /* 
+    /*
      * sharpSlotBase is -1 or first slot of pair for [sharpArray, sharpDepth].
      * The parser calls ensureSharpSlots to allocate these two stack locals.
      */
     int sharpSlotBase;
     bool ensureSharpSlots();
 
     js::Compiler *compiler() { return (js::Compiler *)parser; }
 
@@ -596,28 +596,23 @@ class JSGCConstList {
     bool append(js::Value v) { return list.append(v); }
     size_t length() const { return list.length(); }
     void finish(JSConstArray *array);
 
 };
 
 struct JSCodeGenerator : public JSTreeContext
 {
-    JSArenaPool     *codePool;      /* pointer to thread code arena pool */
-    JSArenaPool     *notePool;      /* pointer to thread srcnote arena pool */
-    void            *codeMark;      /* low watermark in cg->codePool */
-    void            *noteMark;      /* low watermark in cg->notePool */
-
     struct {
         jsbytecode  *base;          /* base of JS bytecode vector */
         jsbytecode  *limit;         /* one byte beyond end of bytecode */
         jsbytecode  *next;          /* pointer to next free bytecode */
         jssrcnote   *notes;         /* source notes, see below */
         uintN       noteCount;      /* number of source notes so far */
-        uintN       noteMask;       /* growth increment for notes */
+        uintN       noteLimit;      /* limit number for source notes in notePool */
         ptrdiff_t   lastNoteOffset; /* code offset for last source note */
         uintN       currentLine;    /* line number for tree-based srcnote gen */
     } prolog, main, *current;
 
     js::OwnedAtomIndexMapPtr atomIndices; /* literals indexed for mapping */
     js::AtomDefnMapPtr roLexdeps;
     uintN           firstLine;      /* first line, for js_NewScriptFromCG */
 
@@ -660,24 +655,17 @@ struct JSCodeGenerator : public JSTreeCo
     /* Vectors of pn_cookie slot values. */
     typedef js::Vector<uint32, 8> SlotVector;
     SlotVector      closedArgs;
     SlotVector      closedVars;
 
     uint16          traceIndex;     /* index for the next JSOP_TRACE instruction */
     uint16          typesetCount;   /* Number of JOF_TYPESET opcodes generated */
 
-    /*
-     * Initialize cg to allocate bytecode space from codePool, source note
-     * space from notePool, and all other arena-allocated temporaries from
-     * parser->context->tempPool.
-     */
-    JSCodeGenerator(js::Parser *parser,
-                    JSArenaPool *codePool, JSArenaPool *notePool,
-                    uintN lineno);
+    JSCodeGenerator(js::Parser *parser, uintN lineno);
     bool init(JSContext *cx, JSTreeContext::InitBehavior ib = USED_AS_CODE_GENERATOR);
 
     JSContext *context() {
         return parser->context;
     }
 
     /*
      * Release cg->codePool, cg->notePool, and parser->context->tempPool to
@@ -685,17 +673,17 @@ struct JSCodeGenerator : public JSTreeCo
      * the arena pool "tops-of-stack" space above their codeMark, noteMark, and
      * tempMark points.  This means you cannot alloc from tempPool and save the
      * pointer beyond the next JSCodeGenerator destructor call.
      */
     ~JSCodeGenerator();
 
     /*
      * Adds a use of a variable that is statically known to exist on the
-     * global object. 
+     * global object.
      *
      * The actual slot of the variable on the global object is not known
      * until after compilation. Properties must be resolved before being
      * added, to avoid aliasing properties that should be resolved. This makes
      * slot prediction based on the global object's free slot impossible. So,
      * we use the slot to index into cg->globalScope->defs, and perform a
      * fixup of the script at the very end of compilation.
      *
@@ -756,17 +744,17 @@ struct JSCodeGenerator : public JSTreeCo
 #define CG_BASE(cg)             ((cg)->current->base)
 #define CG_LIMIT(cg)            ((cg)->current->limit)
 #define CG_NEXT(cg)             ((cg)->current->next)
 #define CG_CODE(cg,offset)      (CG_BASE(cg) + (offset))
 #define CG_OFFSET(cg)           (CG_NEXT(cg) - CG_BASE(cg))
 
 #define CG_NOTES(cg)            ((cg)->current->notes)
 #define CG_NOTE_COUNT(cg)       ((cg)->current->noteCount)
-#define CG_NOTE_MASK(cg)        ((cg)->current->noteMask)
+#define CG_NOTE_LIMIT(cg)       ((cg)->current->noteLimit)
 #define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset)
 #define CG_CURRENT_LINE(cg)     ((cg)->current->currentLine)
 
 #define CG_PROLOG_BASE(cg)      ((cg)->prolog.base)
 #define CG_PROLOG_LIMIT(cg)     ((cg)->prolog.limit)
 #define CG_PROLOG_NEXT(cg)      ((cg)->prolog.next)
 #define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff))
 #define CG_PROLOG_OFFSET(cg)    (CG_PROLOG_NEXT(cg) - CG_PROLOG_BASE(cg))
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1847,17 +1847,16 @@ fun_toSource(JSContext *cx, uintN argc, 
     vp->setString(str);
     return true;
 }
 #endif
 
 JSBool
 js_fun_call(JSContext *cx, uintN argc, Value *vp)
 {
-    LeaveTrace(cx);
     Value fval = vp[1];
 
     if (!js_IsCallable(fval)) {
         ReportIncompatibleMethod(cx, vp, &FunctionClass);
         return false;
     }
 
     Value *argv = vp + 2;
@@ -1913,18 +1912,16 @@ js_fun_apply(JSContext *cx, uintN argc, 
      * Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in
      * original version of ES5).
      */
     JSObject *aobj = &vp[3].toObject();
     jsuint length;
     if (!js_GetLengthProperty(cx, aobj, &length))
         return false;
 
-    LeaveTrace(cx);
-
     /* Step 6. */
     if (length > StackSpace::ARGS_LENGTH_MAX) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_FUN_APPLY_ARGS);
         return false;
     }
 
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, length, &args))
@@ -2022,18 +2019,16 @@ namespace js {
 /* ES5 15.3.4.5.1 and 15.3.4.5.2. */
 JSBool
 CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = &vp[0].toObject();
     JS_ASSERT(obj->isFunction());
     JS_ASSERT(obj->isBoundFunction());
 
-    LeaveTrace(cx);
-
     bool constructing = IsConstructing(vp);
 
     /* 15.3.4.5.1 step 1, 15.3.4.5.2 step 3. */
     uintN argslen = obj->getBoundFunctionArgumentCount();
 
     if (argc + argslen > StackSpace::ARGS_LENGTH_MAX) {
         js_ReportAllocationOverflow(cx);
         return false;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -233,38 +233,34 @@ Arena::finalize(JSContext *cx, AllocKind
 
     FreeSpan nextFree(aheader.getFirstFreeSpan());
     nextFree.checkSpan();
 
     FreeSpan newListHead;
     FreeSpan *newListTail = &newListHead;
     uintptr_t newFreeSpanStart = 0;
     bool allClear = true;
-#ifdef DEBUG
-    size_t nmarked = 0;
-#endif
+    DebugOnly<size_t> nmarked = 0;
     for (;; thing += thingSize) {
         JS_ASSERT(thing <= lastByte + 1);
         if (thing == nextFree.first) {
             JS_ASSERT(nextFree.last <= lastByte);
             if (nextFree.last == lastByte)
                 break;
             JS_ASSERT(Arena::isAligned(nextFree.last, thingSize));
             if (!newFreeSpanStart)
                 newFreeSpanStart = thing;
             thing = nextFree.last;
             nextFree = *nextFree.nextSpan();
             nextFree.checkSpan();
         } else {
             T *t = reinterpret_cast<T *>(thing);
             if (t->isMarked()) {
                 allClear = false;
-#ifdef DEBUG
                 nmarked++;
-#endif
                 if (newFreeSpanStart) {
                     JS_ASSERT(thing >= thingsStart(thingKind) + thingSize);
                     newListTail->first = newFreeSpanStart;
                     newListTail->last = thing - thingSize;
                     newListTail = newListTail->nextSpanUnchecked(thingSize);
                     newFreeSpanStart = 0;
                 }
             } else {
@@ -529,32 +525,32 @@ Chunk::releaseArena(ArenaHeader *aheader
         rt->gcEmptyChunkListHead = this;
         rt->gcEmptyChunkCount++;
     }
 }
 
 inline Chunk *
 AllocateGCChunk(JSRuntime *rt)
 {
-    Chunk *p = (Chunk *)rt->gcChunkAllocator->alloc();
+    Chunk *p = static_cast<Chunk *>(AllocGCChunk());
 #ifdef MOZ_GCTIMER
     if (p)
         JS_ATOMIC_INCREMENT(&newChunkCount);
 #endif
     return p;
 }
 
 inline void
 ReleaseGCChunk(JSRuntime *rt, Chunk *p)
 {
     JS_ASSERT(p);
 #ifdef MOZ_GCTIMER
     JS_ATOMIC_INCREMENT(&destroyChunkCount);
 #endif
-    rt->gcChunkAllocator->free_(p);
+    FreeGCChunk(p);
 }
 
 /* The caller must hold the GC lock. */
 static Chunk *
 PickChunk(JSContext *cx)
 {
     JSCompartment *comp = cx->compartment;
     JSRuntime *rt = comp->rt;
@@ -1552,19 +1548,17 @@ GCMarker::GCMarker(JSContext *cx)
     unmarkedArenaStackTop(MarkingDelay::stackBottom()),
     objStack(cx->runtime->gcMarkStackObjs, sizeof(cx->runtime->gcMarkStackObjs)),
     ropeStack(cx->runtime->gcMarkStackRopes, sizeof(cx->runtime->gcMarkStackRopes)),
     typeStack(cx->runtime->gcMarkStackTypes, sizeof(cx->runtime->gcMarkStackTypes)),
     xmlStack(cx->runtime->gcMarkStackXMLs, sizeof(cx->runtime->gcMarkStackXMLs)),
     largeStack(cx->runtime->gcMarkStackLarges, sizeof(cx->runtime->gcMarkStackLarges))
 {
     JS_TRACER_INIT(this, cx, NULL);
-#ifdef DEBUG
     markLaterArenas = 0;
-#endif
 #ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
     conservativeDumpFileName = getenv("JS_DUMP_CONSERVATIVE_GC_ROOTS");
     memset(&conservativeStats, 0, sizeof(conservativeStats));
 #endif
 }
 
 GCMarker::~GCMarker()
 {
@@ -1579,19 +1573,17 @@ GCMarker::delayMarkingChildren(const voi
     const Cell *cell = reinterpret_cast<const Cell *>(thing);
     ArenaHeader *aheader = cell->arenaHeader();
     if (aheader->getMarkingDelay()->link) {
         /* Arena already scheduled to be marked later */
         return;
     }
     aheader->getMarkingDelay()->link = unmarkedArenaStackTop;
     unmarkedArenaStackTop = aheader;
-#ifdef DEBUG
     markLaterArenas++;
-#endif
 }
 
 static void
 MarkDelayedChildren(JSTracer *trc, ArenaHeader *aheader)
 {
     AllocKind thingKind = aheader->getAllocKind();
     JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind);
     size_t thingSize = aheader->getThingSize();
@@ -1612,20 +1604,18 @@ GCMarker::markDelayedChildren()
          * If marking gets delayed at the same arena again, we must repeat
          * marking of its things. For that we pop arena from the stack and
          * clear its nextDelayedMarking before we begin the marking.
          */
         ArenaHeader *aheader = unmarkedArenaStackTop;
         unmarkedArenaStackTop = aheader->getMarkingDelay()->link;
         JS_ASSERT(unmarkedArenaStackTop);
         aheader->getMarkingDelay()->link = NULL;
-#ifdef DEBUG
         JS_ASSERT(markLaterArenas);
         markLaterArenas--;
-#endif
         MarkDelayedChildren(this, aheader);
     }
     JS_ASSERT(!markLaterArenas);
 }
 
 } /* namespace js */
 
 #ifdef DEBUG
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1475,21 +1475,20 @@ static const size_t TYPE_MARK_STACK_SIZE
 static const size_t LARGE_MARK_STACK_SIZE = 64 * sizeof(LargeMarkItem);
 
 struct GCMarker : public JSTracer {
   private:
     /* The color is only applied to objects, functions and xml. */
     uint32 color;
 
   public:
-    /* See comments before delayMarkingChildren is jsgc.cpp. */
+    /* Pointer to the top of the stack of arenas we are delaying marking on. */
     js::gc::ArenaHeader *unmarkedArenaStackTop;
-#ifdef DEBUG
-    size_t              markLaterArenas;
-#endif
+    /* Count of arenas that are currently in the stack. */
+    DebugOnly<size_t> markLaterArenas;
 
 #ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
     js::gc::ConservativeGCStats conservativeStats;
     Vector<void *, 0, SystemAllocPolicy> conservativeRoots;
     const char *conservativeDumpFileName;
     void dumpConservativeRoots();
 #endif
 
--- a/js/src/jsgcchunk.cpp
+++ b/js/src/jsgcchunk.cpp
@@ -267,27 +267,25 @@ UnmapPages(void *addr, size_t size)
     JS_ALWAYS_TRUE(munmap(addr, size) == 0);
 #endif
 }
 
 #endif
 
 namespace js {
 
-GCChunkAllocator defaultGCChunkAllocator;
-
 inline void *
 FindChunkStart(void *p)
 {
     jsuword addr = reinterpret_cast<jsuword>(p);
     addr = (addr + GC_CHUNK_MASK) & ~GC_CHUNK_MASK;
     return reinterpret_cast<void *>(addr);
 }
 
-JS_FRIEND_API(void *)
+void *
 AllocGCChunk()
 {
     void *p;
 
 #ifdef JS_GC_HAS_MAP_ALIGN
     p = MapAlignedPages(GC_CHUNK_SIZE, GC_CHUNK_SIZE);
     if (!p)
         return NULL;
@@ -324,17 +322,17 @@ AllocGCChunk()
         }
     }
 #endif /* !JS_GC_HAS_MAP_ALIGN */
 
     JS_ASSERT(!(reinterpret_cast<jsuword>(p) & GC_CHUNK_MASK));
     return p;
 }
 
-JS_FRIEND_API(void)
+void
 FreeGCChunk(void *p)
 {
     JS_ASSERT(p);
     JS_ASSERT(!(reinterpret_cast<jsuword>(p) & GC_CHUNK_MASK));
     UnmapPages(p, GC_CHUNK_SIZE);
 }
 
 } /* namespace js */
--- a/js/src/jsgcchunk.h
+++ b/js/src/jsgcchunk.h
@@ -44,49 +44,17 @@
 #include "jsutil.h"
 
 namespace js {
 
 const size_t GC_CHUNK_SHIFT = 20;
 const size_t GC_CHUNK_SIZE = size_t(1) << GC_CHUNK_SHIFT;
 const size_t GC_CHUNK_MASK = GC_CHUNK_SIZE - 1;
 
-JS_FRIEND_API(void *)
+void *
 AllocGCChunk();
 
-JS_FRIEND_API(void)
+void
 FreeGCChunk(void *p);
 
-class GCChunkAllocator {
-  public:
-    GCChunkAllocator() {}
-    
-    void *alloc() {
-        void *chunk = doAlloc();
-        JS_ASSERT(!(reinterpret_cast<jsuword>(chunk) & GC_CHUNK_MASK));
-        return chunk;
-    }
-
-    void free_(void *chunk) {
-        JS_ASSERT(chunk);
-        JS_ASSERT(!(reinterpret_cast<jsuword>(chunk) & GC_CHUNK_MASK));
-        doFree(chunk);
-    }
-    
-  private:
-    virtual void *doAlloc() {
-        return AllocGCChunk();
-    }
-    
-    virtual void doFree(void *chunk) {
-        FreeGCChunk(chunk);
-    }
-
-    /* No copy or assignment semantics. */
-    GCChunkAllocator(const GCChunkAllocator &);
-    void operator=(const GCChunkAllocator &);
-};
-
-extern GCChunkAllocator defaultGCChunkAllocator;
-
 }
 
 #endif /* jsgchunk_h__ */
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -265,16 +265,17 @@ class CellIterImpl
     uintptr_t thing;
     Cell *cell;
 
   protected:
     CellIterImpl() {
     }
 
     void init(JSCompartment *comp, AllocKind kind) {
+        JS_ASSERT(comp->arenas.isSynchronizedFreeList(kind));
         firstThingOffset = Arena::firstThingOffset(kind);
         thingSize = Arena::thingSize(kind);
         aheader = comp->arenas.getFirstArena(kind);
         firstSpan.initAsEmpty();
         span = &firstSpan;
         thing = span->first;
         next();
     }
@@ -317,17 +318,16 @@ class CellIterImpl
     }
 };
 
 class CellIterUnderGC : public CellIterImpl {
 
   public:
     CellIterUnderGC(JSCompartment *comp, AllocKind kind) {
         JS_ASSERT(comp->rt->gcRunning);
-        comp->arenas.checkEmptyFreeList(kind);
         init(comp, kind);
     }
 };
 
 /*
  * When using the iterator outside the GC the caller must ensure that no GC or
  * allocations of GC things are possible and that the background finalization
  * for the given thing kind is not enabled or is done.
--- a/js/src/jshashtable.h
+++ b/js/src/jshashtable.h
@@ -645,18 +645,24 @@ class HashTable : private AllocPolicy
     uint32 count() const {
         return entryCount;
     }
 
     uint32 generation() const {
         return gen;
     }
 
-    size_t tableSize() const {
-        return tableCapacity * sizeof(Entry);
+    /*
+     * This counts the HashTable's |table| array.  If |countMe| is true is also
+     * counts the HashTable object itself.
+     */
+    size_t sizeOf(JSUsableSizeFun usf, bool countMe) const {
+        size_t usable = usf(table) + (countMe ? usf((void*)this) : 0);
+        return usable ? usable
+                      : (tableCapacity * sizeof(Entry)) + (countMe ? sizeof(HashTable) : 0);
     }
 
     Ptr lookup(const Lookup &l) const {
         ReentrancyGuard g(*this);
         HashNumber keyHash = prepareHash(l);
         return Ptr(lookup(l, keyHash, 0));
     }
 
@@ -1077,17 +1083,17 @@ class HashMap
      *   for (HM::Range r = h.all(); !r.empty(); r.popFront())
      *     char c = r.front().value;
      *
      * Also see the definition of Range in HashTable above (with T = Entry).
      */
     typedef typename Impl::Range Range;
     Range all() const                                 { return impl.all(); }
     size_t count() const                              { return impl.count(); }
-    size_t tableSize() const                          { return impl.tableSize(); }
+    size_t sizeOf(JSUsableSizeFun usf, bool cm) const { return impl.sizeOf(usf, cm); }
 
     /*
      * Typedef for the enumeration class. An Enum may be used to examine and
      * remove table entries:
      *
      *   typedef HashMap<int,char> HM;
      *   HM s;
      *   for (HM::Enum e(s); !e.empty(); e.popFront())
@@ -1279,17 +1285,17 @@ class HashSet
      *   for (HS::Range r = h.all(); !r.empty(); r.popFront())
      *     int i = r.front();
      *
      * Also see the definition of Range in HashTable above.
      */
     typedef typename Impl::Range Range;
     Range all() const                                 { return impl.all(); }
     size_t count() const                              { return impl.count(); }
-    size_t tableSize() const                          { return impl.tableSize(); }
+    size_t sizeOf(JSUsableSizeFun usf, bool cm) const { return impl.sizeOf(usf, cm); }
 
     /*
      * Typedef for the enumeration class. An Enum may be used to examine and
      * remove table entries:
      *
      *   typedef HashSet<int> HS;
      *   HS s;
      *   for (HS::Enum e(s); !e.empty(); e.popFront())
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -618,18 +618,16 @@ js::RunScript(JSContext *cx, JSScript *s
  * Find a function reference and its 'this' value implicit first parameter
  * under argc arguments on cx's stack, and call the function.  Push missing
  * required arguments, allocate declared local variables, and pop everything
  * when done.  Then push the return value.
  */
 bool
 js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construct)
 {
-    /* N.B. Must be kept in sync with InvokeSessionGuard::start/invoke */
-
     CallArgs args = argsRef;
     JS_ASSERT(args.argc() <= StackSpace::ARGS_LENGTH_MAX);
 
     JS_ASSERT(!cx->compartment->activeAnalysis);
 
     /* MaybeConstruct is a subset of InitialFrameFlags */
     InitialFrameFlags initial = (InitialFrameFlags) construct;
 
@@ -681,121 +679,19 @@ js::InvokeKernel(JSContext *cx, const Ca
     }
 
     args.rval() = fp->returnValue();
     JS_ASSERT_IF(ok && construct, !args.rval().isPrimitive());
     return ok;
 }
 
 bool
-InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &thisv, uintN argc)
-{
-#ifdef JS_TRACER
-    if (TRACE_RECORDER(cx))
-        AbortRecording(cx, "attempt to reenter VM while recording");
-    LeaveTrace(cx);
-#endif
-
-    /* Always push arguments, regardless of optimized/normal invoke. */
-    ContextStack &stack = cx->stack;
-    if (!stack.pushInvokeArgs(cx, argc, &args_))
-        return false;
-
-    /* Callees may clobber 'this' or 'callee'. */
-    savedCallee_ = args_.calleev() = calleev;
-    savedThis_ = args_.thisv() = thisv;
-
-    /* If anyone (through jsdbgapi) finds this frame, make it safe. */
-    MakeRangeGCSafe(args_.argv(), args_.argc());
-
-    do {
-        /* Hoist dynamic checks from scripted Invoke. */
-        if (!calleev.isObject())
-            break;
-        JSObject &callee = calleev.toObject();
-        if (callee.getClass() != &FunctionClass)
-            break;
-        JSFunction *fun = callee.getFunctionPrivate();
-        if (fun->isNative())
-            break;
-        script_ = fun->script();
-        if (!script_->ensureRanAnalysis(cx, fun, callee.getParent()))
-            return false;
-        if (FunctionNeedsPrologue(cx, fun) || script_->isEmpty())
-            break;
-
-        /*
-         * The frame will remain pushed even when the callee isn't active which
-         * will affect the observable current global, so avoid any change.
-         */
-        if (callee.getGlobal() != GetGlobalForScopeChain(cx))
-            break;
-
-        /* Push the stack frame once for the session. */
-        if (!stack.pushInvokeFrame(cx, args_, INITIAL_NONE, &ifg_))
-            return false;
-
-        /*
-         * Update the 'this' type of the callee according to the value given,
-         * along with the types of any missing arguments. These will be the
-         * same across all calls.
-         */
-        TypeScript::SetThis(cx, script_, thisv);
-        for (unsigned i = argc; i < fun->nargs; i++)
-            TypeScript::SetArgument(cx, script_, i, types::Type::UndefinedType());
-
-        StackFrame *fp = ifg_.fp();
-#ifdef JS_METHODJIT
-        /* Hoist dynamic checks from RunScript. */
-        mjit::CompileStatus status = mjit::CanMethodJIT(cx, script_, false,
-                                                        mjit::CompileRequest_JIT);
-        if (status == mjit::Compile_Error)
-            return false;
-        if (status != mjit::Compile_Okay)
-            break;
-        /* Cannot also cache the raw code pointer; it can change. */
-
-        /* Hoist dynamic checks from CheckStackAndEnterMethodJIT. */
-        JS_CHECK_RECURSION(cx, return false);
-        stackLimit_ = stack.space().getStackLimit(cx, REPORT_ERROR);
-        if (!stackLimit_)
-            return false;
-
-        stop_ = script_->code + script_->length - 1;
-        JS_ASSERT(*stop_ == JSOP_STOP);
-#endif
-
-        /* Cached to avoid canonicalActualArg in InvokeSessionGuard::operator[]. */
-        nformals_ = fp->numFormalArgs();
-        formals_ = fp->formalArgs();
-        actuals_ = args_.argv();
-        JS_ASSERT(actuals_ == fp->actualArgs());
-        return true;
-    } while (0);
-
-    /*
-     * Use the normal invoke path.
-     *
-     * The callee slot gets overwritten during an unoptimized Invoke, so we
-     * cache it here and restore it before every Invoke call. The 'this' value
-     * does not get overwritten, so we can fill it here once.
-     */
-    if (ifg_.pushed())
-        ifg_.pop();
-    formals_ = actuals_ = args_.argv();
-    nformals_ = (unsigned)-1;
-    return true;
-}
-
-bool
 js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, uintN argc, Value *argv,
            Value *rval)
 {
-    LeaveTrace(cx);
-
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return false;
 
     args.calleev() = fval;
     args.thisv() = thisv;
     memcpy(args.argv(), argv, argc * sizeof(Value));
 
@@ -816,18 +712,16 @@ js::Invoke(JSContext *cx, const Value &t
 
     *rval = args.rval();
     return true;
 }
 
 bool
 js::InvokeConstructor(JSContext *cx, const Value &fval, uintN argc, Value *argv, Value *rval)
 {
-    LeaveTrace(cx);
-
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return false;
 
     args.calleev() = fval;
     args.thisv().setMagic(JS_THIS_POISON);
     memcpy(args.argv(), argv, argc * sizeof(Value));
 
@@ -1239,18 +1133,16 @@ error:
     js_ReportIsNotFunction(cx, &args.calleev(), JSV2F_CONSTRUCT);
     return false;
 }
 
 bool
 js::InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval,
                                    uintN argc, Value *argv, Value *rval)
 {
-    LeaveTrace(cx);
-
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
         return JS_FALSE;
 
     args.calleev() = fval;
     /* Initialize args.thisv on all paths below. */
     memcpy(args.argv(), argv, argc * sizeof(Value));
 
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -183,42 +183,16 @@ Invoke(JSContext *cx, const Value &thisv
  * This helper takes care of the infinite-recursion check necessary for
  * getter/setter calls.
  */
 extern bool
 InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, uintN argc, Value *argv,
                      Value *rval);
 
 /*
- * Natives like sort/forEach/replace call Invoke repeatedly with the same
- * callee, this, and number of arguments. To optimize this, such natives can
- * start an "invoke session" to factor out much of the dynamic setup logic
- * required by a normal Invoke. Usage is:
- *
- *   InvokeSessionGuard session(cx);
- *   if (!session.start(cx, callee, thisp, argc, &session))
- *     ...
- *
- *   while (...) {
- *     // write actual args (not callee, this)
- *     session[0] = ...
- *     ...
- *     session[argc - 1] = ...
- *
- *     if (!session.invoke(cx, session))
- *       ...
- *
- *     ... = session.rval();
- *   }
- *
- *   // session ended by ~InvokeSessionGuard
- */
-class InvokeSessionGuard;
-
-/*
  * InvokeConstructor* implement a function call from a constructor context
  * (e.g. 'new') handling the the creation of the new 'this' object.
  */
 extern JS_REQUIRES_STACK bool
 InvokeConstructorKernel(JSContext *cx, const CallArgs &args);
 
 /* See the InvokeArgsGuard overload of Invoke. */
 inline bool
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -66,137 +66,16 @@ class AutoPreserveEnumerators {
     }
 
     ~AutoPreserveEnumerators()
     {
         cx->enumerators = enumerators;
     }
 };
 
-class InvokeSessionGuard
-{
-    InvokeArgsGuard args_;
-    InvokeFrameGuard ifg_;
-    Value savedCallee_, savedThis_;
-    Value *formals_, *actuals_;
-    unsigned nformals_;
-    JSScript *script_;
-    Value *stackLimit_;
-    jsbytecode *stop_;
-
-    bool optimized() const { return ifg_.pushed(); }
-
-  public:
-    InvokeSessionGuard() : args_(), ifg_() {}
-    ~InvokeSessionGuard() {}
-
-    bool start(JSContext *cx, const Value &callee, const Value &thisv, uintN argc);
-    bool invoke(JSContext *cx);
-
-    bool started() const {
-        return args_.pushed();
-    }
-
-    Value &operator[](unsigned i) const {
-        JS_ASSERT(i < argc());
-        Value &arg = i < nformals_ ? formals_[i] : actuals_[i];
-        JS_ASSERT_IF(optimized(), &arg == &ifg_.fp()->canonicalActualArg(i));
-        JS_ASSERT_IF(!optimized(), &arg == &args_[i]);
-        return arg;
-    }
-
-    uintN argc() const {
-        return args_.argc();
-    }
-
-    const Value &rval() const {
-        return optimized() ? ifg_.fp()->returnValue() : args_.rval();
-    }
-};
-
-inline bool
-InvokeSessionGuard::invoke(JSContext *cx)
-{
-    /* N.B. Must be kept in sync with Invoke */
-
-    /* Refer to canonical (callee, this) for optimized() sessions. */
-    formals_[-2] = savedCallee_;
-    formals_[-1] = savedThis_;
-
-    /* Prevent spurious accessing-callee-after-rval assert. */
-    args_.calleeHasBeenReset();
-
-    if (!optimized())
-        return Invoke(cx, args_);
-
-    /*
-     * Update the types of each argument. The 'this' type and missing argument
-     * types were handled when the invoke session was created.
-     */
-    for (unsigned i = 0; i < Min(argc(), nformals_); i++)
-        types::TypeScript::SetArgument(cx, script_, i, (*this)[i]);
-
-#ifdef JS_METHODJIT
-    mjit::JITScript *jit = script_->getJIT(false /* !constructing */);
-    if (!jit) {
-        /* Watch in case the code was thrown away due a recompile. */
-        mjit::CompileStatus status = mjit::TryCompile(cx, script_, false);
-        if (status == mjit::Compile_Error)
-            return false;
-        JS_ASSERT(status == mjit::Compile_Okay);
-        jit = script_->getJIT(false);
-    }
-    void *code;
-    if (!(code = jit->invokeEntry))
-        return Invoke(cx, args_);
-#endif
-
-    StackFrame *fp = ifg_.fp();
-
-    /*
-     * Clear any activation objects on the frame. Normally the frame should not
-     * have any, but since we leave it on the stack between calls to invoke()
-     * the debugger can start operating on it. See markFunctionEpilogueDone()
-     * calls below. :XXX: this is pretty gross, and slows us down. Can the
-     * debugger be prevented from observing this frame?
-     */
-    fp->functionEpilogue(/* activationOnly = */ true);
-    fp->markFunctionEpilogueDone(/* activationOnly = */ true);
-
-    fp->resetCallFrame(script_);
-
-    JSBool ok;
-    {
-        AutoPreserveEnumerators preserve(cx);
-        args_.setActive();  /* From js::Invoke(InvokeArgsGuard) overload. */
-        Probes::enterJSFun(cx, fp->fun(), script_);
-#ifdef JS_METHODJIT
-        ok = mjit::EnterMethodJIT(cx, fp, code, stackLimit_, /* partial = */ false);
-        cx->regs().pc = stop_;
-#else
-        cx->regs().pc = script_->code;
-        ok = Interpret(cx, cx->fp());
-
-        /* Interpret does not perform the entry frame's epilogue, unlike EnterMethodJIT. */
-        cx->fp()->functionEpilogue();
-#endif
-        Probes::exitJSFun(cx, fp->fun(), script_);
-        args_.setInactive();
-    }
-
-    /*
-     * Clear activation object flags, for the functionEpilogue() call in the
-     * next invoke().
-     */
-    fp->markFunctionEpilogueDone(/* activationOnly = */ true);
-
-    /* Don't clobber callee with rval; rval gets read from fp->rval. */
-    return ok;
-}
-
 namespace detail {
 
 template<typename T> class PrimitiveBehavior { };
 
 template<>
 class PrimitiveBehavior<JSString *> {
   public:
     static inline bool isType(const Value &v) { return v.isString(); }
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2713,21 +2713,21 @@ obj_preventExtensions(JSContext *cx, uin
     if (!obj->isExtensible())
         return true;
 
     AutoIdVector props(cx);
     return obj->preventExtensions(cx, &props);
 }
 
 size_t
-JSObject::sizeOfSlotsArray(size_t(*mus)(void *))
+JSObject::sizeOfSlotsArray(JSUsableSizeFun usf)
 {
     if (!hasSlotsArray())
         return 0;
-    size_t usable = mus((void *)slots);
+    size_t usable = usf((void *)slots);
     return usable ? usable : numSlots() * sizeof(js::Value);
 }
 
 bool
 JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
 {
     assertSameCompartment(cx, this);
     JS_ASSERT(it == SEAL || it == FREEZE);
@@ -3264,46 +3264,101 @@ with_LookupProperty(JSContext *cx, JSObj
     if (flags == RESOLVE_INFER)
         flags = js_InferFlags(cx, flags);
     flags |= JSRESOLVE_WITH;
     JSAutoResolveFlags rf(cx, flags);
     return obj->getProto()->lookupProperty(cx, id, objp, propp);
 }
 
 static JSBool
+with_LookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
+                   JSProperty **propp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return with_LookupProperty(cx, obj, id, objp, propp);
+}
+
+static JSBool
 with_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     return obj->getProto()->getProperty(cx, id, vp);
 }
 
 static JSBool
+with_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return with_GetProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 with_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     return obj->getProto()->setProperty(cx, id, vp, strict);
 }
 
 static JSBool
+with_SetElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return with_SetProperty(cx, obj, id, vp, strict);
+}
+
+static JSBool
 with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     return obj->getProto()->getAttributes(cx, id, attrsp);
 }
 
 static JSBool
+with_GetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return with_GetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     return obj->getProto()->setAttributes(cx, id, attrsp);
 }
 
 static JSBool
+with_SetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return with_SetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     return obj->getProto()->deleteProperty(cx, id, rval, strict);
 }
 
 static JSBool
+with_DeleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return with_DeleteProperty(cx, obj, id, rval, strict);
+}
+
+static JSBool
 with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                Value *statep, jsid *idp)
 {
     return obj->getProto()->enumerate(cx, enum_op, statep, idp);
 }
 
 static JSType
 with_TypeOf(JSContext *cx, JSObject *obj)
@@ -3333,22 +3388,29 @@ Class js::WithClass = {
     NULL,                 /* call        */
     NULL,                 /* construct   */
     NULL,                 /* xdrObject   */
     NULL,                 /* hasInstance */
     NULL,                 /* trace       */
     JS_NULL_CLASS_EXT,
     {
         with_LookupProperty,
+        with_LookupElement,
         NULL,             /* defineProperty */
+        NULL,             /* defineElement */
         with_GetProperty,
+        with_GetElement,
         with_SetProperty,
+        with_SetElement,
         with_GetAttributes,
+        with_GetElementAttributes,
         with_SetAttributes,
+        with_SetElementAttributes,
         with_DeleteProperty,
+        with_DeleteElement,
         with_Enumerate,
         with_TypeOf,
         NULL,             /* fix   */
         with_ThisObject,
         NULL,             /* clear */
     }
 };
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -473,17 +473,17 @@ struct JSObject : js::gc::Cell {
     union {
         /* If prototype, type of values using this as their prototype. */
         js::types::TypeObject *newType;
 
         /* If dense array, the initialized length (see jsarray.cpp). */
         jsuword initializedLength;
     };
 
-    JS_FRIEND_API(size_t) sizeOfSlotsArray(size_t(*mus)(void *));
+    JS_FRIEND_API(size_t) sizeOfSlotsArray(JSUsableSizeFun usf);
 
     JSObject    *parent;                    /* object's parent */
     void        *privateData;               /* private data */
     jsuword     capacity;                   /* total number of available slots */
 
   private:
     js::Value   *slots;                     /* dynamically allocated slots,
                                                or pointer to fixedSlots() for
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -297,17 +297,16 @@ PreprocessValue(JSContext *cx, JSObject 
         if (!js_GetMethod(cx, &vp->toObject(), id, JSGET_NO_METHOD_BARRIER, &toJSON))
             return false;
 
         if (js_IsCallable(toJSON)) {
             keyStr = IdToString(cx, key);
             if (!keyStr)
                 return false;
 
-            LeaveTrace(cx);
             InvokeArgsGuard args;
             if (!cx->stack.pushInvokeArgs(cx, 1, &args))
                 return false;
 
             args.calleev() = toJSON;
             args.thisv() = *vp;
             args[0] = StringValue(keyStr);
 
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -315,17 +315,17 @@ JSFunctionBox::joinable() const
                        TCF_FUN_USES_OWN_NAME |
                        TCF_COMPILE_N_GO)) == TCF_COMPILE_N_GO;
 }
 
 bool
 JSFunctionBox::inAnyDynamicScope() const
 {
     for (const JSFunctionBox *funbox = this; funbox; funbox = funbox->parent) {
-        if (funbox->tcflags & (TCF_IN_WITH | TCF_FUN_CALLS_EVAL))
+        if (funbox->tcflags & (TCF_IN_WITH | TCF_FUN_EXTENSIBLE_SCOPE))
             return true;
     }
     return false;
 }
 
 bool
 JSFunctionBox::scopeIsExtensible() const
 {
@@ -898,17 +898,16 @@ Compiler::Compiler(JSContext *cx, JSPrin
 JSScript *
 Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame,
                         JSPrincipals *principals, uint32 tcflags,
                         const jschar *chars, size_t length,
                         const char *filename, uintN lineno, JSVersion version,
                         JSString *source /* = NULL */,
                         uintN staticLevel /* = 0 */)
 {
-    JSArenaPool codePool, notePool;
     TokenKind tt;
     JSParseNode *pn;
     JSScript *script;
     bool inDirectivePrologue;
 
     JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL | TCF_NEED_MUTABLE_SCRIPT |
                             TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_OBJECT)));
 
@@ -918,23 +917,20 @@ Compiler::compileScript(JSContext *cx, J
      */
     JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
     JS_ASSERT_IF(staticLevel != 0, callerFrame);
 
     Compiler compiler(cx, principals, callerFrame);
     if (!compiler.init(chars, length, filename, lineno, version))
         return NULL;
 
-    JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
-    JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
-
     Parser &parser = compiler.parser;
     TokenStream &tokenStream = parser.tokenStream;
 
-    JSCodeGenerator cg(&parser, &codePool, &notePool, tokenStream.getLineno());
+    JSCodeGenerator cg(&parser, tokenStream.getLineno());
     if (!cg.init(cx, JSTreeContext::USED_AS_TREE_CONTEXT))
         return NULL;
 
     Probes::compileScriptBegin(cx, filename, lineno);
 
     MUST_FLOW_THROUGH("out");
 
     // We can specialize a bit for the given scope chain if that scope chain is the global object.
@@ -1113,18 +1109,16 @@ Compiler::compileScript(JSContext *cx, J
         goto out;
 
     JS_ASSERT(script->savedCallerFun == savedCallerFun);
 
     if (!defineGlobals(cx, globalScope, script))
         script = NULL;
 
   out:
-    JS_FinishArenaPool(&codePool);
-    JS_FinishArenaPool(&notePool);
     Probes::compileScriptEnd(cx, script, filename, lineno);
     return script;
 
   too_many_slots:
     parser.reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_TOO_MANY_LOCALS);
     script = NULL;
     goto out;
 }
@@ -1777,25 +1771,20 @@ Compiler::compileFunctionBody(JSContext 
                               Bindings *bindings, const jschar *chars, size_t length,
                               const char *filename, uintN lineno, JSVersion version)
 {
     Compiler compiler(cx, principals);
 
     if (!compiler.init(chars, length, filename, lineno, version))
         return false;
 
-    /* No early return from after here until the js_FinishArenaPool calls. */
-    JSArenaPool codePool, notePool;
-    JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
-    JS_InitArenaPool(&notePool, "note", 1024, sizeof(jssrcnote));
-
     Parser &parser = compiler.parser;
     TokenStream &tokenStream = parser.tokenStream;
 
-    JSCodeGenerator funcg(&parser, &codePool, &notePool, tokenStream.getLineno());
+    JSCodeGenerator funcg(&parser, tokenStream.getLineno());
     if (!funcg.init(cx, JSTreeContext::USED_AS_TREE_CONTEXT))
         return false;
 
     funcg.flags |= TCF_IN_FUNCTION;
     funcg.setFunction(fun);
     funcg.bindings.transfer(cx, bindings);
     fun->setArgCount(funcg.bindings.countArgs());
     if (!GenerateBlockId(&funcg, funcg.bodyid))
@@ -1855,19 +1844,16 @@ Compiler::compileFunctionBody(JSContext 
                 pn = fn->pn_body;
             }
 
             if (!js_EmitFunctionScript(cx, &funcg, pn))
                 pn = NULL;
         }
     }
 
-    /* Restore saved state and release code generation arenas. */
-    JS_FinishArenaPool(&codePool);
-    JS_FinishArenaPool(&notePool);
     return pn != NULL;
 }
 
 /*
  * Parameter block types for the several Binder functions.  We use a common
  * helper function signature in order to share code among destructuring and
  * simple variable declaration parsers.  In the destructuring case, the binder
  * function is called indirectly from the variable declaration parser by way
@@ -6743,17 +6729,17 @@ class GenexpGuard {
         }
         startYieldCount = tc->yieldCount;
         startArgumentsCount = tc->argumentsCount;
         tc->parenDepth++;
     }
 
     void endBody();
     bool checkValidBody(JSParseNode *pn);
-    bool maybeNoteGenerator();
+    bool maybeNoteGenerator(JSParseNode *pn);
 };
 
 void
 GenexpGuard::endBody()
 {
     tc->parenDepth--;
 }
 
@@ -6789,25 +6775,32 @@ GenexpGuard::checkValidBody(JSParseNode 
 /*
  * Check whether a |yield| token has been encountered in the body expression,
  * and if so, note that the current function is a generator function.
  *
  * Call this after endBody() when determining that the body *was not* in a
  * generator expression.
  */
 bool
-GenexpGuard::maybeNoteGenerator()
+GenexpGuard::maybeNoteGenerator(JSParseNode *pn)
 {
     if (tc->yieldCount > 0) {
         tc->flags |= TCF_FUN_IS_GENERATOR;
         if (!tc->inFunction()) {
             tc->parser->reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD,
                                           js_yield_str);
             return false;
         }
+        if (tc->flags & TCF_RETURN_EXPR) {
+            /* At the time we saw the yield, we might not have set TCF_FUN_IS_GENERATOR yet. */
+            ReportBadReturn(tc->parser->context, tc, pn, JSREPORT_ERROR,
+                            JSMSG_BAD_GENERATOR_RETURN,
+                            JSMSG_BAD_ANON_GENERATOR_RETURN);
+            return false;
+        }
     }
     return true;
 }
 
 /*
  * Any definitions nested within the comprehension expression of a generator
  * expression must move "down" one static level, which of course increases the
  * upvar-frame-skip count.
@@ -7138,17 +7131,17 @@ Parser::comprehensionTail(JSParseNode *k
         MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL);
 
         guard.endBody();
 
         if (isGenexp) {
             if (!guard.checkValidBody(pn2))
                 return NULL;
         } else {
-            if (!guard.maybeNoteGenerator())
+            if (!guard.maybeNoteGenerator(pn2))
                 return NULL;
         }
 
         switch (tt) {
 #if JS_HAS_DESTRUCTURING
           case TOK_LB:
           case TOK_LC:
             if (!CheckDestructuring(context, &data, pn3, tc))
@@ -7368,17 +7361,17 @@ Parser::argumentList(JSParseNode *listNo
             if (listNode->pn_count > 1 ||
                 tokenStream.peekToken() == TOK_COMMA) {
                 reportErrorNumber(argNode, JSREPORT_ERROR, JSMSG_BAD_GENERATOR_SYNTAX,
                                   js_generator_str);
                 return JS_FALSE;
             }
         } else
 #endif
-        if (arg0 && !guard.maybeNoteGenerator())
+        if (arg0 && !guard.maybeNoteGenerator(argNode))
             return JS_FALSE;
 
         arg0 = false;
 
         listNode->append(argNode);
     } while (tokenStream.matchToken(TOK_COMMA));
 
     if (tokenStream.getToken() != TOK_RP) {
@@ -8463,17 +8456,16 @@ Parser::primaryExpr(TokenKind tt, JSBool
             MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST);
         }
         pn->pn_pos.end = tokenStream.currentToken().pos.end;
         return pn;
       }
 
       case TOK_LC:
       {
-        JSBool afterComma;
         JSParseNode *pnval;
 
         /*
          * A map from property names we've seen thus far to a mask of property
          * assignment types, stored and retrieved with ALE_SET_INDEX/ALE_INDEX.
          */
         AtomIndexMap seen(context);
 
@@ -8485,17 +8477,16 @@ Parser::primaryExpr(TokenKind tt, JSBool
 
         pn = ListNode::create(tc);
         if (!pn)
             return NULL;
         pn->pn_type = TOK_RC;
         pn->pn_op = JSOP_NEWINIT;
         pn->makeEmpty();
 
-        afterComma = JS_FALSE;
         for (;;) {
             JSAtom *atom;
             tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME);
             switch (tt) {
               case TOK_NUMBER:
                 pn3 = NullaryNode::create(tc);
                 if (!pn3)
                     return NULL;
@@ -8644,17 +8635,16 @@ Parser::primaryExpr(TokenKind tt, JSBool
 
             tt = tokenStream.getToken();
             if (tt == TOK_RC)
                 goto end_obj_init;
             if (tt != TOK_COMMA) {
                 reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_CURLY_AFTER_LIST);
                 return NULL;
             }
-            afterComma = JS_TRUE;
         }
 
       end_obj_init:
         pn->pn_pos.end = tokenStream.currentToken().pos.end;
         return pn;
       }
 
 #if JS_HAS_BLOCK_SCOPE
@@ -8989,17 +8979,17 @@ Parser::parenExpr(JSBool *genexp)
                 return NULL;
             }
             pn->pn_pos.end = tokenStream.currentToken().pos.end;
             *genexp = JS_TRUE;
         }
     } else
 #endif /* JS_HAS_GENERATOR_EXPRS */
 
-    if (!guard.maybeNoteGenerator())
+    if (!guard.maybeNoteGenerator(pn))
         return NULL;
 
     return pn;
 }
 
 /*
  * Fold from one constant type to another.
  * XXX handles only strings and numbers for now
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -897,73 +897,138 @@ proxy_LookupProperty(JSContext *cx, JSOb
     } else {
         *objp = NULL;
         *propp = NULL;
     }
     return true;
 }
 
 static JSBool
+proxy_LookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
+                    JSProperty **propp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return proxy_LookupProperty(cx, obj, id, objp, propp);
+}
+
+static JSBool
 proxy_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                      PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     AutoPropertyDescriptorRooter desc(cx);
     desc.obj = obj;
     desc.value = *value;
     desc.attrs = (attrs & (~JSPROP_SHORTID));
     desc.getter = getter;
     desc.setter = setter;
     desc.shortid = 0;
     return JSProxy::defineProperty(cx, obj, id, &desc);
 }
 
 static JSBool
+proxy_DefineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *value,
+                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return proxy_DefineProperty(cx, obj, id, value, getter, setter, attrs);
+}
+
+static JSBool
 proxy_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     return JSProxy::get(cx, obj, receiver, id, vp);
 }
 
 static JSBool
+proxy_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return proxy_GetProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 proxy_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     return JSProxy::set(cx, obj, obj, id, strict, vp);
 }
 
 static JSBool
+proxy_SetElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return proxy_SetProperty(cx, obj, id, vp, strict);
+}
+
+static JSBool
 proxy_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     AutoPropertyDescriptorRooter desc(cx);
     if (!JSProxy::getOwnPropertyDescriptor(cx, obj, id, false, &desc))
         return false;
     *attrsp = desc.attrs;
     return true;
 }
 
 static JSBool
+proxy_GetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return proxy_GetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 proxy_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     /* Lookup the current property descriptor so we have setter/getter/value. */
     AutoPropertyDescriptorRooter desc(cx);
     if (!JSProxy::getOwnPropertyDescriptor(cx, obj, id, true, &desc))
         return false;
     desc.attrs = (*attrsp & (~JSPROP_SHORTID));
     return JSProxy::defineProperty(cx, obj, id, &desc);
 }
 
 static JSBool
+proxy_SetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return proxy_SetAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 proxy_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     // TODO: throwing away strict
     bool deleted;
     if (!JSProxy::delete_(cx, obj, id, &deleted) || !js_SuppressDeletedProperty(cx, obj, id))
         return false;
     rval->setBoolean(deleted);
     return true;
 }
 
+static JSBool
+proxy_DeleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return proxy_DeleteProperty(cx, obj, id, rval, strict);
+}
+
 static void
 proxy_TraceObject(JSTracer *trc, JSObject *obj)
 {
     obj->getProxyHandler()->trace(trc, obj);
     MarkCrossCompartmentValue(trc, obj->getProxyPrivate(), "private");
     MarkCrossCompartmentValue(trc, obj->getProxyExtra(), "extra");
     if (obj->isFunctionProxy()) {
         MarkCrossCompartmentValue(trc, GetCall(obj), "call");
@@ -1041,22 +1106,29 @@ JS_FRIEND_DATA(Class) js::ObjectProxyCla
     NULL,                 /* call        */
     NULL,                 /* construct   */
     NULL,                 /* xdrObject   */
     proxy_HasInstance,    /* hasInstance */
     proxy_TraceObject,    /* trace       */
     JS_NULL_CLASS_EXT,
     {
         proxy_LookupProperty,
+        proxy_LookupElement,
         proxy_DefineProperty,
+        proxy_DefineElement,
         proxy_GetProperty,
+        proxy_GetElement,
         proxy_SetProperty,
+        proxy_SetElement,
         proxy_GetAttributes,
+        proxy_GetElementAttributes,
         proxy_SetAttributes,
+        proxy_SetElementAttributes,
         proxy_DeleteProperty,
+        proxy_DeleteElement,
         NULL,             /* enumerate       */
         proxy_TypeOf,
         proxy_Fix,        /* fix             */
         NULL,             /* thisObject      */
         NULL,             /* clear           */
     }
 };
 
@@ -1081,22 +1153,29 @@ JS_FRIEND_DATA(Class) js::OuterWindowPro
     {
         NULL,             /* equality    */
         NULL,             /* outerObject */
         proxy_innerObject,
         NULL        /* unused */
     },
     {
         proxy_LookupProperty,
+        proxy_LookupElement,
         proxy_DefineProperty,
+        proxy_DefineElement,
         proxy_GetProperty,
+        proxy_GetElement,
         proxy_SetProperty,
+        proxy_SetElement,
         proxy_GetAttributes,
+        proxy_GetElementAttributes,
         proxy_SetAttributes,
+        proxy_SetElementAttributes,
         proxy_DeleteProperty,
+        proxy_DeleteElement,
         NULL,             /* enumerate       */
         NULL,             /* typeof          */
         NULL,             /* fix             */
         NULL,             /* thisObject      */
         NULL,             /* clear           */
     }
 };
 
@@ -1133,22 +1212,29 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
     proxy_Call,
     proxy_Construct,
     NULL,                 /* xdrObject   */
     FunctionClass.hasInstance,
     proxy_TraceFunction,  /* trace       */
     JS_NULL_CLASS_EXT,
     {
         proxy_LookupProperty,
+        proxy_LookupElement,
         proxy_DefineProperty,
+        proxy_DefineElement,
         proxy_GetProperty,
+        proxy_GetElement,
         proxy_SetProperty,
+        proxy_SetElement,
         proxy_GetAttributes,
+        proxy_GetElementAttributes,
         proxy_SetAttributes,
+        proxy_SetElementAttributes,
         proxy_DeleteProperty,
+        proxy_DeleteElement,
         NULL,             /* enumerate       */
         proxy_TypeOf,
         NULL,             /* fix             */
         NULL,             /* thisObject      */
         NULL,             /* clear           */
     }
 };
 
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -129,17 +129,16 @@ namespace js {
 struct ArgumentsData;
 
 class RegExp;
 class RegExpStatics;
 class AutoStringRooter;
 class ExecuteArgsGuard;
 class InvokeFrameGuard;
 class InvokeArgsGuard;
-class InvokeSessionGuard;
 class StringBuffer;
 class TraceRecorder;
 struct TraceMonitor;
 
 class FrameRegs;
 class StackFrame;
 class StackSegment;
 class StackSpace;
@@ -324,21 +323,16 @@ typedef struct JSDebugHooks {
  * exception, true on success.  On success, return null in *propp if id was
  * not found.  If id was found, return the first object searching from obj
  * along its prototype chain in which id names a direct property in *objp, and
  * return a non-null, opaque property pointer in *propp.
  *
  * If JSLookupPropOp succeeds and returns with *propp non-null, that pointer
  * may be passed as the prop parameter to a JSAttributesOp, as a short-cut
  * that bypasses id re-lookup.
- *
- * NB: successful return with non-null *propp means the implementation may
- * have locked *objp and added a reference count associated with *propp, so
- * callers should not risk deadlock by nesting or interleaving other lookups
- * or any obj-bearing ops before dropping *propp.
  */
 typedef JSBool
 (* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
                    JSProperty **propp);
 
 /*
  * Get or set attributes of the property obj[id]. Return false on error or
  * exception, true with current attributes in *attrsp.
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -246,23 +246,23 @@ struct PropertyTable {
     }
 
     /* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */
     uint32 capacity() const { return JS_BIT(JS_DHASH_BITS - hashShift); }
 
     /* Computes the size of the entries array for a given capacity. */
     static size_t sizeOfEntries(size_t cap) { return cap * sizeof(Shape *); }
 
-    size_t sizeOf(size_t(*mus)(void *)) const {
-        if (mus) {
-            size_t usable = mus((void*)this) + mus(entries);
-            if (usable)
-                return usable;
-        }
-        return sizeOfEntries(capacity()) + sizeof(PropertyTable);
+    /*
+     * This counts the PropertyTable object itself (which must be
+     * heap-allocated) and its |entries| array.
+     */
+    size_t sizeOf(JSUsableSizeFun usf) const {
+        size_t usable = usf((void*)this) + usf(entries);
+        return usable ? usable : sizeOfEntries(capacity()) + sizeof(PropertyTable);
     }
 
     /* Whether we need to grow.  We want to do this if the load factor is >= 0.75 */
     bool needsToGrow() const {
         uint32 size = capacity();
         return entryCount + removedCount >= size - (size >> 2);
     }
 
@@ -352,16 +352,17 @@ struct Shape : public js::gc::Cell
   private:
     uint8               attrs;          /* attributes, see jsapi.h JSPROP_* */
     mutable uint8       flags;          /* flags, see below for defines */
   public:
     int16               shortid;        /* tinyid, or local arg/var index */
 
   protected:
     mutable js::Shape   *parent;        /* parent node, reverse for..in order */
+    /* kids is valid when !inDictionary(), listp is valid when inDictionary(). */
     union {
         mutable js::KidsPointer kids;   /* null, single child, or a tagged ptr
                                            to many-kids data structure */
         mutable js::Shape **listp;      /* dictionary list starting at lastProp
                                            has a double-indirect back pointer,
                                            either to shape->parent if not last,
                                            else to obj->lastProp */
     };
@@ -440,16 +441,27 @@ struct Shape : public js::gc::Cell
         return numLinearSearches > PropertyTable::MAX_LINEAR_SEARCHES;
     }
 
     js::PropertyTable *getTable() const {
         JS_ASSERT(hasTable());
         return table;
     }
 
+    size_t sizeOfPropertyTable(JSUsableSizeFun usf) const {
+        return hasTable() ? getTable()->sizeOf(usf) : 0;
+    }
+
+    size_t sizeOfKids(JSUsableSizeFun usf) const {
+        /* Nb: |countMe| is true because the kids HashTable is on the heap. */
+        return (!inDictionary() && kids.isHash())
+             ? kids.toHash()->sizeOf(usf, /* countMe */true)
+             : 0;
+    }
+
     bool isNative() const { return this != &sharedNonNative; }
 
     const js::Shape *previous() const {
         return parent;
     }
 
     class Range {
       protected:
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1284,16 +1284,28 @@ JSScript::dataSize()
         return 0;
 #endif
 
     uint8 *dataEnd = code + length * sizeof(jsbytecode) + numNotes() * sizeof(jssrcnote);
     JS_ASSERT(dataEnd >= data);
     return dataEnd - data;
 }
 
+size_t
+JSScript::dataSize(JSUsableSizeFun usf)
+{
+#if JS_SCRIPT_INLINE_DATA_LIMIT
+    if (data == inlineData)
+        return 0;
+#endif
+
+    size_t usable = usf(data);
+    return usable ? usable : dataSize();
+}
+
 void
 JSScript::setOwnerObject(JSObject *owner)
 {
 #ifdef JS_CRASH_DIAGNOSTICS
     CheckScriptOwner(this, JS_NEW_SCRIPT);
     ownerObject = owner;
 #endif
 }
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -678,25 +678,31 @@ struct JSScript : public js::gc::Cell {
         if (addr == NULL)
             return JITScript_None;
         if (addr == JS_UNJITTABLE_SCRIPT)
             return JITScript_Invalid;
         return JITScript_Valid;
     }
 
     /* Size of the JITScript and all sections.  (This method is implemented in MethodJIT.h.) */
-    JS_FRIEND_API(size_t) jitDataSize(size_t(*mus)(void *));
+    JS_FRIEND_API(size_t) jitDataSize(JSUsableSizeFun usf);
     
 #endif
 
     jsbytecode *main() {
         return code + mainOffset;
     }
 
-    JS_FRIEND_API(size_t) dataSize();   /* Size of all data sections */
+    /*
+     * The first dataSize() is the in-use size of all the data sections, the
+     * second is the size of the block allocated to hold all the data sections
+     * (which can be larger than the in-use size).
+     */
+    JS_FRIEND_API(size_t) dataSize();                       /* Size of all data sections */
+    JS_FRIEND_API(size_t) dataSize(JSUsableSizeFun usf);    /* Size of all data sections */
     uint32 numNotes();                  /* Number of srcnote slots in the srcnotes section */
 
     /* Script notes are allocated right after the code. */
     jssrcnote *notes() { return (jssrcnote *)(code + length); }
 
     static const uint8 INVALID_OFFSET = 0xFF;
     static bool isValidOffset(uint8 offset) { return offset != INVALID_OFFSET; }
 
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1617,18 +1617,17 @@ struct ReplaceData
     JSObject           *lambda;        /* replacement function object or null */
     JSObject           *elembase;      /* object for function(a){return b[a]} replace */
     JSLinearString     *repstr;        /* replacement string */
     const jschar       *dollar;        /* null or pointer to first $ in repstr */
     const jschar       *dollarEnd;     /* limit pointer for js_strchr_limit */
     jsint              leftIndex;      /* left context index in str->chars */
     JSSubString        dollarStr;      /* for "$$" InterpretDollar result */
     bool               calledBack;     /* record whether callback has been called */
-    InvokeSessionGuard session;        /* arguments for repeated lambda Invoke call */
-    InvokeArgsGuard    singleShot;     /* arguments for single lambda Invoke call */
+    InvokeArgsGuard    args;           /* arguments for lambda call */
     StringBuffer       sb;             /* buffer built during DoMatch */
 };
 
 static bool
 InterpretDollar(JSContext *cx, RegExpStatics *res, const jschar *dp, const jschar *ep,
                 ReplaceData &rdata, JSSubString *out, size_t *skip)
 {
     JS_ASSERT(*dp == '$');
@@ -1745,57 +1744,58 @@ FindReplaceLength(JSContext *cx, RegExpS
          * Couldn't handle this property, fall through and despecialize to the
          * general lambda case.
          */
         rdata.elembase = NULL;
     }
 
     JSObject *lambda = rdata.lambda;
     if (lambda) {
+        PreserveRegExpStatics staticsGuard(res);
+        if (!staticsGuard.init(cx))
+            return false;
+
         /*
          * In the lambda case, not only do we find the replacement string's
          * length, we compute repstr and return it via rdata for use within
          * DoReplace.  The lambda is called with arguments ($&, $1, $2, ...,
          * index, input), i.e., all the properties of a regexp match array.
          * For $&, etc., we must create string jsvals from cx->regExpStatics.
          * We grab up stack space to keep the newborn strings GC-rooted.
          */
         uintN p = res->parenCount();
         uintN argc = 1 + p + 2;
 
-        InvokeSessionGuard &session = rdata.session;
-        if (!session.started()) {
-            Value lambdav = ObjectValue(*lambda);
-            if (!session.start(cx, lambdav, UndefinedValue(), argc))
-                return false;
-        }
-
-        PreserveRegExpStatics staticsGuard(res);
-        if (!staticsGuard.init(cx))
+        InvokeArgsGuard &args = rdata.args;
+        if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, argc, &args))
             return false;
 
+        args.calleeHasBeenReset();
+        args.calleev() = ObjectValue(*lambda);
+        args.thisv() = UndefinedValue();
+
         /* Push $&, $1, $2, ... */
         uintN argi = 0;
-        if (!res->createLastMatch(cx, &session[argi++]))
+        if (!res->createLastMatch(cx, &args[argi++]))
             return false;
 
         for (size_t i = 0; i < res->parenCount(); ++i) {
-            if (!res->createParen(cx, i + 1, &session[argi++]))
+            if (!res->createParen(cx, i + 1, &args[argi++]))
                 return false;
         }
 
         /* Push match index and input string. */
-        session[argi++].setInt32(res->matchStart());
-        session[argi].setString(rdata.str);
-
-        if (!session.invoke(cx))
+        args[argi++].setInt32(res->matchStart());
+        args[argi].setString(rdata.str);
+
+        if (!Invoke(cx, args))
             return false;
 
         /* root repstr: rdata is on the stack, so scanned by conservative gc. */
-        JSString *repstr = ValueToString_TestForStringInline(cx, session.rval());
+        JSString *repstr = ValueToString_TestForStringInline(cx, args.rval());
         if (!repstr)
             return false;
         rdata.repstr = repstr->ensureLinear(cx);
         if (!rdata.repstr)
             return false;
         *sizep = rdata.repstr->length();
         return true;
     }
@@ -2069,37 +2069,36 @@ str_replace_regexp(JSContext *cx, uintN 
     return true;
 }
 
 static inline bool
 str_replace_flat_lambda(JSContext *cx, uintN argc, Value *vp, ReplaceData &rdata,
                         const FlatMatch &fm)
 {
     JS_ASSERT(fm.match() >= 0);
-    LeaveTrace(cx);
 
     JSString *matchStr = js_NewDependentString(cx, rdata.str, fm.match(), fm.patternLength());
     if (!matchStr)
         return false;
 
     /* lambda(matchStr, matchStart, textstr) */
     static const uint32 lambdaArgc = 3;
-    if (!cx->stack.pushInvokeArgs(cx, lambdaArgc, &rdata.singleShot))
+    if (!cx->stack.pushInvokeArgs(cx, lambdaArgc, &rdata.args))
         return false;
 
-    CallArgs &args = rdata.singleShot;
+    CallArgs &args = rdata.args;
     args.calleev().setObject(*rdata.lambda);
     args.thisv().setUndefined();
 
     Value *sp = args.argv();
     sp[0].setString(matchStr);
     sp[1].setInt32(fm.match());
     sp[2].setString(rdata.str);
 
-    if (!Invoke(cx, rdata.singleShot))
+    if (!Invoke(cx, rdata.args))
         return false;
 
     JSString *repstr = js_ValueToString(cx, args.rval());
     if (!repstr)
         return false;
 
     JSString *leftSide = js_NewDependentString(cx, rdata.str, 0, fm.match());
     if (!leftSide)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2493,43 +2493,53 @@ TraceMonitor::getCodeAllocStats(size_t &
     } else {
         total = 0;
         frag_size = 0;
         free_size = 0;
     }
 }
 
 size_t
-TraceMonitor::getVMAllocatorsMainSize() const
+TraceMonitor::getVMAllocatorsMainSize(JSUsableSizeFun usf) const
 {
     size_t n = 0;
     if (dataAlloc)
-        n += dataAlloc->getBytesAllocated();
+        n += dataAlloc->getBytesAllocated(usf);
     if (traceAlloc)
-        n += traceAlloc->getBytesAllocated();
+        n += traceAlloc->getBytesAllocated(usf);
     if (tempAlloc)
-        n += tempAlloc->getBytesAllocated();
+        n += tempAlloc->getBytesAllocated(usf);
     return n;
 }
 
 size_t
-TraceMonitor::getVMAllocatorsReserveSize() const
-{
-    return dataAlloc->mReserveSize +
-           traceAlloc->mReserveSize +
-           tempAlloc->mReserveSize;
+TraceMonitor::getVMAllocatorsReserveSize(JSUsableSizeFun usf) const
+{
+    size_t usable = usf(dataAlloc->mReserve) +
+                    usf(traceAlloc->mReserve) +
+                    usf(tempAlloc->mReserve);
+    return usable ? usable : dataAlloc->mReserveSize +
+                             traceAlloc->mReserveSize +
+                             tempAlloc->mReserveSize;
 }
 
 size_t
-TraceMonitor::getTraceMonitorSize() const
-{
-    return sizeof(TraceMonitor) +           // TraceMonitor
-           sizeof(*storage) +               // TraceNativeStorage
-           recordAttempts->tableSize() +    // RecordAttemptMap
-           loopProfiles->tableSize();       // LoopProfileMap
+TraceMonitor::getTraceMonitorSize(JSUsableSizeFun usf) const
+{
+    /*
+     * Measures: TraceMonitor, TraceNativeStorage, RecordAttemptMap,
+     * LoopProfileMap.  |countMe| is true for both sizeOf() calls because the
+     * two HashMaps are not inline in TraceMonitor.
+     */
+    size_t usableTM  = usf((void *)this);
+    size_t usableTNS = usf(storage);
+    return (usableTM  ? usableTM  : sizeof(*this)) +
+           (usableTNS ? usableTNS : sizeof(*storage)) +
+           recordAttempts->sizeOf(usf, /* countMe */true) +
+           loopProfiles->sizeOf(usf, /* countMe */true);
 }
 
 /*
  * This function destroys the recorder after a successful recording, possibly
  * starting a suspended outer recorder.
  */
 AbortableRecordingStatus
 TraceRecorder::finishSuccessfully()
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -60,16 +60,17 @@
 #include "jsstaticcheck.h"
 #include "jsbit.h"
 #include "jsvector.h"
 #include "jstypedarray.h"
 #include "jsutil.h"
 
 #include "vm/GlobalObject.h"
 
+#include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jstypedarrayinlines.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 
@@ -272,44 +273,73 @@ ArrayBuffer::obj_lookupProperty(JSContex
         *propp = NULL;
         return true;
     }
 
     return proto->lookupProperty(cx, id, objp, propp);
 }
 
 JSBool
+ArrayBuffer::obj_lookupElement(JSContext *cx, JSObject *obj, uint32 index,
+                               JSObject **objp, JSProperty **propp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_lookupProperty(cx, obj, id, objp, propp);
+}
+
+JSBool
 ArrayBuffer::obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
         return true;
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_DefineProperty(cx, delegate, id, v, getter, setter, attrs);
 }
 
 JSBool
+ArrayBuffer::obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
+                   PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+}
+
+JSBool
 ArrayBuffer::obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     obj = getArrayBuffer(obj);
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         vp->setInt32(obj->arrayBufferByteLength());
         return true;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_GetProperty(cx, delegate, receiver, id, vp);
 }
 
 JSBool
+ArrayBuffer::obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_getProperty(cx, obj, receiver, id, vp);
+}
+
+JSBool
 ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
         return true;
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.protoAtom)) {
         // setting __proto__ = null
         // effectively removes the prototype chain.
@@ -354,59 +384,95 @@ ArrayBuffer::obj_setProperty(JSContext *
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
 
     return js_SetPropertyHelper(cx, delegate, id, 0, vp, strict);
 }
 
 JSBool
+ArrayBuffer::obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_setProperty(cx, obj, id, vp, strict);
+}
+
+JSBool
 ArrayBuffer::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         *attrsp = JSPROP_PERMANENT | JSPROP_READONLY;
         return true;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_GetAttributes(cx, delegate, id, attrsp);
 }
 
 JSBool
+ArrayBuffer::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_getAttributes(cx, obj, id, attrsp);
+}
+
+JSBool
 ArrayBuffer::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_SET_ARRAY_ATTRS);
         return false;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_SetAttributes(cx, delegate, id, attrsp);
 }
 
 JSBool
+ArrayBuffer::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_setAttributes(cx, obj, id, attrsp);
+}
+
+JSBool
 ArrayBuffer::obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         rval->setBoolean(false);
         return true;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
         return false;
     return js_DeleteProperty(cx, delegate, id, rval, strict);
 }
 
 JSBool
+ArrayBuffer::obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_deleteElement(cx, obj, index, rval, strict);
+}
+
+JSBool
 ArrayBuffer::obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
               Value *statep, jsid *idp)
 {
     statep->setNull();
     return true;
 }
 
 JSType
@@ -534,32 +600,60 @@ TypedArray::obj_lookupProperty(JSContext
         *propp = NULL;
         return true;
     }
 
     return proto->lookupProperty(cx, id, objp, propp);
 }
 
 JSBool
+TypedArray::obj_lookupElement(JSContext *cx, JSObject *obj, uint32 index,
+                              JSObject **objp, JSProperty **propp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_lookupProperty(cx, obj, id, objp, propp);
+}
+
+JSBool
 TypedArray::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     *attrsp = (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
               ? JSPROP_PERMANENT | JSPROP_READONLY
               : JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 JSBool
+TypedArray::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_getAttributes(cx, obj, id, attrsp);
+}
+
+JSBool
 TypedArray::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                          JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
+JSBool
+TypedArray::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return obj_setAttributes(cx, obj, id, attrsp);
+}
+
 /* static */ int
 TypedArray::lengthOffset()
 {
     return JSObject::getFixedSlotOffset(FIELD_LENGTH) + offsetof(jsval_layout, s.payload);
 }
 
 /* static */ int
 TypedArray::dataOffset()
@@ -773,16 +867,25 @@ class TypedArrayTemplate
                 }
             }
         }
 
         return true;
     }
 
     static JSBool
+    obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp)
+    {
+        jsid id;
+        if (!IndexToId(cx, index, &id))
+            return false;
+        return obj_getProperty(cx, obj, receiver, id, vp);
+    }
+
+    static JSBool
     obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
     {
         JSObject *tarray = getTypedArray(obj);
         JS_ASSERT(tarray);
 
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
             vp->setNumber(getLength(tarray));
             return true;
@@ -850,27 +953,46 @@ class TypedArrayTemplate
             int32 n = js_DoubleToECMAInt32(d);
             setIndex(tarray, index, NativeType(n));
         }
 
         return true;
     }
 
     static JSBool
+    obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
+    {
+        jsid id;
+        if (!IndexToId(cx, index, &id))
+            return false;
+        return obj_setProperty(cx, obj, id, vp, strict);
+    }
+
+    static JSBool
     obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
             return true;
 
         Value tmp = *v;
         return obj_setProperty(cx, obj, id, &tmp, false);
     }
 
     static JSBool
+    obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
+                       PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+    {
+        jsid id;
+        if (!IndexToId(cx, index, &id))
+            return false;
+        return obj_defineProperty(cx, obj, id, v, getter, setter, attrs);
+    }
+
+    static JSBool
     obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
             rval->setBoolean(false);
             return true;
         }
 
         JSObject *tarray = TypedArray::getTypedArray(obj);
@@ -881,16 +1003,25 @@ class TypedArrayTemplate
             return true;
         }
 
         rval->setBoolean(true);
         return true;
     }
 
     static JSBool
+    obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
+    {
+        jsid id;
+        if (!IndexToId(cx, index, &id))
+            return false;
+        return obj_deleteProperty(cx, obj, id, rval, strict);
+    }
+
+    static JSBool
     obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                   Value *statep, jsid *idp)
     {
         JSObject *tarray = getTypedArray(obj);
         JS_ASSERT(tarray);
 
         /*
          * Iteration is "length" (if JSENUMERATE_INIT_ALL), then [0, length).
@@ -1713,22 +1844,29 @@ Class js::ArrayBufferClass = {
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* xdrObject   */
     NULL,           /* hasInstance */
     ArrayBuffer::obj_trace,
     JS_NULL_CLASS_EXT,
     {
         ArrayBuffer::obj_lookupProperty,
+        ArrayBuffer::obj_lookupElement,
         ArrayBuffer::obj_defineProperty,
+        ArrayBuffer::obj_defineElement,
         ArrayBuffer::obj_getProperty,
+        ArrayBuffer::obj_getElement,
         ArrayBuffer::obj_setProperty,
+        ArrayBuffer::obj_setElement,
         ArrayBuffer::obj_getAttributes,
+        ArrayBuffer::obj_getElementAttributes,
         ArrayBuffer::obj_setAttributes,
+        ArrayBuffer::obj_setElementAttributes,
         ArrayBuffer::obj_deleteProperty,
+        ArrayBuffer::obj_deleteElement,
         ArrayBuffer::obj_enumerate,
         ArrayBuffer::obj_typeOf,
         NULL,       /* thisObject      */
         NULL,       /* clear           */
     }
 };
 
 JSPropertySpec ArrayBuffer::jsprops[] = {
@@ -1804,22 +1942,29 @@ JSFunctionSpec _typedArray::jsfuncs[] = 
     NULL,           /* call        */                                          \
     NULL,           /* construct   */                                          \
     NULL,           /* xdrObject   */                                          \
     NULL,           /* hasInstance */                                          \
     _typedArray::obj_trace,           /* trace       */                                          \
     JS_NULL_CLASS_EXT,                                                         \
     {                                                                          \
         _typedArray::obj_lookupProperty,                                       \
+        _typedArray::obj_lookupElement,                                        \
         _typedArray::obj_defineProperty,                                       \
+        _typedArray::obj_defineElement,                                        \
         _typedArray::obj_getProperty,                                          \
+        _typedArray::obj_getElement,                                           \
         _typedArray::obj_setProperty,                                          \
+        _typedArray::obj_setElement,                                           \
         _typedArray::obj_getAttributes,                                        \
+        _typedArray::obj_getElementAttributes,                                 \
         _typedArray::obj_setAttributes,                                        \
+        _typedArray::obj_setElementAttributes,                                 \
         _typedArray::obj_deleteProperty,                                       \
+        _typedArray::obj_deleteElement,                                        \
         _typedArray::obj_enumerate,                                            \
         _typedArray::obj_typeOf,                                               \
         NULL,       /* thisObject      */                                      \
         NULL,       /* clear           */                                      \
     }                                                                          \
 }
 
 template<class ArrayType>
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -74,35 +74,58 @@ struct JS_FRIEND_API(ArrayBuffer) {
     static void
     obj_trace(JSTracer *trc, JSObject *obj);
 
     static JSBool
     obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                        JSObject **objp, JSProperty **propp);
 
     static JSBool
+    obj_lookupElement(JSContext *cx, JSObject *obj, uint32 index,
+                      JSObject **objp, JSProperty **propp);
+
+    static JSBool
     obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs);
 
     static JSBool
+    obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
+                      PropertyOp getter, StrictPropertyOp setter, uintN attrs);
+
+    static JSBool
     obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
 
     static JSBool
+    obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp);
+
+    static JSBool
     obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 
     static JSBool
+    obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
+
+    static JSBool
     obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
     static JSBool
+    obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
+
+    static JSBool
     obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
     static JSBool
+    obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
+
+    static JSBool
     obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict);
 
     static JSBool
+    obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict);
+
+    static JSBool
     obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                   Value *statep, jsid *idp);
 
     static JSType
     obj_typeOf(JSContext *cx, JSObject *obj);
 
     static JSObject *
     getArrayBuffer(JSObject *obj);
@@ -159,20 +182,24 @@ struct JS_FRIEND_API(TypedArray) {
 
     static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
 
     static JSBool obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                                      JSObject **objp, JSProperty **propp);
+    static JSBool obj_lookupElement(JSContext *cx, JSObject *obj, uint32 index,
+                                    JSObject **objp, JSProperty **propp);
 
     static JSBool obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 
     static JSBool obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+    static JSBool obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 
     static JSUint32 getLength(JSObject *obj);
     static JSUint32 getByteOffset(JSObject *obj);
     static JSUint32 getByteLength(JSObject *obj);
     static JSUint32 getType(JSObject *obj);
     static JSObject * getBuffer(JSObject *obj);
     static void * getDataOffset(JSObject *obj);
 
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -262,16 +262,23 @@ static JS_INLINE void* js_realloc(void* 
     return realloc(p, bytes);
 }
 
 static JS_INLINE void js_free(void* p) {
     free(p);
 }
 #endif/* JS_USE_CUSTOM_ALLOCATOR */
 
+/* 
+ * This signature is for malloc_usable_size-like functions used to measure
+ * memory usage.  A return value of zero indicates that the size is unknown,
+ * and so a fall-back computation should be done for the size.
+ */
+typedef size_t(*JSUsableSizeFun)(void *p);
+
 JS_END_EXTERN_C
 
 
 
 #ifdef __cplusplus
 
 /* 
  * User guide to memory management within SpiderMonkey:
--- a/js/src/jsvalue.h
+++ b/js/src/jsvalue.h
@@ -944,28 +944,42 @@ typedef JSBool
 (* CheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
                   Value *vp);
 typedef JSBool
 (* EqualityOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
 typedef JSBool
 (* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                  PropertyOp getter, StrictPropertyOp setter, uintN attrs);
 typedef JSBool
+(* DefineElementOp)(JSContext *cx, JSObject *obj, uint32 index, const Value *value,
+                    PropertyOp getter, StrictPropertyOp setter, uintN attrs);
+typedef JSBool
 (* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
 typedef JSBool
+(* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp);
+typedef JSBool
 (* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 typedef JSBool
+(* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
+typedef JSBool
 (* DeleteIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
 typedef JSBool
+(* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict);
+typedef JSBool
 (* CallOp)(JSContext *cx, uintN argc, Value *vp);
 typedef JSBool
 (* LookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
                  JSProperty **propp);
 typedef JSBool
+(* LookupElementOp)(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
+                    JSProperty **propp);
+typedef JSBool
 (* AttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
+typedef JSBool
+(* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp);
 typedef JSType
 (* TypeOfOp)(JSContext *cx, JSObject *obj);
 typedef JSObject *
 (* ObjectOp)(JSContext *cx, JSObject *obj);
 typedef void
 (* FinalizeOp)(JSContext *cx, JSObject *obj);
 
 class AutoIdVector;
@@ -1053,30 +1067,40 @@ struct ClassExtension {
      */
     bool                isWrappedNative;
 };
 
 #define JS_NULL_CLASS_EXT   {NULL,NULL,NULL,NULL,NULL,false}
 
 struct ObjectOps {
     js::LookupPropOp        lookupProperty;
+    js::LookupElementOp     lookupElement;
     js::DefinePropOp        defineProperty;
+    js::DefineElementOp     defineElement;
     js::PropertyIdOp        getProperty;
+    js::ElementIdOp         getElement;
     js::StrictPropertyIdOp  setProperty;
+    js::StrictElementIdOp   setElement;
     js::AttributesOp        getAttributes;
+    js::ElementAttributesOp getElementAttributes;
     js::AttributesOp        setAttributes;
+    js::ElementAttributesOp setElementAttributes;
     js::DeleteIdOp          deleteProperty;
+    js::DeleteElementOp     deleteElement;
+
     js::NewEnumerateOp      enumerate;
     js::TypeOfOp            typeOf;
     js::FixOp               fix;
     js::ObjectOp            thisObject;
     js::FinalizeOp          clear;
 };
 
-#define JS_NULL_OBJECT_OPS  {NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL}
+#define JS_NULL_OBJECT_OPS                                                    \
+    {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,   \
+     NULL,NULL,NULL,NULL,NULL}
 
 struct Class {
     JS_CLASS_MEMBERS;
     ClassExtension      ext;
     ObjectOps           ops;
     uint8               pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
                             sizeof(ClassExtension) - sizeof(ObjectOps)];
 
--- a/js/src/jsweakmap.h
+++ b/js/src/jsweakmap.h
@@ -94,17 +94,17 @@ namespace js {
 //        became marked.
 //
 //        To ensure that the WeakMap's behavior isn't visibly affected by
 //        garbage collection, this should leave k unmarked only when no key
 //        matching k could ever be produced after this GC cycle completes ---
 //        removing entries whose keys this function leaves unmarked should never
 //        make future lookups fail.
 //
-//        A typical definition of markIteratively would be:
+//        A typical definition of markEntryIfLive would be:
 //
 //          if (keyMarked(k) && !valueMarked(v)) {
 //              markObject(*v, "WeakMap entry value");
 //              return true;
 //          }
 //          return false;
 //
 //        This meets the above constraint when, for example, Key is JSObject *:
@@ -112,21 +112,22 @@ namespace js {
 //        and thus can't be supplied as a key.
 //
 //        Note that this may mark entries where keyMarked(k) is not initially
 //        true. For example, you could have a table whose keys match when the
 //        values of one of their properties are equal: k1.x === k2.x. An entry
 //        in such a table could be live even when its key is not marked. The
 //        markEntryIfLive function for such a table would generally mark both k and v.
 //
-//     void markEntry(Key &k, Value &v)
-//        Mark the table entry's key and value, k and v, as reachable by the
-//        collector. WeakMap uses this function for non-marking tracers: other
-//        code using the GC heap tracing functions to map the heap for some
-//        purpose or other.
+//     void markEntry(Value &v)
+//        Mark the table entry's value v as reachable by the collector. WeakMap
+//        uses this function for non-marking tracers: other code using the GC
+//        heap tracing functions to map the heap for some purpose or other.
+//        This provides a conservative approximation of the true reachability
+//        relation of the heap graph.
 //
 //   If omitted, the MarkPolicy parameter defaults to js::DefaultMarkPolicy<Key,
 //   Value>, a policy template with the obvious definitions for some typical
 //   SpiderMonkey type combinations.
 
 // A policy template holding default marking algorithms for common type combinations. This
 // provides default types for WeakMap's MarkPolicy template parameter.
 template <class Key, class Value> class DefaultMarkPolicy;
@@ -192,17 +193,17 @@ class WeakMap : public HashMap<Key, Valu
   public:
     explicit WeakMap(JSRuntime *rt) : Base(rt) { }
     explicit WeakMap(JSContext *cx) : Base(cx) { }
 
   private:
     void nonMarkingTrace(JSTracer *tracer) {
         MarkPolicy t(tracer);
         for (Range r = Base::all(); !r.empty(); r.popFront())
-            t.markEntry(r.front().key, r.front().value);
+            t.markEntry(r.front().value);
     }
 
     bool markIteratively(JSTracer *tracer) {
         MarkPolicy t(tracer);
         bool markedAny = false;
         for (Range r = Base::all(); !r.empty(); r.popFront()) {
             /* If the entry is live, ensure its key and value are marked. */
             if (t.markEntryIfLive(r.front().key, r.front().value)) {
@@ -276,18 +277,17 @@ class DefaultMarkPolicy<JSObject *, Valu
         if (keyMarked(k))
             return markUnmarkedValue(v);
         if (!overrideKeyMarking(k))
             return false;
         js::gc::MarkObject(tracer, *k, "WeakMap entry wrapper key");
         markUnmarkedValue(v);
         return true;
     }
-    void markEntry(JSObject *k, const Value &v) {
-        js::gc::MarkObject(tracer, *k, "WeakMap entry key");
+    void markEntry(const Value &v) {
         js::gc::MarkValue(tracer, v, "WeakMap entry value");
     }
 };
 
 template <>
 class DefaultMarkPolicy<JSObject *, JSObject *> {
   protected:
     JSTracer *tracer;
@@ -297,18 +297,17 @@ class DefaultMarkPolicy<JSObject *, JSOb
     bool valueMarked(JSObject *v) { return !IsAboutToBeFinalized(tracer->context, v); }
     bool markEntryIfLive(JSObject *k, JSObject *v) {
         if (keyMarked(k) && !valueMarked(v)) {
             js::gc::MarkObject(tracer, *v, "WeakMap entry value");
             return true;
         }
         return false;
     }
-    void markEntry(JSObject *k, JSObject *v) {
-        js::gc::MarkObject(tracer, *k, "WeakMap entry key");
+    void markEntry(JSObject *v) {
         js::gc::MarkObject(tracer, *v, "WeakMap entry value");
     }
 };
 
 // A MarkPolicy for WeakMaps whose keys and values may be objects in arbitrary
 // compartments within a runtime.
 //
 // With the current GC, the implementation turns out to be identical to the
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -4729,73 +4729,129 @@ xml_lookupProperty(JSContext *cx, JSObje
 
         *objp = obj;
         *propp = (JSProperty *) shape;
     }
     return JS_TRUE;
 }
 
 static JSBool
+xml_lookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
+                  JSProperty **propp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return xml_lookupProperty(cx, obj, id, objp, propp);
+}
+
+static JSBool
 xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                    PropertyOp getter, StrictPropertyOp setter, uintN attrs)
 {
     if (IsFunctionObject(*v) || getter || setter ||
         (attrs & JSPROP_ENUMERATE) == 0 ||
         (attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) {
         return js_DefineProperty(cx, obj, id, v, getter, setter, attrs);
     }
 
     jsval tmp = Jsvalify(*v);
     return PutProperty(cx, obj, id, false, &tmp);
 }
 
 static JSBool
+xml_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v,
+                  PropertyOp getter, StrictPropertyOp setter, uintN attrs)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return xml_defineProperty(cx, obj, id, v, getter, setter, attrs);
+}
+
+static JSBool
 xml_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     if (JSID_IS_DEFAULT_XML_NAMESPACE(id)) {
         vp->setUndefined();
         return JS_TRUE;
     }
 
     return GetProperty(cx, obj, id, Jsvalify(vp));
 }
 
 static JSBool
+xml_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32 index, Value *vp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return xml_getProperty(cx, obj, receiver, id, vp);
+}
+
+static JSBool
 xml_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
 {
     return PutProperty(cx, obj, id, strict, Jsvalify(vp));
 }
 
 static JSBool
+xml_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return xml_setProperty(cx, obj, id, vp, strict);
+}
+
+static JSBool
 xml_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     JSBool found;
     if (!HasProperty(cx, obj, IdToJsval(id), &found))
         return false;
 
     *attrsp = found ? JSPROP_ENUMERATE : 0;
     return JS_TRUE;
 }
 
 static JSBool
+xml_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return xml_getAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 xml_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     JSBool found;
     if (!HasProperty(cx, obj, IdToJsval(id), &found))
         return false;
 
     if (found) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_SET_XML_ATTRS);
         return false;
     }
     return true;
 }
 
 static JSBool
+xml_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return xml_setAttributes(cx, obj, id, attrsp);
+}
+
+static JSBool
 xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     JSXML *xml;
     jsval idval;
     uint32 index;
     JSObject *nameqn;
     jsid funid;
 
@@ -4830,16 +4886,25 @@ xml_deleteProperty(JSContext *cx, JSObje
      */
     if (!obj->nativeEmpty() && !js_DeleteProperty(cx, obj, id, rval, false))
         return false;
 
     rval->setBoolean(true);
     return true;
 }
 
+static JSBool
+xml_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict)
+{
+    jsid id;
+    if (!IndexToId(cx, index, &id))
+        return false;
+    return xml_deleteProperty(cx, obj, id, rval, strict);
+}
+
 static JSString *
 xml_toString_helper(JSContext *cx, JSXML *xml);
 
 JSBool
 xml_convert(JSContext *cx, JSObject *obj, JSType hint, Value *rval)
 {
     JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
     JS_ASSERT(obj->isXML());
@@ -5129,22 +5194,29 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
     NULL,                 /* call        */
     NULL,                 /* construct   */
     NULL,                 /* xdrObject   */
     xml_hasInstance,
     xml_trace,
     JS_NULL_CLASS_EXT,
     {
         xml_lookupProperty,
+        xml_lookupElement,
         xml_defineProperty,
+        xml_defineElement,
         xml_getProperty,
+        xml_getElement,
         xml_setProperty,
+        xml_setElement,
         xml_getAttributes,
+        xml_getElementAttributes,
         xml_setAttributes,
+        xml_setElementAttributes,
         xml_deleteProperty,
+        xml_deleteElement,
         xml_enumerate,
         xml_typeOf,
         xml_fix,
         NULL,       /* thisObject     */
         xml_clear
     }
 };
 
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -1243,17 +1243,17 @@ static const JSC::MacroAssembler::Regist
      * to result and filling it in according to templateObject. Returns a jump
      * taken if a free thing was not retrieved.
      */
     Jump getNewObject(JSContext *cx, RegisterID result, JSObject *templateObject)
     {
         gc::AllocKind allocKind = templateObject->getAllocKind();
 
         JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
-        size_t thingSize = gc::Arena::thingSize(allocKind);
+        int thingSize = (int)gc::Arena::thingSize(allocKind);
 
         JS_ASSERT(cx->typeInferenceEnabled());
         JS_ASSERT(!templateObject->hasSlotsArray());
 
 #ifdef JS_GC_ZEAL
         if (cx->runtime->needZealousGC())
             return jump();
 #endif
@@ -1284,17 +1284,17 @@ static const JSC::MacroAssembler::Regist
         /*
          * Write out the slots pointer before readjusting the result register,
          * as for dense arrays we will need to get the address of the fixed
          * slots first.
          */
         if (templateObject->isDenseArray()) {
             JS_ASSERT(!templateObject->initializedLength);
             addPtr(Imm32(-thingSize + sizeof(JSObject)), result);
-            storePtr(result, Address(result, -sizeof(JSObject) + JSObject::offsetOfSlots()));
+            storePtr(result, Address(result, -(int)sizeof(JSObject) + JSObject::offsetOfSlots()));
             addPtr(Imm32(-(int)sizeof(JSObject)), result);
         } else {
             JS_ASSERT(!templateObject->newType);
             addPtr(Imm32(-thingSize), result);
             storePtr(ImmPtr(NULL), Address(result, JSObject::offsetOfSlots()));
         }
 
         storePtr(ImmPtr(templateObject->lastProp), Address(result, offsetof(JSObject, lastProp)));
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -1139,31 +1139,31 @@ mjit::JITScript::~JITScript()
         repatch.repatch(ic->funGuard, NULL);
         repatch.relink(ic->funJump, ic->slowPathStart);
         ic->purgeGuardedObject();
     }
 #endif
 }
 
 size_t
-JSScript::jitDataSize(size_t(*mus)(void *))
+JSScript::jitDataSize(JSUsableSizeFun usf)
 {
     size_t n = 0;
     if (jitNormal)
-        n += jitNormal->scriptDataSize(mus); 
+        n += jitNormal->scriptDataSize(usf); 
     if (jitCtor)
-        n += jitCtor->scriptDataSize(mus); 
+        n += jitCtor->scriptDataSize(usf); 
     return n;
 }
 
 /* Please keep in sync with Compiler::finishThisUp! */
 size_t
-mjit::JITScript::scriptDataSize(size_t(*mus)(void *))
+mjit::JITScript::scriptDataSize(JSUsableSizeFun usf)
 {
-    size_t usable = mus ? mus(this) : 0;
+    size_t usable = usf ? usf(this) : 0;
     return usable ? usable :
         sizeof(JITScript) +
         sizeof(NativeMapEntry) * nNmapPairs +
         sizeof(InlineFrame) * nInlineFrames +
         sizeof(CallSite) * nCallSites +
         sizeof(JSObject *) * nRootedObjects +
 #if defined JS_MONOIC
         sizeof(ic::GetGlobalNameIC) * nGetGlobalNames +
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -667,17 +667,18 @@ struct JITScript {
 
     void nukeScriptDependentICs();
     void sweepCallICs(JSContext *cx, bool purgeAll);
     void purgeMICs();
     void purgePICs();
 
     void trace(JSTracer *trc);
 
-    size_t scriptDataSize(size_t(*mus)(void *));
+    /* |usf| can be NULL here, in which case the fallback size computation will be used. */
+    size_t scriptDataSize(JSUsableSizeFun usf);
 
     jsbytecode *nativeToPC(void *returnAddress, CallSite **pinline) const;
 
   private:
     /* Helpers used to navigate the variable-length sections. */
     char *commonSectionLimit() const;
     char *monoICSectionsLimit() const;
     char *polyICSectionsLimit() const;
--- a/js/src/nanojit-import-rev
+++ b/js/src/nanojit-import-rev
@@ -1,1 +1,1 @@
-55c10227eece4a02b593997eda3dedef39af7beb
+d66d2e24ef1688e3b6d47e824354f5a78ac22487
--- a/js/src/nanojit/Allocator.cpp
+++ b/js/src/nanojit/Allocator.cpp
@@ -95,21 +95,22 @@ namespace nanojit
             current_limit = (char*)mem + chunkbytes;
             return true;
         } else {
             NanoAssert(fallible);
             return false;
         }
     }
 
-    size_t Allocator::getBytesAllocated()
+    size_t Allocator::getBytesAllocated(size_t(*my_malloc_usable_size)(void *))
     {
         size_t n = 0;
         Chunk *c = current_chunk;
         while (c) {
-            n += c->size;
+            size_t usable = my_malloc_usable_size(c);
+            n += usable ? usable : c->size;
             c = c->prev;
         }
         return n;
     }
 }
 
 #endif // FEATURE_NANOJIT
--- a/js/src/nanojit/Allocator.h
+++ b/js/src/nanojit/Allocator.h
@@ -85,17 +85,17 @@ namespace nanojit
                 p = current_top;
                 current_top += nbytes;
             } else {
                 p = allocSlow(nbytes, /* fallible = */true);
             }
             return p;
         }
 
-        size_t getBytesAllocated();
+        size_t getBytesAllocated(size_t(*my_malloc_usable_size)(void *));
 
     protected:
         void* allocSlow(size_t nbytes, bool fallible = false);
         bool fill(size_t minbytes, bool fallible);
 
         class Chunk {
         public:
             Chunk* prev;
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4064,34 +4064,44 @@ MJitCodeStats(JSContext *cx, uintN argc,
 #else
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 #endif
     return true;
 }
 
 #ifdef JS_METHODJIT
 
+static size_t
+zero_usable_size(void *p)
+{
+    return 0;
+}
+
 static void
 SumJitDataSizeCallback(JSContext *cx, void *data, void *thing,
                        JSGCTraceKind traceKind, size_t thingSize)
 {
     size_t *sump = static_cast<size_t *>(data);
     JS_ASSERT(traceKind == JSTRACE_SCRIPT);
     JSScript *script = static_cast<JSScript *>(thing);
-    *sump += script->jitDataSize(NULL);
+    /*
+     * Passing in zero_usable_size causes jitDataSize to fall back to its
+     * secondary size computation.
+     */
+    *sump += script->jitDataSize(zero_usable_size);
 }
 
 #endif
 
 JSBool
 MJitDataStats(JSContext *cx, uintN argc, jsval *vp)
 {
 #ifdef JS_METHODJIT
     size_t n = 0;
-    IterateCells(cx, NULL, gc::FINALIZE_TYPE_OBJECT, &n, SumJitDataSizeCallback);
+    IterateCells(cx, NULL, gc::FINALIZE_SCRIPT, &n, SumJitDataSizeCallback);
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
 #else
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 #endif
     return true;
 }
 
 JSBool
--- a/js/src/tests/js1_8/genexps/jstests.list
+++ b/js/src/tests/js1_8/genexps/jstests.list
@@ -7,8 +7,9 @@ script regress-380237-01.js
 script regress-380237-02.js
 script regress-380237-03.js
 skip script regress-380237-04.js # obsolete test, need to remove minor failures to reenable.
 script regress-384991.js
 script regress-634472.js
 script regress-665286.js
 script regress-666852.js
 script regress-667131.js
+script regress-683738.js
new file mode 100644
--- /dev/null
+++ b/js/src/tests/js1_8/genexps/regress-683738.js
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is JavaScript Engine testing utilities.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Dave Herman
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 683738;
+var summary = 'return with argument and lazy generator detection';
+var actual = '';
+var expect = '';
+
+//-----------------------------------------------------------------------------
+test();
+//-----------------------------------------------------------------------------
+
+function test()
+{
+  enterFunc ('test');
+  printBugNumber(BUGNUMBER);
+  printStatus (summary);
+
+  expect = "generator function foo returns a value";
+  try
+  {
+    actual = 'No Error';
+    eval("function foo(x) { if (x) { return this; } else { yield 3; } }");
+  }
+  catch(ex)
+  {
+    actual = ex.message;
+  }
+  reportCompare(expect, actual, summary + ": 1");
+
+  expect = "generator function foo returns a value";
+  try
+  {
+    actual = 'No Error';
+    eval("function foo(x) { if (x) { yield 3; } else { return this; } }");
+  }
+  catch(ex)
+  {
+    actual = ex.message;
+  }
+  reportCompare(expect, actual, summary + ": 2");
+
+  expect = "generator function foo returns a value";
+  try
+  {
+    actual = 'No Error';
+    eval("function foo(x) { if (x) { return this; } else { (yield 3); } }");
+  }
+  catch(ex)
+  {
+    actual = ex.message;
+  }
+  reportCompare(expect, actual, summary + ": 3");
+
+  expect = "generator function foo returns a value";
+  try
+  {
+    actual = 'No Error';
+    eval("function foo(x) { if (x) { (yield 3); } else { return this; } }");
+  }
+  catch(ex)
+  {
+    actual = ex.message;
+  }
+  reportCompare(expect, actual, summary + ": 4");
+
+}
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -398,17 +398,17 @@ class Debugger {
   private:
     /* Prohibit copying. */
     Debugger(const Debugger &);
     Debugger & operator=(const Debugger &);
 };
 
 class BreakpointSite {
     friend class js::Breakpoint;
-    friend class ::JSCompartment;
+    friend struct ::JSCompartment;
     friend class js::Debugger;
 
   public:
     JSScript * const script;
     jsbytecode * const pc;
     const JSOp realOpcode;
 
   private:
@@ -455,17 +455,17 @@ class BreakpointSite {
  * Debugger::hasAnyLiveHooks to check for rule 1.
  *
  * Nothing else causes a breakpoint to be retained, so if its script or
  * debugger is collected, the breakpoint is destroyed during GC sweep phase,
  * even if the debugger compartment isn't being GC'd. This is implemented in
  * JSCompartment::sweepBreakpoints.
  */
 class Breakpoint {
-    friend class ::JSCompartment;
+    friend struct ::JSCompartment;
     friend class js::Debugger;
 
   public:
     Debugger * const debugger;
     BreakpointSite * const site;
   private:
     JSObject *handler;
     JSCList debuggerLinks;
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -639,16 +639,17 @@ ContextStack::popSegment()
 
     if (!seg_)
         cx_->maybeMigrateVersionOverride();
 }
 
 bool
 ContextStack::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *iag)
 {
+    LeaveTrace(cx);
     JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
 
     uintN nvars = 2 + argc;
     Value *firstUnused = ensureOnTop(cx, REPORT_ERROR, nvars, CAN_EXTEND, &iag->pushedSeg_);
     if (!firstUnused)
         return false;
 
     ImplicitCast<CallArgs>(*iag) = CallArgsFromVp(argc, firstUnused);
@@ -1014,23 +1015,16 @@ StackIter::settleOnNewState()
          */
         if (containsFrame && (!containsCall || (Value *)fp_ >= calls_->argv())) {
             /* Nobody wants to see dummy frames. */
             if (fp_->isDummyFrame()) {
                 popFrame();
                 continue;
             }
 
-            /* Censor pushed-but-not-active frames from InvokeSessionGuard. */
-            if (containsCall && !calls_->active() && fp_->hasArgs() &&
-                calls_->argv() == fp_->actualArgs()) {
-                popFrame();
-                continue;
-            }
-
             /*
              * As an optimization, there is no CallArgsList element pushed for
              * natives called directly by a script (compiled or interpreted).
              * We catch these by inspecting the bytecode and stack. This check
              * relies on the property that, at a call opcode,
              *
              *   regs.sp == vp + 2 + argc
              *
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -78,50 +78,55 @@ void
 JSLinearString::mark(JSTracer *)
 {
     JSLinearString *str = this;
     while (!str->isStaticAtom() && str->markIfUnmarked() && str->isDependent())
         str = str->asDependent().base();
 }
 
 size_t
-JSString::charsHeapSize()
+JSString::charsHeapSize(JSUsableSizeFun usf)
 {
     /* JSRope: do nothing, we'll count all children chars when we hit the leaf strings. */
     if (isRope())
         return 0;
 
     JS_ASSERT(isLinear());
 
     /* JSDependentString: do nothing, we'll count the chars when we hit the base string. */
     if (isDependent())
         return 0;
 
     JS_ASSERT(isFlat());
 
     /* JSExtensibleString: count the full capacity, not just the used space. */
-    if (isExtensible())
-        return asExtensible().capacity() * sizeof(jschar);
+    if (isExtensible()) {
+        JSExtensibleString &extensible = asExtensible();
+        size_t usable = usf((void *)extensible.chars());
+        return usable ? usable : asExtensible().capacity() * sizeof(jschar);
+    }
 
     JS_ASSERT(isFixed());
 
     /* JSExternalString: don't count, the chars could be stored anywhere. */
     if (isExternal())
         return 0;
 
     /* JSInlineString, JSShortString, JSInlineAtom, JSShortAtom: the chars are inline. */
     if (isInline())
         return 0;
 
     /* JSStaticAtom: the chars are static and so not part of the heap. */
     if (isStaticAtom())
         return 0;
 
     /* JSAtom, JSFixedString: count the chars. */
-    return length() * sizeof(jschar);
+    JSFixedString &fixed = asFixed();
+    size_t usable = usf((void *)fixed.chars());
+    return usable ? usable : length() * sizeof(jschar);
 }
 
 static JS_ALWAYS_INLINE bool
 AllocChars(JSContext *maybecx, size_t length, jschar **chars, size_t *capacity)
 {
     /*
      * String length doesn't include the null char, so include it here before
      * doubling. Adding the null char after doubling would interact poorly with
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -406,17 +406,17 @@ class JSString : public js::gc::Cell
     }
 
     /* Only called by the GC for strings with the FINALIZE_STRING kind. */
 
     inline void finalize(JSContext *cx);
 
     /* Gets the number of bytes that the chars take on the heap. */
 
-    JS_FRIEND_API(size_t) charsHeapSize();
+    JS_FRIEND_API(size_t) charsHeapSize(JSUsableSizeFun usf);
 
     /* Offsets for direct field from jit code. */
 
     static size_t offsetOfLengthAndFlags() {
         return offsetof(JSString, d.lengthAndFlags);
     }
 
     static size_t offsetOfChars() {
--- a/js/src/xpconnect/idl/nsIXPCScriptable.idl
+++ b/js/src/xpconnect/idl/nsIXPCScriptable.idl
@@ -103,16 +103,17 @@ interface nsIXPCScriptable : nsISupports
     const PRUint32 DONT_ASK_INSTANCE_FOR_SCRIPTABLE = 1 << 22;
     const PRUint32 CLASSINFO_INTERFACES_ONLY        = 1 << 23;
     const PRUint32 ALLOW_PROP_MODS_DURING_RESOLVE   = 1 << 24;
     const PRUint32 ALLOW_PROP_MODS_TO_PROTOTYPE     = 1 << 25;
     const PRUint32 DONT_SHARE_PROTOTYPE             = 1 << 26;
     const PRUint32 DONT_REFLECT_INTERFACE_NAMES     = 1 << 27;
     const PRUint32 WANT_EQUALITY                    = 1 << 28;
     const PRUint32 WANT_OUTER_OBJECT                = 1 << 29;
+    const PRUint32 USE_STUB_EQUALITY_HOOK           = 1 << 30;
 
     // The high order bit is RESERVED for consumers of these flags. 
     // No implementor of this interface should ever return flags 
     // with this bit set.
     const PRUint32 RESERVED                         = 1 << 31;
 
     readonly attribute string   className;
     readonly attribute PRUint32 scriptableFlags;
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -387,17 +387,17 @@ interface nsIXPCFunctionThisTranslator :
 %{ C++
 // For use with the service manager
 // {CB6593E0-F9B2-11d2-BDD6-000064657374}
 #define NS_XPCONNECT_CID \
 { 0xcb6593e0, 0xf9b2, 0x11d2, \
     { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 %}
 
-[uuid(f99ffb06-4e7b-4bab-83d4-7d573235a08a)]
+[uuid(a995b541-d514-43f1-ac0e-f49746c0b063)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Initializes classes on a global object that has already been created.
@@ -720,23 +720,16 @@ interface nsIXPConnect : nsISupports
      * Note aJSContext as a child to the cycle collector.
      * @param aJSContext The JSContext to note.
      * @param aCb The cycle collection traversal callback.
      */
     [noscript,notxpcom] void noteJSContext(in JSContextPtr aJSContext,
                                            in nsCCTraversalCallbackRef aCb);
 
     /**
-     * Get the JSEqualityOp pointer to use for identifying JSObjects that hold
-     * a pointer to a nsIXPConnectWrappedNative or to the native in their
-     * private date. See IS_WRAPPER_CLASS in xpcprivate.h for details.
-     */
-    void GetXPCWrappedNativeJSClassInfo(out JSEqualityOp equality);
-
-    /**
      * Whether or not XPConnect should report all JS exceptions when returning
      * from JS into C++. False by default, although any value set in the
      * MOZ_REPORT_ALL_JS_EXCEPTIONS environment variable will override the value
      * passed here.
      */
     void setReportAllJSExceptions(in boolean reportAllJSExceptions);
 
     /**
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -2103,28 +2103,16 @@ nsXPConnect::EvalInSandboxObject(const n
     nsresult rv = sandbox->GetJSObject(&obj);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return xpc_EvalInSandbox(cx, obj, source,
                              NS_ConvertUTF16toUTF8(source).get(), 1,
                              JSVERSION_DEFAULT, returnStringOnly, rval);
 }
 
-/* void GetXPCWrappedNativeJSClassInfo(out JSEqualityOp equality); */
-NS_IMETHODIMP
-nsXPConnect::GetXPCWrappedNativeJSClassInfo(JSEqualityOp *equality)
-{
-    // Expose the equality pointer used by IS_WRAPPER_CLASS(). If that macro
-    // ever changes, this function needs to stay in sync.
-
-    *equality = &XPC_WN_Equality;
-
-    return NS_OK;
-}
-
 /* nsIXPConnectJSObjectHolder getWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo); */
 NS_IMETHODIMP 
 nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext, 
                                        JSObject * aScope, 
                                        nsIClassInfo *aClassInfo, 
                                        nsIXPConnectJSObjectHolder **_retval)
 {
     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -1263,33 +1263,33 @@ GetCompartmentTjitCodeSize(JSCompartment
     }
     return 0;
 }
 
 PRInt64
 GetCompartmentTjitDataAllocatorsMainSize(JSCompartment *c)
 {
     return c->hasTraceMonitor()
-         ? c->traceMonitor()->getVMAllocatorsMainSize()
+         ? c->traceMonitor()->getVMAllocatorsMainSize(moz_malloc_usable_size)
          : 0;
 }
 
 PRInt64
 GetCompartmentTjitDataAllocatorsReserveSize(JSCompartment *c)
 {
     return c->hasTraceMonitor()
-         ? c->traceMonitor()->getVMAllocatorsReserveSize()
+         ? c->traceMonitor()->getVMAllocatorsReserveSize(moz_malloc_usable_size)
          : 0;
 }
 
 PRInt64
 GetCompartmentTjitDataTraceMonitorSize(JSCompartment *c)
 {
     return c->hasTraceMonitor()
-         ? c->traceMonitor()->getTraceMonitorSize()
+         ? c->traceMonitor()->getTraceMonitorSize(moz_malloc_usable_size)
          : 0;
 }
 
 #endif  // JS_TRACER
 
 void
 CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
 {
@@ -1347,37 +1347,30 @@ CellCallback(JSContext *cx, void *vdata,
         {
             JSObject *obj = static_cast<JSObject *>(thing);
             curr->objectSlots += obj->sizeOfSlotsArray(moz_malloc_usable_size);
             break;
         }
         case JSTRACE_STRING:
         {
             JSString *str = static_cast<JSString *>(thing);
-            curr->stringChars += str->charsHeapSize();
+            curr->stringChars += str->charsHeapSize(moz_malloc_usable_size);
             break;
         }
         case JSTRACE_SHAPE:
         {
             js::Shape *shape = static_cast<js::Shape *>(thing);
-            if(shape->hasTable())
-                curr->propertyTables +=
-                    shape->getTable()->sizeOf(moz_malloc_usable_size);
+            curr->propertyTables += shape->sizeOfPropertyTable(moz_malloc_usable_size);
+            curr->shapeKids += shape->sizeOfKids(moz_malloc_usable_size);
             break;
         }
         case JSTRACE_SCRIPT:
         {
             JSScript *script = static_cast<JSScript *>(thing);
-#if JS_SCRIPT_INLINE_DATA_LIMIT
-            if (script->data != script->inlineData)
-#endif
-            {
-                size_t usable = moz_malloc_usable_size(script->data);
-                curr->scriptData += usable ? usable : script->dataSize();
-            }
+            curr->scriptData += script->dataSize(moz_malloc_usable_size);
 #ifdef JS_METHODJIT
             curr->mjitData += script->jitDataSize(moz_malloc_usable_size);
 #endif
             break;
         }
         case JSTRACE_TYPE_OBJECT:
         {
             js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
@@ -1443,51 +1436,17 @@ MakeMemoryReporterPath(const nsACString 
                        const char (&reporterName)[N])
 {
   return pathPrefix + NS_LITERAL_CSTRING("compartment(") + compartmentName +
          NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName);
 }
 
 } // anonymous namespace
 
-class XPConnectGCChunkAllocator
-    : public js::GCChunkAllocator
-{
-public:
-    XPConnectGCChunkAllocator() {}
-
-private:
-    virtual void *doAlloc() {
-        void *chunk;
-#ifdef MOZ_MEMORY
-        // posix_memalign returns zero on success, nonzero on failure.
-        if (posix_memalign(&chunk, js::GC_CHUNK_SIZE, js::GC_CHUNK_SIZE))
-            chunk = 0;
-#else
-        chunk = js::AllocGCChunk();
-#endif
-        return chunk;
-    }
-
-    virtual void doFree(void *chunk) {
-#ifdef MOZ_MEMORY
-        free(chunk);
-#else
-        js::FreeGCChunk(chunk);
-#endif
-    }
-};
-
-static XPConnectGCChunkAllocator gXPCJSChunkAllocator;
-
-#ifdef MOZ_MEMORY
-#define JS_GC_HEAP_KIND  nsIMemoryReporter::KIND_HEAP
-#else
 #define JS_GC_HEAP_KIND  nsIMemoryReporter::KIND_NONHEAP
-#endif
 
 // We have per-compartment GC heap totals, so we can't put the total GC heap
 // size in the explicit allocations tree.  But it's a useful figure, so put it
 // in the "others" list.
 
 static PRInt64
 GetGCChunkTotalBytes()
 {
@@ -1631,18 +1590,22 @@ CollectCompartmentStatsForRuntime(JSRunt
 
         js::IterateCompartmentsArenasCells(cx, data, CompartmentCallback,
                                            ArenaCallback, CellCallback);
 
         for(js::ThreadDataIter i(rt); !i.empty(); i.popFront())
             data->stackSize += i.threadData()->stackSpace.committedSize();
 
         size_t usable = moz_malloc_usable_size(rt);
-        data->runtimeObjectSize += usable ? usable : sizeof(JSRuntime);
-        data->atomsTableSize += rt->atomState.atoms.tableSize();
+        data->runtimeObjectSize = usable ? usable : sizeof(JSRuntime);
+
+        // Nb: |countMe| is false because atomState.atoms is within JSRuntime,
+        // and so counted when JSRuntime is counted.
+        data->atomsTableSize =
+            rt->atomState.atoms.sizeOf(moz_malloc_usable_size, /* countMe */false);
     }
 
     JS_DestroyContextNoGC(cx);
 
     // This is initialized to all bytes stored in used chunks, and then we
     // subtract used space from it each time around the loop.
     data->gcHeapChunkDirtyUnused = data->gcHeapChunkTotal -
                                    data->gcHeapChunkCleanUnused;
@@ -1792,16 +1755,24 @@ ReportCompartmentStats(const Compartment
     ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
                                               "object-empty-shapes"),
                        nsIMemoryReporter::KIND_HEAP,
                        stats.typeInferenceMemory.emptyShapes,
     "Arrays attached to prototype JS objects managing shape information.",
                        callback, closure);
 
     ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+                                              "shape-kids"),
+                       nsIMemoryReporter::KIND_HEAP, stats.shapeKids,
+    "Memory allocated for the compartment's shape kids.  A shape kid "
+    "is an internal data structure that makes JavaScript property accesses "
+    "fast.",
+                       callback, closure);
+
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
                                               "script-data"),
                        nsIMemoryReporter::KIND_HEAP, stats.scriptData,
     "Memory allocated for JSScript bytecode and various variable-length "
     "tables." SLOP_BYTES_STRING,
                        callback, closure);
 
 #ifdef JS_METHODJIT
     ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
@@ -2085,18 +2056,16 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
         JS_EnumerateDiagnosticMemoryRegions(DiagnosticMemoryCallback);
 #endif
         mWatchdogWakeup = JS_NEW_CONDVAR(mJSRuntime->gcLock);
         if (!mWatchdogWakeup)
             NS_RUNTIMEABORT("JS_NEW_CONDVAR failed.");
 
         mJSRuntime->setActivityCallback(ActivityCallback, this);
 
-        mJSRuntime->setCustomGCChunkAllocator(&gXPCJSChunkAllocator);
-
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
         NS_RegisterMemoryMultiReporter(new XPConnectJSCompartmentsMultiReporter);
     }
 
     if(!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
                           sizeof(ObjectHolder), 512))
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -1384,38 +1384,52 @@ XPC_WN_JSOp_Clear(JSContext *cx, JSObjec
 
 extern JSObject*
 XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
 
 // Macros to initialize Object or Function like XPC_WN classes
 #define XPC_WN_WithCall_ObjectOps                                             \
     {                                                                         \
         nsnull, /* lookupProperty */                                          \
+        nsnull, /* lookupElement */                                           \
         nsnull, /* defineProperty */                                          \
+        nsnull, /* defineElement */                                           \
         nsnull, /* getProperty    */                                          \
+        nsnull, /* getElement    */                                           \
         nsnull, /* setProperty    */                                          \
+        nsnull, /* setElement    */                                           \
         nsnull, /* getAttributes  */                                          \
+        nsnull, /* getElementAttributes  */                                   \
         nsnull, /* setAttributes  */                                          \
+        nsnull, /* setElementAttributes  */                                   \
         nsnull, /* deleteProperty */                                          \
+        nsnull, /* deleteElement */                                           \
         js::Valueify(XPC_WN_JSOp_Enumerate),                                  \
         XPC_WN_JSOp_TypeOf_Function,                                          \
         nsnull, /* fix            */                                          \
         XPC_WN_JSOp_ThisObject,                                               \
         XPC_WN_JSOp_Clear                                                     \
     }
 
 #define XPC_WN_NoCall_ObjectOps                                               \
     {                                                                         \
         nsnull, /* lookupProperty */                                          \
+        nsnull, /* lookupElement */                                           \
         nsnull, /* defineProperty */                                          \
+        nsnull, /* defineElement */                                           \
         nsnull, /* getProperty    */                                          \
+        nsnull, /* getElement    */                                           \
         nsnull, /* setProperty    */                                          \
+        nsnull, /* setElement    */                                           \
         nsnull, /* getAttributes  */                                          \
+        nsnull, /* getElementAttributes  */                                   \
         nsnull, /* setAttributes  */                                          \
+        nsnull, /* setElementAttributes  */                                   \
         nsnull, /* deleteProperty */                                          \
+        nsnull, /* deleteElement */                                           \
         js::Valueify(XPC_WN_JSOp_Enumerate),                                  \
         XPC_WN_JSOp_TypeOf_Object,                                            \
         nsnull, /* fix            */                                          \
         XPC_WN_JSOp_ThisObject,                                               \
         XPC_WN_JSOp_Clear                                                     \
     }
 
 // Maybe this macro should check for class->enumerate ==
@@ -1947,16 +1961,17 @@ public:
     JSBool DontEnumStaticProps()          GET_IT(DONT_ENUM_STATIC_PROPS)
     JSBool DontEnumQueryInterface()       GET_IT(DONT_ENUM_QUERY_INTERFACE)
     JSBool DontAskInstanceForScriptable() GET_IT(DONT_ASK_INSTANCE_FOR_SCRIPTABLE)
     JSBool ClassInfoInterfacesOnly()      GET_IT(CLASSINFO_INTERFACES_ONLY)
     JSBool AllowPropModsDuringResolve()   GET_IT(ALLOW_PROP_MODS_DURING_RESOLVE)
     JSBool AllowPropModsToPrototype()     GET_IT(ALLOW_PROP_MODS_TO_PROTOTYPE)
     JSBool DontSharePrototype()           GET_IT(DONT_SHARE_PROTOTYPE)
     JSBool DontReflectInterfaceNames()    GET_IT(DONT_REFLECT_INTERFACE_NAMES)
+    JSBool UseStubEqualityHook()          GET_IT(USE_STUB_EQUALITY_HOOK)
 
 #undef GET_IT
 };
 
 /***************************************************************************/
 
 // XPCNativeScriptableShared is used to hold the JSClass and the
 // associated scriptable flags for XPCWrappedNatives. These are shared across
--- a/js/src/xpconnect/src/xpcpublic.h
+++ b/js/src/xpconnect/src/xpcpublic.h
@@ -70,21 +70,18 @@ xpc_CreateMTGlobalObject(JSContext *cx, 
 
 // XXX where should this live?
 NS_EXPORT_(void)
 xpc_LocalizeContext(JSContext *cx);
 
 nsresult
 xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph);
 
-extern JSBool
-XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
-
 #define IS_WRAPPER_CLASS(clazz)                                               \
-    (clazz->ext.equality == js::Valueify(XPC_WN_Equality))
+    ((clazz)->ext.isWrappedNative)
 
 inline JSBool
 DebugCheckWrapperClass(JSObject* obj)
 {
     NS_ASSERTION(IS_WRAPPER_CLASS(obj->getClass()),
                  "Forgot to check if this is a wrapper?");
     return JS_TRUE;
 }
@@ -202,16 +199,17 @@ struct CompartmentStats
     PRInt64 gcHeapArenaPadding;
     PRInt64 gcHeapArenaUnused;
 
     PRInt64 gcHeapKinds[JSTRACE_LAST + 1];
 
     PRInt64 objectSlots;
     PRInt64 stringChars;
     PRInt64 propertyTables;
+    PRInt64 shapeKids;
     PRInt64 scriptData;
 
 #ifdef JS_METHODJIT
     PRInt64 mjitCodeMethod;
     PRInt64 mjitCodeRegexp;
     PRInt64 mjitCodeUnused;
     PRInt64 mjitData;
 #endif
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -902,22 +902,29 @@ js::Class XPC_WN_NoHelper_JSClass = {
         nsnull, // iteratorObject
         nsnull, // unused
         true,   // isWrappedNative
     },
    
     // ObjectOps
     {
         nsnull, // lookupProperty
+        nsnull, // lookupElement
         nsnull, // defineProperty
+        nsnull, // defineElement
         nsnull, // getProperty
+        nsnull, // getElement
         nsnull, // setProperty
+        nsnull, // setElement
         nsnull, // getAttributes
+        nsnull, // getElementAttributes
         nsnull, // setAttributes
+        nsnull, // setElementAttributes
         nsnull, // deleteProperty
+        nsnull, // deleteElement
         JS_VALUEIFY(js::NewEnumerateOp, XPC_WN_JSOp_Enumerate),
         XPC_WN_JSOp_TypeOf_Object,
         nsnull, // fix
         XPC_WN_JSOp_ThisObject,
         XPC_WN_JSOp_Clear
     }
 };
 
@@ -1536,18 +1543,27 @@ XPCNativeScriptableShared::PopulateJSCla
         if(mFlags.WantConstruct())
             mJSClass.base.construct = js::Valueify(XPC_WN_Helper_Construct);
     }
     else
     {
         ops->typeOf = XPC_WN_JSOp_TypeOf_Object;
     }
 
-    // Equality is a required hook.
-    mJSClass.base.ext.equality = js::Valueify(XPC_WN_Equality);
+    if(mFlags.UseStubEqualityHook())
+    {
+        NS_ASSERTION(!mFlags.WantEquality(),
+                     "If you want an Equality callback, you can't use a stub "
+                     "equality hook");
+        mJSClass.base.ext.equality = nsnull;
+    }
+    else
+    {
+        mJSClass.base.ext.equality = js::Valueify(XPC_WN_Equality);
+    }
 
     if(mFlags.WantHasInstance())
         mJSClass.base.hasInstance = js::Valueify(XPC_WN_Helper_HasInstance);
 
     if(mFlags.WantTrace())
         mJSClass.base.trace = XPC_WN_Helper_Trace;
     else
         mJSClass.base.trace = XPC_WN_Shared_Trace;
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1898,36 +1898,39 @@ InternalInvalidateThebesLayersInSubtree(
   PRBool foundContainerLayer = PR_FALSE;
   if (aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) {
     // Delete the invalid region to indicate that all Thebes contents
     // need to be invalidated
     aFrame->Properties().Delete(ThebesLayerInvalidRegionProperty());
     foundContainerLayer = PR_TRUE;
   }
 
-  nsIFrame* frame = aFrame;
-  while (frame) {
-    nsIFrame::ChildListIterator lists(frame);
-    for (; !lists.IsDone(); lists.Next()) {
-      nsFrameList::Enumerator childFrames(lists.CurrentList());
-      for (; !childFrames.AtEnd(); childFrames.Next()) {
-        if (InternalInvalidateThebesLayersInSubtree(childFrames.get())) {
-          foundContainerLayer = PR_TRUE;
-        }
+  nsAutoTArray<nsIFrame::ChildList,4> childListArray;
+  if (!aFrame->GetFirstPrincipalChild()) {
+    nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(aFrame);
+    if (subdocumentFrame) {
+      // Descend into the subdocument
+      nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame();
+      if (root) {
+        childListArray.AppendElement(nsIFrame::ChildList(
+          nsFrameList(root, nsLayoutUtils::GetLastSibling(root)),
+          nsIFrame::kPrincipalList));
       }
     }
-    if (frame == aFrame && !frame->GetFirstPrincipalChild()) {
-      nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(frame);
-      if (subdocumentFrame) {
-        // Descend into the subdocument
-        frame = subdocumentFrame->GetSubdocumentRootFrame();
-        continue;
+  }
+
+  aFrame->GetChildLists(&childListArray);
+  nsIFrame::ChildListArrayIterator lists(childListArray);
+  for (; !lists.IsDone(); lists.Next()) {
+    nsFrameList::Enumerator childFrames(lists.CurrentList());
+    for (; !childFrames.AtEnd(); childFrames.Next()) {
+      if (InternalInvalidateThebesLayersInSubtree(childFrames.get())) {
+        foundContainerLayer = PR_TRUE;
       }
     }
-    break;
   }
 
   if (!foundContainerLayer) {
     aFrame->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
   }
   return foundContainerLayer;
 }
 
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -36,20 +36,20 @@ asserts(1) load 243519-1.html # bug 5366
 load 244490-1.html
 load 254367-1.html
 load 263359-1.html
 load 265027-1.html
 load 265736-1.html
 load 265736-2.html
 asserts(2) load 265899-1.html # bug 575011
 load 265973-1.html
-asserts(8-12) load 265986-1.html # Bug 512405
-asserts(4) load 265999-1.html # bug 575011
+asserts(6-12) load 265986-1.html # Bug 512405
+asserts(2-4) load 265999-1.html # bug 575011
 load 266222-1.html
-asserts(5-7) load 266360-1.html # bug 575011 / bug 576358
+asserts(3-7) load 266360-1.html # bug 575011 / bug 576358
 asserts(4) load 266445-1.html # Bug 575011
 load 268157-1.html
 load 269566-1.html
 load 272647-1.html
 load 275746-1.html
 load 276053-1.html
 load 280708-1.html
 load 280708-2.html
@@ -252,22 +252,20 @@ load 468578-1.xhtml
 load 468645-1.xhtml
 load 468645-2.xhtml
 load 468645-3.xhtml
 load 469861-1.xhtml
 load 469861-2.xhtml
 load 471594-1.xhtml
 load 479114-1.html
 load 477333-1.xhtml
-load 477731-1.html
-# 479360-1.xhtml will assert 6 times due to bug 439258 and then make the test
-# after the test after it also assert 6 times.
-asserts(6) load 479360-1.xhtml # Bug 439258
-load 480686-1.html
-asserts(6) load 481806-1.html  # Bug 439258
+asserts-if(Android,6) load 477731-1.html
+load 479360-1.xhtml
+asserts-if(Android,6) load 480686-1.html
+load 481806-1.html
 load 483604-1.xhtml
 load 485501-1.html
 load 487544-1.html
 load 488390-1.xhtml
 load 489691.html
 load 490376-1.xhtml
 load 490559-1.html
 load 490747.html
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2577,17 +2577,17 @@ PRBool nsDisplayTransform::ComputeVisibi
                        mFrame, 
                        aBuilder->ToReferenceFrame(mFrame), 
                        &untransformedVisibleRect)) 
   {
     untransformedVisibleRect = mFrame->GetVisualOverflowRectRelativeToSelf() +  
                                aBuilder->ToReferenceFrame(mFrame);
   }
   nsRegion untransformedVisible = untransformedVisibleRect;
-  // Call RecomputeVisiblity instead of ComputeVisibilty since
+  // Call RecomputeVisiblity instead of ComputeVisibility since
   // nsDisplayItem::ComputeVisibility should only be called from
   // nsDisplayList::ComputeVisibility (which sets mVisibleRect on the item)
   mStoredList.RecomputeVisibility(aBuilder, &untransformedVisible);
   return PR_TRUE;
 }
 
 #ifdef DEBUG_HIT
 #include <time.h>
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1429,16 +1429,19 @@ public:
     NS_DECL_NSIMEMORYMULTIREPORTER
   protected:
     static PLDHashOperator SizeEnumerator(PresShellPtrKey *aEntry, void *userArg);
   };
 
 protected:
   void QueryIsActive();
   nsresult UpdateImageLockingState();
+
+private:
+  nscolor GetDefaultBackgroundColorToDraw();
 };
 
 NS_IMPL_ISUPPORTS1(PresShell::MemoryReporter, nsIMemoryMultiReporter)
 
 namespace {
 
 struct MemoryReporterData
 {
@@ -4039,23 +4042,29 @@ PresShell::ScrollToAnchor()
  * Helper (per-continuation) for ScrollContentIntoView.
  *
  * @param aContainerFrame [in] the frame which aRect is relative to
  * @param aFrame [in] Frame whose bounds should be unioned
  * @param aUseWholeLineHeightForInlines [in] if true, then for inline frames
  * we should include the top of the line in the added rectangle
  * @param aRect [inout] rect into which its bounds should be unioned
  * @param aHaveRect [inout] whether aRect contains data yet
+ * @param aPrevBlock [inout] the block aLines is a line iterator for
+ * @param aLines [inout] the line iterator we're using
+ * @param aCurLine [inout] the line to start looking from in this iterator
  */
 static void
 AccumulateFrameBounds(nsIFrame* aContainerFrame,
                       nsIFrame* aFrame,
                       PRBool aUseWholeLineHeightForInlines,
                       nsRect& aRect,
-                      PRBool& aHaveRect)
+                      PRBool& aHaveRect,
+                      nsIFrame*& aPrevBlock,
+                      nsAutoLineIterator& aLines,
+                      PRInt32& aCurLine)
 {
   nsRect frameBounds = aFrame->GetRect() +
     aFrame->GetParent()->GetOffsetTo(aContainerFrame);
 
   // If this is an inline frame and either the bounds height is 0 (quirks
   // layout model) or aUseWholeLineHeightForInlines is set, we need to
   // change the top of the bounds to include the whole line.
   if (frameBounds.height == 0 || aUseWholeLineHeightForInlines) {
@@ -4068,27 +4077,32 @@ AccumulateFrameBounds(nsIFrame* aContain
       prevFrame = f;
       f = prevFrame->GetParent();
     }
 
     if (f != aFrame &&
         f &&
         frameType == nsGkAtoms::blockFrame) {
       // find the line containing aFrame and increase the top of |offset|.
-      nsAutoLineIterator lines = f->GetLineIterator();
-      if (lines) {
-        PRInt32 index = lines->FindLineContaining(prevFrame);
+      if (f != aPrevBlock) {
+        aLines = f->GetLineIterator();
+        aPrevBlock = f;
+        aCurLine = 0;
+      }
+      if (aLines) {
+        PRInt32 index = aLines->FindLineContaining(prevFrame, aCurLine);
         if (index >= 0) {
+          aCurLine = index;
           nsIFrame *trash1;
           PRInt32 trash2;
           nsRect lineBounds;
           PRUint32 trash3;
 
-          if (NS_SUCCEEDED(lines->GetLine(index, &trash1, &trash2,
-                                          lineBounds, &trash3))) {
+          if (NS_SUCCEEDED(aLines->GetLine(index, &trash1, &trash2,
+                                           lineBounds, &trash3))) {
             lineBounds += f->GetOffsetTo(aContainerFrame);
             if (lineBounds.y < frameBounds.y) {
               frameBounds.height = frameBounds.YMost() - lineBounds.y;
               frameBounds.y = lineBounds.y;
             }
           }
         }
       }
@@ -4281,19 +4295,26 @@ PresShell::DoScrollContentIntoView(nsICo
   //         appropriately.
   // frameBounds is relative to container. We're assuming
   // that scrollframes don't split so every continuation of frame will
   // be a descendant of container. (Things would still mostly work
   // even if that assumption was false.)
   nsRect frameBounds;
   PRBool haveRect = PR_FALSE;
   PRBool useWholeLineHeightForInlines = aVPercent != NS_PRESSHELL_SCROLL_ANYWHERE;
+  // Reuse the same line iterator across calls to AccumulateFrameBounds.  We set
+  // it every time we detect a new block (stored in prevBlock).
+  nsIFrame* prevBlock = nsnull;
+  nsAutoLineIterator lines;
+  // The last line we found a continuation on in |lines|.  We assume that later
+  // continuations cannot come on earlier lines.
+  PRInt32 curLine = 0;
   do {
     AccumulateFrameBounds(container, frame, useWholeLineHeightForInlines,
-                          frameBounds, haveRect);
+                          frameBounds, haveRect, prevBlock, lines, curLine);
   } while ((frame = frame->GetNextContinuation()));
 
   ScrollFrameRectIntoView(container, frameBounds, aVPercent, aHPercent,
                           aFlags);
 }
 
 PRBool
 PresShell::ScrollFrameRectIntoView(nsIFrame*     aFrame,
@@ -5828,16 +5849,24 @@ static PRBool IsTransparentContainerElem
   if (!pwin)
     return PR_FALSE;
   nsCOMPtr<nsIContent> containerElement =
     do_QueryInterface(pwin->GetFrameElementInternal());
   return containerElement &&
          containerElement->HasAttr(kNameSpaceID_None, nsGkAtoms::transparent);
 }
 
+nscolor PresShell::GetDefaultBackgroundColorToDraw()
+{
+  if (!mPresContext || !mPresContext->GetBackgroundColorDraw()) {
+    return NS_RGB(255,255,255);
+  }
+  return mPresContext->DefaultBackgroundColor();
+}
+
 void PresShell::UpdateCanvasBackground()
 {
   // If we have a frame tree and it has style information that
   // specifies the background color of the canvas, update our local
   // cache of that color.
   nsIFrame* rootStyleFrame = FrameConstructor()->GetRootElementStyleFrame();
   if (rootStyleFrame) {
     nsStyleContext* bgStyle =
@@ -5847,40 +5876,40 @@ void PresShell::UpdateCanvasBackground()
     // a problem because only a few frames can return something other than true
     // and none of them would be a canvas frame or root element style frame.
     mCanvasBackgroundColor =
       nsCSSRendering::DetermineBackgroundColor(mPresContext, bgStyle,
                                                rootStyleFrame);
     if (GetPresContext()->IsRootContentDocument() &&
         !IsTransparentContainerElement(mPresContext)) {
       mCanvasBackgroundColor =
-        NS_ComposeColors(mPresContext->DefaultBackgroundColor(), mCanvasBackgroundColor);
+        NS_ComposeColors(GetDefaultBackgroundColorToDraw(), mCanvasBackgroundColor);
     }
   }
 
   // If the root element of the document (ie html) has style 'display: none'
   // then the document's background color does not get drawn; cache the
   // color we actually draw.
   if (!FrameConstructor()->GetRootElementFrame()) {
-    mCanvasBackgroundColor = mPresContext->DefaultBackgroundColor();
+    mCanvasBackgroundColor = GetDefaultBackgroundColorToDraw();
   }
 }
 
 nscolor PresShell::ComputeBackstopColor(nsIView* aDisplayRoot)
 {
   nsIWidget* widget = aDisplayRoot->GetWidget();
   if (widget && widget->GetTransparencyMode() != eTransparencyOpaque) {
     // Within a transparent widget, so the backstop color must be
     // totally transparent.
     return NS_RGBA(0,0,0,0);
   }
   // Within an opaque widget (or no widget at all), so the backstop
   // color must be totally opaque. The user's default background
   // as reported by the prescontext is guaranteed to be opaque.
-  return GetPresContext()->DefaultBackgroundColor();
+  return GetDefaultBackgroundColorToDraw();
 }
 
 struct PaintParams {
   nscolor mBackgroundColor;
 };
 
 LayerManager* PresShell::GetLayerManager()
 {
--- a/layout/base/tests/test_reftests_with_caret.html
+++ b/layout/base/tests/test_reftests_with_caret.html
@@ -92,45 +92,45 @@ function endTest() {
   } else {
     prefs.clearUserPref("ui.caretBlinkTime");
   }
 }
 
 var isWindows = /WINNT/.test(SpecialPowers.OS);
 
 var tests = [
-    [ 'bug106855-1.html' , 'bug106855-1-ref.html' ] ,
     [ 'bug389321-1.html' , 'bug389321-1-ref.html' ] ,
     [ 'bug389321-2.html' , 'bug389321-2-ref.html' ] ,
     [ 'bug389321-3.html' , 'bug389321-3-ref.html' ] ,
     [ 'bug482484.html'   , 'bug482484-ref.html'   ] ,
     [ 'bug585922.html'   , 'bug585922-ref.html'   ] ,
-    [ 'bug602141-2.html' , 'bug602141-2-ref.html' ] ,
     [ 'bug602141-3.html' , 'bug602141-3-ref.html' ] ,
-    [ 'bug613433-2.html' , 'bug613433-ref.html' ] ,
-    [ 'bug613433-3.html' , 'bug613433-ref.html' ] ,
     [ 'bug632215-1.html' , 'bug632215-ref.html'   ] ,
     [ 'bug632215-2.html' , 'bug632215-ref.html'   ] ,
     [ 'bug633044-1.html' , 'bug633044-1-ref.html' ] ,
     [ 'bug644428-1.html' , 'bug644428-1-ref.html' ] ,
 ];
 
 if (!isWindows) {
+  tests.push([ 'bug106855-1.html' , 'bug106855-1-ref.html' ]); // bug 682837
   tests.push([ 'bug106855-2.html' , 'bug106855-1-ref.html' ]); // bug 681138
   tests.push([ 'bug240933-1.html' , 'bug240933-1-ref.html' ]); // bug 681144
   tests.push([ 'bug240933-2.html' , 'bug240933-1-ref.html' ]); // bug 681162
   tests.push([ 'bug512295-1.html' , 'bug512295-1-ref.html' ]); // bug 681152
   tests.push([ 'bug512295-2.html' , 'bug512295-2-ref.html' ]); // bug 681331
   tests.push([ 'bug597519-1.html' , 'bug597519-1-ref.html' ]); // bug 680579
   tests.push([ 'bug602141-1.html' , 'bug602141-1-ref.html' ]); // bug 681334
+  tests.push([ 'bug602141-2.html' , 'bug602141-2-ref.html' ]); // bug 682836
   tests.push([ 'bug602141-4.html' , 'bug602141-4-ref.html' ]); // bug 681167
   tests.push([ 'bug612271-1.html' , 'bug612271-ref.html' ]);   // bug 681032
   tests.push([ 'bug612271-2.html' , 'bug612271-ref.html' ]);   // bug 680581
   tests.push([ 'bug612271-3.html' , 'bug612271-ref.html' ]);   // bug 681035
   tests.push([ 'bug613433-1.html' , 'bug613433-ref.html' ]);   // bug 681332
+  tests.push([ 'bug613433-2.html' , 'bug613433-ref.html' ]);   // bug 681332
+  tests.push([ 'bug613433-3.html' , 'bug613433-ref.html' ]);   // bug 681332
   tests.push([ 'bug613807-1.html' , 'bug613807-1-ref.html' ]); // bug 680574
   tests.push([ 'bug634406-1.html' , 'bug634406-1-ref.html' ]); // bug 681146
 }
 
 tests.push(function() {SpecialPowers.setBoolPref("bidi.browser.ui", true);});
 
 if (!isWindows) {
   tests.push([ 'bug646382-1.html' , 'bug646382-1-ref.html' ]);  // bug 681076
--- a/layout/doc/obsolete/nav4-html.html
+++ b/layout/doc/obsolete/nav4-html.html
@@ -71,17 +71,17 @@ the tag. The HTML parser serves as the t
 tags documented below. Tag attribute handling is done during translation
 of tags into content. This mapping translates the tag attributes into content
 data and into style data. The translation to style data is documented below
 by indicating the mapping from tag attributes to their CSS1 (plus extensions)
 equivalents.
 <H3>
 Special Hacks</H3>
 The following list describes hacks added to the magellan parsing engine
-to deal with navigator compatability. These are just the parser hacks,
+to deal with navigator compatibility. These are just the parser hacks,
 not the layout or presentation hacks. Most hacks are intriduced for HTML
 syntax error recovering. HTML doesn't specify much how to handle those
 error conditions. Netscape has made big effort to render pages with non-prefect
 HTML. For many reasons, new browsers need to keep compatible in thsi area.
 <UL>
 <LI>
 Entities can be used as escape in quoted string. For value string in name-value
 pair,&nbsp; see <A HREF="../testhtml/quote001.html">compatibility test
--- a/layout/forms/crashtests/crashtests.list
+++ b/layout/forms/crashtests/crashtests.list
@@ -15,21 +15,21 @@ load 363696-1.xul
 load 363696-2.html
 load 363696-3.html
 load 366205-1.html
 load 366537-1.xhtml
 load 367587-1.html
 load 370703-1.html
 load 370940-1.html
 load 373586-1.xhtml
-asserts(8-10) load 378413-1.xhtml # bug 424225, bug 402850?
+asserts(5-10) load 378413-1.xhtml # bug 424225, bug 402850?
 load 380116-1.xhtml
 load 382212-1.xhtml
 load 382610-1.html
-asserts-if(winWidget,1) load 383887-1.html # bug 576434
+asserts-if(winWidget||Android,1) load 383887-1.html # bug 576434
 load 386554-1.html
 load 388374-1.xhtml
 load 388374-2.html
 load 393656-1.xhtml
 load 393656-2.xhtml
 load 402852-1.html
 load 403148-1.html
 load 404118-1.html
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -66,17 +66,17 @@ load 370866-1.xhtml
 load 370884-1.xhtml
 load 371348-1.xhtml
 load 371561-1.html
 load 371566-1.xhtml
 load 372376-1.xhtml
 load 373859-1.html
 load 373868-1.xhtml
 load 379217-1.xhtml
-asserts(2) load 379217-2.xhtml # Bug 439204
+asserts(1-2) load 379217-2.xhtml # Bug 439204
 load 379917-1.xhtml
 load 380012-1.html
 load 381152-1.html
 load 381786-1.html
 asserts-if(gtk2Widget,0-2) load 382129-1.xhtml # Bug 540078
 asserts-if(gtk2Widget,0-1) load 382131-1.html # Bug 540078
 load 382199-1.html
 load 382208-1.xhtml
@@ -119,17 +119,17 @@ load 393906-1.html
 load 393923-1.html
 load 393956-1.html
 load 393956-2.html
 load 393956-3.html
 load 393956-4.html
 load 394237-1.html
 load 394820-1.html
 load 394818-1.html
-load 394818-2.html
+asserts-if(Android,1) load 394818-2.html
 load 395316-1.html
 load 395450-1.xhtml
 load 397007-1.html
 load 397187-1.html
 load 397844-1.xhtml
 load 397844-2.xhtml
 load 397852-1.xhtml
 load 398181-1.html
@@ -178,18 +178,18 @@ load 413048-1.html
 load 413079-1.xhtml
 load 413079-2.xhtml
 load 413079-3.xhtml
 load 413085-1.html
 load 413085-2.html
 load 413582-1.xhtml
 load 413582-2.html
 load 413712-1.xhtml
-load 414061-1.html
-asserts(6) load 414180-1.xul # Bug 439258
+asserts-if(Android,6) load 414061-1.html
+asserts-if(!Android,6) load 414180-1.xul # Bug 439258
 load 414719-1.html
 load 415685-1.html
 load 416264-1.html
 load 416476-1.html
 load 417109-1.xhtml
 load 417902-1.html
 load 417902-2.html
 load 418532-1.html
@@ -275,17 +275,17 @@ load 472950-1.html
 load 473278-1.xhtml
 load 473894-1.html
 load 476241-1.html
 load 477731-1.html
 load 477928.html
 load 478131-1.html
 load 478170-1.html
 load 478185-1.html
-asserts(1) load 479938-1.html # Bug 575011
+asserts-if(!Android,1) load 479938-1.html # Bug 575011
 load 480345-1.html
 skip-if(Android) load 481921.html
 load 489462-1.html
 load 489480-1.xhtml
 load 493111-1.html
 load 493118-1.html
 load 494300-1.xul
 load 494332-1.html
@@ -363,12 +363,12 @@ load 650499-1.html
 load 660416.html
 load text-overflow-form-elements.html
 load text-overflow-iframe.html
 load text-overflow-bug666751-1.html
 load text-overflow-bug666751-2.html
 asserts(2) load text-overflow-bug670564.xhtml # asserts(2) for bug 436470
 load text-overflow-bug671796.xhtml
 load 667025.html
-asserts(14) load 673770.html # bug 569193 and bug 459597
+asserts(14) asserts-if(Android,8) load 673770.html # bug 569193 and bug 459597
 load 679933-1.html
 load 682649-1.html
 load 683702-1.xhtml
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=78: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/I
+ * http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is mozilla.org code.
  *
@@ -556,17 +556,17 @@ public:
    */
   NS_IMETHOD  Init(nsIContent*      aContent,
                    nsIFrame*        aParent,
                    nsIFrame*        aPrevInFlow) = 0;
 
   /**
    * Destroys this frame and each of its child frames (recursively calls
    * Destroy() for each child). If this frame is a first-continuation, this
-   * also removes the frame from the primary frame man and clears undisplayed
+   * also removes the frame from the primary frame map and clears undisplayed
    * content for its content node.
    * If the frame is a placeholder, it also ensures the out-of-flow frame's
    * removal and destruction.
    */
   void Destroy() { DestroyFrom(this); }
 
 protected:
   /**
--- a/layout/generic/nsILineIterator.h
+++ b/layout/generic/nsILineIterator.h
@@ -99,19 +99,22 @@ public:
   NS_IMETHOD GetLine(PRInt32 aLineNumber,
                      nsIFrame** aFirstFrameOnLine,
                      PRInt32* aNumFramesOnLine,
                      nsRect& aLineBounds,
                      PRUint32* aLineFlags) = 0;
 
   /**
    * Given a frame that's a child of the block, find which line its on
-   * and return that line index. Returns -1 if the frame cannot be found.
+   * and return that line index, as long as it's at least as big as
+   * aStartLine.  Returns -1 if the frame cannot be found on lines
+   * starting with aStartLine.
    */
-  virtual PRInt32 FindLineContaining(nsIFrame* aFrame) = 0;
+  virtual PRInt32 FindLineContaining(nsIFrame* aFrame,
+                                     PRInt32 aStartLine = 0) = 0;
 
   // Given a line number and an X coordinate, find the frame on the
   // line that is nearest to the X coordinate. The
   // aXIsBeforeFirstFrame and aXIsAfterLastFrame flags are updated
   // appropriately.
   NS_IMETHOD FindFrameAt(PRInt32 aLineNumber,
                          nscoord aX,
                          nsIFrame** aFrameFound,
--- a/layout/generic/nsImageMap.cpp
+++ b/layout/generic/nsImageMap.cpp
@@ -398,17 +398,17 @@ void RectArea::ParseCoords(const nsAStri
 
   if (!saneRect) {
     logMessage(mArea, aSpec, flag, "ImageMapRectBoundsError");
   }
 }
 
 PRBool RectArea::IsInside(nscoord x, nscoord y) const
 {
-  if (mNumCoords >= 4) {       // Note: > is for nav compatability
+  if (mNumCoords >= 4) {       // Note: > is for nav compatibility
     nscoord x1 = mCoords[0];
     nscoord y1 = mCoords[1];
     nscoord x2 = mCoords[2];
     nscoord y2 = mCoords[3];
     NS_ASSERTION(x1 <= x2 && y1 <= y2,
                  "Someone screwed up RectArea::ParseCoords");
     if ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2)) {
       return PR_TRUE;
@@ -633,17 +633,17 @@ void CircleArea::ParseCoords(const nsASt
                aSpec,
                flag,
                "ImageMapCircleWrongNumberOfCoords");
   }
 }
 
 PRBool CircleArea::IsInside(nscoord x, nscoord y) const
 {
-  // Note: > is for nav compatability
+  // Note: > is for nav compatibility
   if (mNumCoords >= 3) {
     nscoord x1 = mCoords[0];
     nscoord y1 = mCoords[1];
     nscoord radius = mCoords[2];
     if (radius < 0) {
       return PR_FALSE;
     }
     nscoord dx = x1 - x;
--- a/layout/generic/nsLineBox.cpp
+++ b/layout/generic/nsLineBox.cpp
@@ -621,25 +621,26 @@ nsLineIterator::GetLine(PRInt32 aLineNum
       flags |= NS_LINE_FLAG_ENDS_IN_BREAK;
   }
   *aLineFlags = flags;
 
   return NS_OK;
 }
 
 PRInt32
-nsLineIterator::FindLineContaining(nsIFrame* aFrame)
+nsLineIterator::FindLineContaining(nsIFrame* aFrame, PRInt32 aStartLine)
 {
-  nsLineBox* line = mLines[0];
-  PRInt32 lineNumber = 0;
+  NS_PRECONDITION(aStartLine <= mNumLines, "Bogus line numbers");
+  PRInt32 lineNumber = aStartLine;
   while (lineNumber != mNumLines) {
+    nsLineBox* line = mLines[lineNumber];
     if (line->Contains(aFrame)) {
       return lineNumber;
     }
-    line = mLines[++lineNumber];
+    ++lineNumber;
   }
   return -1;
 }
 
 #ifdef IBMBIDI
 NS_IMETHODIMP
 nsLineIterator::CheckLineOrder(PRInt32                  aLine,
                                PRBool                   *aIsReordered,
--- a/layout/generic/nsLineBox.h
+++ b/layout/generic/nsLineBox.h
@@ -1576,17 +1576,17 @@ public:
 
   virtual PRInt32 GetNumLines();
   virtual PRBool GetDirection();
   NS_IMETHOD GetLine(PRInt32 aLineNumber,
                      nsIFrame** aFirstFrameOnLine,
                      PRInt32* aNumFramesOnLine,
                      nsRect& aLineBounds,
                      PRUint32* aLineFlags);
-  virtual PRInt32 FindLineContaining(nsIFrame* aFrame);
+  virtual PRInt32 FindLineContaining(nsIFrame* aFrame, PRInt32 aStartLine = 0);
   NS_IMETHOD FindFrameAt(PRInt32 aLineNumber,
                          nscoord aX,
                          nsIFrame** aFrameFound,
                          PRBool* aXIsBeforeFirstFrame,
                          PRBool* aXIsAfterLastFrame);
 
   NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, PRInt32 aLineNumber);
 #ifdef IBMBIDI
new file mode 100644
--- /dev/null
+++ b/layout/reftests/editor/462758-grabbers-resizers-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+  <script type="text/javascript">
+    function init() {
+      var editor = document.querySelector("div[contenteditable]");
+      editor.addEventListener("focus", function() {
+        setTimeout(function() {
+          document.documentElement.className = "";
+        }, 0);
+      }, false);
+      editor.focus();
+    }
+  </script>
+  <style type="text/css">
+    html, body, div {
+      margin: 0;
+      padding: 0;
+    }
+    div {
+      border: 1px solid black;
+      margin: 50px;
+      height: 200px;
+      width: 200px;
+    }
+  </style>
+</head>
+<body onload="init()">
+  <div contenteditable>
+    this editable container should be neither draggable nor resizable.
+  </div>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/editor/462758-grabbers-resizers.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+  <script type="text/javascript">
+    function init() {
+      var editor = document.querySelector("div[contenteditable]");
+      editor.addEventListener("focus", function() {
+        setTimeout(function() {
+          document.documentElement.className = "";
+        }, 0);
+      }, false);
+      editor.focus();
+    }
+  </script>
+  <style type="text/css">
+    html, body, div {
+      margin: 0;
+      padding: 0;
+    }
+    div {
+      border: 1px solid black;
+      margin: 50px;
+      height: 200px;
+      width: 200px;
+    }
+  </style>
+</head>
+<body onload="init()">
+  <div contenteditable style="position: absolute">
+    this editable container should be neither draggable nor resizable.
+  </div>
+</body>
+</html>
--- a/layout/reftests/editor/reftest.list
+++ b/layout/reftests/editor/reftest.list
@@ -63,8 +63,9 @@ fails-if(Android) != spellcheck-hyphen-m
 == selection_visibility_after_reframe.html selection_visibility_after_reframe-ref.html
 != selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html
 != selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html
 == 672709.html 672709-ref.html
 == 338427-1.html 338427-1-ref.html
 skip-if(Android) == 674212-spellcheck.html 674212-spellcheck-ref.html
 skip-if(Android) == 338427-2.html 338427-2-ref.html
 skip-if(Android) == 338427-3.html 338427-3-ref.html
+skip-if(Android) == 462758-grabbers-resizers.html 462758-grabbers-resizers-ref.html
--- a/layout/reftests/font-matching/reftest.list
+++ b/layout/reftests/font-matching/reftest.list
@@ -57,11 +57,16 @@ HTTP(..) != normalmedium.html normalmedi
 HTTP(..) == weightmapping-12.html weightmapping-12-ref.html
 HTTP(..) == weightmapping-25.html weightmapping-25-ref.html
 HTTP(..) == weightmapping-45.html weightmapping-45-ref.html
 HTTP(..) == weightmapping-458.html weightmapping-458-ref.html
 HTTP(..) == weightmapping-478.html weightmapping-478-ref.html
 HTTP(..) == weightmapping-7.html weightmapping-7-ref.html
 HTTP(..) == weightmapping-12579.html weightmapping-12579-ref.html
 
+HTTP(..) == stretchmapping-all.html stretchmapping-all-ref.html
+HTTP(..) == stretchmapping-reverse.html stretchmapping-reverse-ref.html
+HTTP(..) == stretchmapping-35.html stretchmapping-35-ref.html
+HTTP(..) == stretchmapping-137.html stretchmapping-137-ref.html
+
 # test for font-stretch using @font-face
 HTTP(..) == font-stretch-1.html font-stretch-1-ref.html
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-137-ref.html
@@ -0,0 +1,348 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch mapping tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Verdana, sans-serif;
+}
+
+h3, h4 { font-weight: normal; }
+
+table {
+  border-collapse: collapse;
+  font-size: 28px;
+}
+
+td {
+  padding: 0; margin: 0;
+  font-family: test;
+}
+
+th {
+  font-weight: inherit;
+}
+
+p { width: 300px; }
+
+.red { color: red; }
+
+thead { font-weight: 400; font-size: 75%; }
+
+/* make all the spans blocks to avoid influence of what's outside them
+   on line-height calculations */
+span { display: block; }
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test100;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+}
+
+@font-face {
+  font-family: test200;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test400;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+}
+
+@font-face {
+  font-family: test500;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test800;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+}
+
+@font-face {
+  font-family: test900;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+}
+
+.w1 { font-weight: 100; }
+.w2 { font-weight: 200; }
+.w3 { font-weight: 300; }
+.w4 { font-weight: 400; }
+.w5 { font-weight: 500; }
+.w6 { font-weight: 600; }
+.w7 { font-weight: 700; }
+.w8 { font-weight: 800; }
+.w9 { font-weight: 900; }
+
+.w1 .fs1 { font-family: test100; }
+.w2 .fs1 { font-family: test100; }
+.w3 .fs1 { font-family: test100; }
+.w4 .fs1 { font-family: test400; }
+.w5 .fs1 { font-family: test400; }
+.w6 .fs1 { font-family: test400; }
+.w7 .fs1 { font-family: test400; }
+.w8 .fs1 { font-family: test400; }
+.w9 .fs1 { font-family: test400; }
+
+.w1 .fs2 { font-family: test100; }
+.w2 .fs2 { font-family: test100; }
+.w3 .fs2 { font-family: test100; }
+.w4 .fs2 { font-family: test400; }
+.w5 .fs2 { font-family: test400; }
+.w6 .fs2 { font-family: test400; }
+.w7 .fs2 { font-family: test400; }
+.w8 .fs2 { font-family: test400; }
+.w9 .fs2 { font-family: test400; }
+
+.w1 .fs3 { font-family: test200; }
+.w2 .fs3 { font-family: test200; }
+.w3 .fs3 { font-family: test200; }
+.w4 .fs3 { font-family: test200; }
+.w5 .fs3 { font-family: test200; }
+.w6 .fs3 { font-family: test800; }
+.w7 .fs3 { font-family: test800; }
+.w8 .fs3 { font-family: test800; }
+.w9 .fs3 { font-family: test800; }
+
+.w1 .fs4 { font-family: test200; }
+.w2 .fs4 { font-family: test200; }
+.w3 .fs4 { font-family: test200; }
+.w4 .fs4 { font-family: test200; }
+.w5 .fs4 { font-family: test200; }
+.w6 .fs4 { font-family: test800; }
+.w7 .fs4 { font-family: test800; }
+.w8 .fs4 { font-family: test800; }
+.w9 .fs4 { font-family: test800; }
+
+.w1 .fs5 { font-family: test200; }
+.w2 .fs5 { font-family: test200; }
+.w3 .fs5 { font-family: test200; }
+.w4 .fs5 { font-family: test200; }
+.w5 .fs5 { font-family: test200; }
+.w6 .fs5 { font-family: test800; }
+.w7 .fs5 { font-family: test800; }
+.w8 .fs5 { font-family: test800; }
+.w9 .fs5 { font-family: test800; }
+
+.w1 .fs6 { font-family: test500; }
+.w2 .fs6 { font-family: test500; }
+.w3 .fs6 { font-family: test500; }
+.w4 .fs6 { font-family: test500; }
+.w5 .fs6 { font-family: test500; }
+.w6 .fs6 { font-family: test900; }
+.w7 .fs6 { font-family: test900; }
+.w8 .fs6 { font-family: test900; }
+.w9 .fs6 { font-family: test900; }
+
+.w1 .fs7 { font-family: test500; }
+.w2 .fs7 { font-family: test500; }
+.w3 .fs7 { font-family: test500; }
+.w4 .fs7 { font-family: test500; }
+.w5 .fs7 { font-family: test500; }
+.w6 .fs7 { font-family: test900; }
+.w7 .fs7 { font-family: test900; }
+.w8 .fs7 { font-family: test900; }
+.w9 .fs7 { font-family: test900; }
+
+.w1 .fs8 { font-family: test500; }
+.w2 .fs8 { font-family: test500; }
+.w3 .fs8 { font-family: test500; }
+.w4 .fs8 { font-family: test500; }
+.w5 .fs8 { font-family: test500; }
+.w6 .fs8 { font-family: test900; }
+.w7 .fs8 { font-family: test900; }
+.w8 .fs8 { font-family: test900; }
+.w9 .fs8 { font-family: test900; }
+
+.w1 .fs9 { font-family: test500; }
+.w2 .fs9 { font-family: test500; }
+.w3 .fs9 { font-family: test500; }
+.w4 .fs9 { font-family: test500; }
+.w5 .fs9 { font-family: test500; }
+.w6 .fs9 { font-family: test900; }
+.w7 .fs9 { font-family: test900; }
+.w8 .fs9 { font-family: test900; }
+.w9 .fs9 { font-family: test900; }
+
+</style>
+</head>
+<body>
+
+<p>Font family with ultra-condensed 100, 400, condensed 200, 800 and expanded 500, 900</p>
+
+<table>
+<thead>
+<th></th>
+<th class="red">1</th>
+<th>2</th>
+<th class="red">3</th>
+<th>4</th>
+<th>5</th>
+<th>6</th>
+<th class="red">7</th>
+<th>8</th>
+<th>9</th>
+</thead>
+<tr class="w1">
+<th>100</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w2">
+<th>200</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w3">
+<th>300</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w4">
+<th>400</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w5">
+<th>500</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w6">
+<th>600</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w7">
+<th>700</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w8">
+<th>800</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w9">
+<th>900</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+</table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/stretchmapping-137.html
@@ -0,0 +1,268 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>font-stretch mapping tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+<style type="text/css">
+
+body {
+  margin: 50px;
+  font-family: Verdana, sans-serif;
+}
+
+h3, h4 { font-weight: normal; }
+
+table {
+  border-collapse: collapse;
+  font-size: 28px;
+}
+
+td {
+  padding: 0; margin: 0;
+  font-family: test;
+}
+
+th {
+  font-weight: inherit;
+}
+
+p { width: 300px; }
+
+.red { color: red; }
+
+thead { font-weight: 400; font-size: 75%; }
+
+/* make all the spans blocks to avoid influence of what's outside them
+   on line-height calculations */
+span { display: block; }
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+  font-stretch: ultra-condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+  font-stretch: condensed;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+  font-stretch: expanded;
+}
+
+@font-face {
+  font-family: test100;
+  src: url(../fonts/mplus/mplus-1p-thin.ttf);
+  font-weight: 100;
+}
+
+@font-face {
+  font-family: test200;
+  src: url(../fonts/mplus/mplus-1p-light.ttf);
+  font-weight: 200;
+}
+
+@font-face {
+  font-family: test400;
+  src: url(../fonts/mplus/mplus-1p-regular.ttf);
+  font-weight: 400;
+}
+
+@font-face {
+  font-family: test500;
+  src: url(../fonts/mplus/mplus-1p-medium.ttf);
+  font-weight: 500;
+}
+
+@font-face {
+  font-family: test800;
+  src: url(../fonts/mplus/mplus-1p-heavy.ttf);
+  font-weight: 800;
+}
+
+@font-face {
+  font-family: test900;
+  src: url(../fonts/mplus/mplus-1p-black.ttf);
+  font-weight: 900;
+}
+
+.w1 { font-weight: 100; }
+.w2 { font-weight: 200; }
+.w3 { font-weight: 300; }
+.w4 { font-weight: 400; }
+.w5 { font-weight: 500; }
+.w6 { font-weight: 600; }
+.w7 { font-weight: 700; }
+.w8 { font-weight: 800; }
+.w9 { font-weight: 900; }
+
+.fs1 { font-stretch: ultra-condensed; }
+.fs2 { font-stretch: extra-condensed; }
+.fs3 { font-stretch: condensed; }
+.fs4 { font-stretch: semi-condensed; }
+.fs5 { font-stretch: normal; }
+.fs6 { font-stretch: semi-expanded; }
+.fs7 { font-stretch: expanded; }
+.fs8 { font-stretch: extra-expanded; }
+.fs9 { font-stretch: ultra-expanded; }
+
+</style>
+</head>
+<body>
+
+<p>Font family with ultra-condensed 100, 400, condensed 200, 800 and expanded 500, 900</p>
+
+<table>
+<thead>
+<th></th>
+<th class="red">1</th>
+<th>2</th>
+<th class="red">3</th>
+<th>4</th>
+<th>5</th>
+<th>6</th>
+<th class="red">7</th>
+<th>8</th>
+<th>9</th>
+</thead>
+<tr class="w1">
+<th>100</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w2">
+<th>200</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w3">
+<th>300</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w4">
+<th>400</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w5">
+<th>500</th>
+<td class="fs1"><span>か</span></td>
+<td class="fs2"><span>か</span></td>
+<td class="fs3"><span>か</span></td>
+<td class="fs4"><span>か</span></td>
+<td class="fs5"><span>か</span></td>
+<td class="fs6"><span>か</span></td>
+<td class="fs7"><span>か</span></td>
+<td class="fs8"><span>か</span></td>
+<td class="fs9"><span>か</span></td>
+</tr>
+<tr class="w6">