Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Tue, 29 Nov 2011 11:56:13 -0800
changeset 84608 9aa7d346ae56c1f6f58b5542e03549ae50e88ee4
parent 84607 9dc80d92e1f31f69235b2a461578659113616a41 (current diff)
parent 82571 4c3b8d006a0d9c44dbc43227c0720bb2ca4572ea (diff)
child 84609 81b802ef7ebc06a2df0cdc1aa70fba035404cbc5
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to s-c.
browser/themes/gnomestripe/feeds/audioFeedIcon.png
browser/themes/gnomestripe/feeds/audioFeedIcon16.png
browser/themes/gnomestripe/feeds/videoFeedIcon.png
browser/themes/gnomestripe/feeds/videoFeedIcon16.png
browser/themes/pinstripe/feeds/audioFeedIcon.png
browser/themes/pinstripe/feeds/audioFeedIcon16.png
browser/themes/pinstripe/feeds/videoFeedIcon.png
browser/themes/pinstripe/feeds/videoFeedIcon16.png
browser/themes/winstripe/aboutSessionRestore-window-icon.png
browser/themes/winstripe/feeds/audioFeedIcon-aero.png
browser/themes/winstripe/feeds/audioFeedIcon.png
browser/themes/winstripe/feeds/audioFeedIcon16-aero.png
browser/themes/winstripe/feeds/audioFeedIcon16.png
browser/themes/winstripe/feeds/videoFeedIcon-aero.png
browser/themes/winstripe/feeds/videoFeedIcon.png
browser/themes/winstripe/feeds/videoFeedIcon16-aero.png
browser/themes/winstripe/feeds/videoFeedIcon16.png
browser/themes/winstripe/places/searching_16-aero.png
browser/themes/winstripe/preferences/plugin-aero.png
dom/interfaces/base/nsIAnimationFrameListener.idl
layout/xul/base/src/tree/src/nsITreeImageListener.h
toolkit/components/places/nsIDynamicContainer.idl
toolkit/components/places/tests/unit/nsDynamicContainerServiceSample.js
toolkit/components/places/tests/unit/nsDynamicContainerServiceSample.manifest
toolkit/components/places/tests/unit/test_457698_crash.js
toolkit/components/places/tests/unit/test_dynamic_containers.js
toolkit/themes/gnomestripe/mozapps/extensions/category-extensions.png
toolkit/themes/gnomestripe/mozapps/extensions/category-languages.png
toolkit/themes/gnomestripe/mozapps/extensions/category-themes.png
toolkit/themes/gnomestripe/mozapps/passwordmgr/key.png
toolkit/themes/gnomestripe/mozapps/places/tagContainerIcon.png
toolkit/themes/gnomestripe/mozapps/plugins/pluginOutdated-16.png
toolkit/themes/pinstripe/global/dirListing/local.png
toolkit/themes/pinstripe/global/notification/question-icon.png
toolkit/themes/pinstripe/mozapps/extensions/category-extensions.png
toolkit/themes/pinstripe/mozapps/extensions/category-languages.png
toolkit/themes/pinstripe/mozapps/extensions/category-themes.png
toolkit/themes/pinstripe/mozapps/places/tagContainerIcon.png
toolkit/themes/winstripe/global/arrow/arrow-lft-hov.gif
toolkit/themes/winstripe/global/arrow/arrow-rit-hov.gif
toolkit/themes/winstripe/global/console/bullet-error-aero.png
toolkit/themes/winstripe/global/console/bullet-error.png
toolkit/themes/winstripe/global/console/bullet-question-aero.png
toolkit/themes/winstripe/global/console/bullet-question.png
toolkit/themes/winstripe/global/console/bullet-warning-aero.png
toolkit/themes/winstripe/global/console/bullet-warning.png
toolkit/themes/winstripe/global/icons/informationBar-30-aero.png
toolkit/themes/winstripe/global/icons/informationBar-30.png
toolkit/themes/winstripe/global/icons/informationBar-60-aero.png
toolkit/themes/winstripe/global/icons/informationBar-60.png
toolkit/themes/winstripe/global/icons/loading_16-aero.png
toolkit/themes/winstripe/global/icons/notfound-aero.png
toolkit/themes/winstripe/global/icons/notfound.png
toolkit/themes/winstripe/global/icons/notloading_16-aero.png
toolkit/themes/winstripe/global/icons/questionBar-30-aero.png
toolkit/themes/winstripe/global/icons/questionBar-30.png
toolkit/themes/winstripe/global/icons/questionBar-60-aero.png
toolkit/themes/winstripe/global/icons/questionBar-60.png
toolkit/themes/winstripe/mozapps/extensions/category-extensions-aero.png
toolkit/themes/winstripe/mozapps/extensions/category-extensions.png
toolkit/themes/winstripe/mozapps/extensions/category-languages-aero.png
toolkit/themes/winstripe/mozapps/extensions/category-languages.png
toolkit/themes/winstripe/mozapps/extensions/category-themes-aero.png
toolkit/themes/winstripe/mozapps/extensions/category-themes.png
toolkit/themes/winstripe/mozapps/places/tagContainerIcon-aero.png
toolkit/themes/winstripe/mozapps/places/tagContainerIcon.png
toolkit/themes/winstripe/mozapps/plugins/pluginFinderWizard.css
toolkit/themes/winstripe/mozapps/plugins/pluginHelp-16-aero.png
toolkit/themes/winstripe/mozapps/plugins/pluginOutdated-16-aero.png
toolkit/themes/winstripe/mozapps/plugins/pluginOutdated-16.png
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -7,16 +7,17 @@ builtin(include, build/autoconf/glib.m4)
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/nss.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/freetype2.m4)dnl
 builtin(include, build/autoconf/codeset.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
+builtin(include, build/autoconf/mozcommonheader.m4)dnl
 builtin(include, build/autoconf/acwinpaths.m4)dnl
 builtin(include, build/autoconf/lto.m4)dnl
 builtin(include, build/autoconf/gcc-pr49911.m4)dnl
 builtin(include, build/autoconf/frameptr.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
 
 # Read the user's .mozconfig script.  We can't do this in
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3476,17 +3476,16 @@ const BrowserSearch = {
     // SearchService._addEngineToStore() should fail for such an engine),
     // but let's be on the safe side.
     if (!submission)
       return;
 
     openLinkIn(submission.uri.spec,
                useNewTab ? "tab" : "current",
                { postData: submission.postData,
-                 inBackground: false,
                  relatedToCurrent: true });
   },
 
   /**
    * Returns the search bar element if it is present in the toolbar, null otherwise.
    */
   get searchBar() {
     return document.getElementById("searchbar");
@@ -3946,16 +3945,19 @@ var FullScreen = {
     let focusManger = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
     if (focusManger.activeWindow != window) {
       // The top-level window has lost focus since the request to enter
       // full-screen was made. Cancel full-screen.
       document.mozCancelFullScreen();
       return;
     }
 
+    if (gFindBarInitialized)
+      gFindBar.close();
+
     this.showWarning(true);
 
     // Exit DOM full-screen mode upon open, close, or change tab.
     gBrowser.tabContainer.addEventListener("TabOpen", this.exitDomFullScreen);
     gBrowser.tabContainer.addEventListener("TabClose", this.exitDomFullScreen);
     gBrowser.tabContainer.addEventListener("TabSelect", this.exitDomFullScreen);
 
     // Exit DOM full-screen mode when the browser window loses focus (ALT+TAB, etc).
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -335,16 +335,19 @@ var MigrationWizard = {
         source = "sourceNameIE";
         break;
       case "opera":
         source = "sourceNameOpera";
         break;
       case "safari":
         source = "sourceNameSafari";
         break;
+      case "chrome":
+        source = "sourceNameChrome";
+        break;
     }
 
     // semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
     this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
 
     var oldHomePageURL = this._migrator.sourceHomePageURL;
 
     if (oldHomePageURL && source) {
--- a/browser/components/migration/content/migration.xul
+++ b/browser/components/migration/content/migration.xul
@@ -74,16 +74,17 @@
 #elifdef XP_UNIX
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
 #elifdef XP_WIN
 #ifndef NO_IE_MIGRATOR
       <radio id="ie"        label="&importFromIE.label;"        accesskey="&importFromIE.accesskey;"/>
 #endif
       <radio id="opera"     label="&importFromOpera.label;"     accesskey="&importFromOpera.accesskey;"/>
 #endif
+      <radio id="chrome"    label="&importFromChrome.label;"    accesskey="&importFromChrome.accesskey;"/>
       <radio id="fromfile"  label="&importFromHTMLFile.label;"  accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
       <radio id="nothing"   label="&importFromNothing.label;"   accesskey="&importFromNothing.accesskey;" hidden="true"/>
     </radiogroup>
     <label id="noSources" hidden="true">&noMigrationSources.label;</label>
   </wizardpage>
 
   <wizardpage id="selectProfile" pageid="selectProfile" label="&selectProfile.title;"
               next="importItems"
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/src/BrowserProfileMigrators.manifest
@@ -0,0 +1,2 @@
+component {4cec1de4-1671-4fc3-a53e-6c539dc77a26} ChromeProfileMigrator.js
+contract @mozilla.org/profile/migrator;1?app=browser&type=chrome {4cec1de4-1671-4fc3-a53e-6c539dc77a26}
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/src/ChromeProfileMigrator.js
@@ -0,0 +1,532 @@
+/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 et
+ * ***** 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 the Browser Profile Migrator.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Makoto Kato <m_kato@ga2.so-net.ne.jp> (Original Author)
+ *
+ * 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 ***** */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+const LOCAL_FILE_CID = "@mozilla.org/file/local;1";
+const FILE_INPUT_STREAM_CID = "@mozilla.org/network/file-input-stream;1";
+
+const BUNDLE_MIGRATION = "chrome://browser/locale/migration/migration.properties";
+
+const MIGRATE_ALL = 0x0000;
+const MIGRATE_SETTINGS = 0x0001;
+const MIGRATE_COOKIES = 0x0002;
+const MIGRATE_HISTORY = 0x0004;
+const MIGRATE_FORMDATA = 0x0008;
+const MIGRATE_PASSWORDS = 0x0010;
+const MIGRATE_BOOKMARKS = 0x0020;
+const MIGRATE_OTHERDATA = 0x0040;
+
+const S100NS_FROM1601TO1970 = 0x19DB1DED53E8000;
+const S100NS_PER_MS = 10;
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "bookmarksSubfolderTitle", function () {
+  // get "import from google chrome" string for folder
+  let strbundle =
+    Services.strings.createBundle(BUNDLE_MIGRATION);
+  let sourceNameChrome = strbundle.GetStringFromName("sourceNameChrome");
+  return strbundle.formatStringFromName("importedBookmarksFolder",
+                                        [sourceNameChrome],
+                                        1);
+});
+
+/*
+ * Convert Chrome time format to Date object
+ *
+ * @param   aTime
+ *          Chrome time 
+ * @return  converted Date object
+ * @note    Google Chrome uses FILETIME / 10 as time.
+ *          FILETIME is based on same structure of Windows.
+ */
+function chromeTimeToDate(aTime)
+{
+  return new Date((aTime * S100NS_PER_MS - S100NS_FROM1601TO1970 ) / 10000);
+}
+
+/*
+ * Insert bookmark items into specific folder.
+ *
+ * @param   aFolderId
+ *          id of folder where items will be inserted
+ * @param   aItems
+ *          bookmark items to be inserted
+ */
+function insertBookmarkItems(aFolderId, aItems)
+{
+  for (let i = 0; i < aItems.length; i++) {
+    let item = aItems[i];
+
+    try {
+      if (item.type == "url") {
+        PlacesUtils.bookmarks.insertBookmark(aFolderId,
+                                             NetUtil.newURI(item.url),
+                                             PlacesUtils.bookmarks.DEFAULT_INDEX,
+                                             item.name);
+      } else if (item.type == "folder") {
+        let newFolderId =
+          PlacesUtils.bookmarks.createFolder(aFolderId,
+                                             item.name,
+                                             PlacesUtils.bookmarks.DEFAULT_INDEX);
+
+        insertBookmarkItems(newFolderId, item.children);
+      }
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  }
+}
+
+function ChromeProfileMigrator()
+{
+}
+
+ChromeProfileMigrator.prototype = {
+  _paths: {
+    bookmarks : null,
+    cookies : null,
+    history : null,
+    prefs : null,
+  },
+
+  _homepageURL : null,
+  _replaceBookmarks : false,
+
+  /*
+   * Notify to observers to start migration
+   *
+   * @param   aType
+   *          notification type such as MIGRATE_BOOKMARKS
+   */
+
+  _notifyStart : function Chrome_notifyStart(aType)
+  {
+    Services.obs.notifyObservers(null, "Migration:ItemBeforeMigrate", aType);
+    this._pendingCount++;
+  },
+
+  /*
+   * Notify to observers to finish migration for item
+   * If all items are finished, it sends migration end notification.
+   *
+   * @param   aType
+   *          notification type such as MIGRATE_BOOKMARKS
+   */
+  _notifyCompleted : function Chrome_notifyIfCompleted(aType)
+  {
+    Services.obs.notifyObservers(null, "Migration:ItemAfterMigrate", aType);
+    if (--this._pendingCount == 0) {
+      // All items are migrated, so we have to send end notification.
+      Services.obs.notifyObservers(null, "Migration:Ended", null);
+    }
+  },
+
+  /*
+   * Migrating bookmark items
+   */
+  _migrateBookmarks : function Chrome_migrateBookmarks()
+  {
+    this._notifyStart(MIGRATE_BOOKMARKS);
+
+    try {
+      PlacesUtils.bookmarks.runInBatchMode({
+        _self : this,
+        runBatched : function (aUserData) {
+          let migrator = this._self;
+          let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+          file.initWithPath(migrator._paths.bookmarks);
+
+          NetUtil.asyncFetch(file, function(aInputStream, aResultCode) {
+            if (!Components.isSuccessCode(aResultCode)) {
+              migrator._notifyCompleted(MIGRATE_BOOKMARKS);
+              return;
+            }
+
+            // Parse Chrome bookmark file that is JSON format
+            let bookmarkJSON = NetUtil.readInputStreamToString(aInputStream,
+                                                               aInputStream.available(),
+                                                               { charset : "UTF-8" });
+            let roots = JSON.parse(bookmarkJSON).roots;
+
+            // Importing bookmark bar items
+            if (roots.bookmark_bar.children &&
+                roots.bookmark_bar.children.length > 0) {
+              // Toolbar
+              let parentId = PlacesUtils.toolbarFolderId;
+              if (!migrator._replaceBookmarks) { 
+                parentId =
+                  PlacesUtils.bookmarks.createFolder(parentId,
+                                                     bookmarksSubfolderTitle,
+                                                     PlacesUtils.bookmarks.DEFAULT_INDEX);
+              }
+              insertBookmarkItems(parentId, roots.bookmark_bar.children);
+            }
+
+            // Importing bookmark menu items
+            if (roots.other.children &&
+                roots.other.children.length > 0) {
+              // Bookmark menu
+              let parentId = PlacesUtils.bookmarksMenuFolderId;
+              if (!migrator._replaceBookmarks) { 
+                parentId =
+                  PlacesUtils.bookmarks.createFolder(parentId,
+                                                     bookmarksSubfolderTitle,
+                                                     PlacesUtils.bookmarks.DEFAULT_INDEX);
+              }
+              insertBookmarkItems(parentId, roots.other.children);
+            }
+
+            migrator._notifyCompleted(MIGRATE_BOOKMARKS);
+          });
+        }
+      }, null);
+    } catch (e) {
+      Cu.reportError(e);
+      this._notifyCompleted(MIGRATE_BOOKMARKS);
+    }
+  },
+
+  /*
+   * Migrating history
+   */
+  _migrateHistory : function Chrome_migrateHistory()
+  {
+    this._notifyStart(MIGRATE_HISTORY);
+
+    try {
+      PlacesUtils.history.runInBatchMode({
+        _self : this,
+        runBatched : function (aUserData) {
+          // access sqlite3 database of Chrome's history
+          let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+          file.initWithPath(this._self._paths.history);
+
+          let dbConn = Services.storage.openUnsharedDatabase(file);
+          let stmt = dbConn.createAsyncStatement(
+              "SELECT url, title, last_visit_time, typed_count FROM urls WHERE hidden = 0");
+
+          stmt.executeAsync({
+            _asyncHistory : Cc["@mozilla.org/browser/history;1"]
+                            .getService(Ci.mozIAsyncHistory),
+            _db : dbConn,
+            _self : this._self,
+            handleResult : function(aResults) {
+              let places = [];
+              for (let row = aResults.getNextRow(); row; row = aResults.getNextRow()) {
+                try {
+                  // if having typed_count, we changes transition type to typed.
+                  let transType = PlacesUtils.history.TRANSITION_LINK;
+                  if (row.getResultByName("typed_count") > 0)
+                    transType = PlacesUtils.history.TRANSITION_TYPED;
+
+                  places.push({
+                    uri: NetUtil.newURI(row.getResultByName("url")),
+                    title: row.getResultByName("title"),
+                    visits: [{
+                      transitionType: transType,
+                      visitDate: chromeTimeToDate(
+                                   row.getResultByName(
+                                     "last_visit_time")) * 1000,
+                    }],
+                  });
+                } catch (e) {
+                  Cu.reportError(e);
+                }
+              }
+
+              try {
+                this._asyncHistory.updatePlaces(places);
+              } catch (e) {
+                Cu.reportError(e);
+              }
+            },
+
+            handleError : function(aError) {
+              Cu.reportError("Async statement execution returned with '" +
+                             aError.result + "', '" + aError.message + "'");
+            },
+
+            handleCompletion : function(aReason) {
+              this._db.asyncClose();
+              this._self._notifyCompleted(MIGRATE_HISTORY);
+            }
+          });
+          stmt.finalize();
+        }
+      }, null);
+    } catch (e) {
+      Cu.reportError(e);
+      this._notifyCompleted(MIGRATE_HISTORY);
+    }
+  },
+
+  /*
+   * Migrating cookies
+   */
+  _migrateCookies : function Chrome_migrateCookies()
+  {
+    this._notifyStart(MIGRATE_COOKIES);
+
+    try {
+      // Access sqlite3 database of Chrome's cookie
+      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+      file.initWithPath(this._paths.cookies);
+
+      let dbConn = Services.storage.openUnsharedDatabase(file);
+      let stmt = dbConn.createAsyncStatement(
+          "SELECT host_key, path, name, value, secure, httponly, expires_utc FROM cookies");
+
+      stmt.executeAsync({
+        _db : dbConn,
+        _self : this,
+        handleResult : function(aResults) {
+          for (let row = aResults.getNextRow(); row; row = aResults.getNextRow()) {
+            let host_key = row.getResultByName("host_key");
+            if (host_key.match(/^\./)) {
+              // 1st character of host_key may be ".", so we have to remove it
+              host_key = host_key.substr(1);
+            }
+
+            try {
+              let expiresUtc =
+                chromeTimeToDate(row.getResultByName("expires_utc")) / 1000;
+              Services.cookies.add(host_key,
+                                   row.getResultByName("path"),
+                                   row.getResultByName("name"),
+                                   row.getResultByName("value"),
+                                   row.getResultByName("secure"),
+                                   row.getResultByName("httponly"),
+                                   false,
+                                   parseInt(expiresUtc));
+            } catch (e) {
+              Cu.reportError(e);
+            }
+          }
+        },
+
+        handleError : function(aError) {
+          Cu.reportError("Async statement execution returned with '" +
+                         aError.result + "', '" + aError.message + "'");
+        },
+
+        handleCompletion : function(aReason) {
+          this._db.asyncClose();
+          this._self._notifyCompleted(MIGRATE_COOKIES);
+        },
+      });
+      stmt.finalize();
+    } catch (e) {
+      Cu.reportError(e);
+      this._notifyCompleted(MIGRATE_COOKIES);
+    }
+  },
+
+  /*
+   * nsIBrowserProfileMigrator interface implementation
+   */
+
+  /*
+   * Let's migrate all items
+   *
+   * @param   aItems
+   *          list of data items to migrate.  but this is unused.
+   * @param   aStartup
+   *          non-null if called during startup.
+   * @param   aProfile
+   *          this is unused due to single profile support only
+   */
+  migrate : function Chrome_migrate(aItems, aStartup, aProfile)
+  {
+    if (aStartup) {
+      aStartup.doStartup();
+      this._replaceBookmarks = true;
+    }
+
+    Services.obs.notifyObservers(null, "Migration:Started", null);
+
+    // Reset panding count.  If this count becomes 0, "Migration:Ended"
+    // notification is sent
+    this._pendingCount = 1;
+
+    if (aItems & MIGRATE_HISTORY)
+      this._migrateHistory();
+
+    if (aItems & MIGRATE_COOKIES)
+      this._migrateCookies();
+
+    if (aItems & MIGRATE_BOOKMARKS)
+      this._migrateBookmarks();
+
+    if (--this._pendingCount == 0) {
+      // When async imports are immeditelly completed unfortunately,
+      // this will be called.
+      // Usually, this notification is sent by _notifyCompleted()
+      Services.obs.notifyObservers(null, "Migration:Ended", null);
+    }
+  },
+
+  /*
+   * return supported migration types
+   *
+   * @param   aProfile
+   *          this is unused due to single profile support only
+   * @param   aDoingStartup
+   *          non-null if called during startup.
+   * @return  supported migration types
+   */
+  getMigrateData: function Chrome_getMigrateData(aProfile, aDoingStartup)
+  {
+#ifdef XP_WIN
+    let chromepath = Services.dirsvc.get("LocalAppData", Ci.nsIFile).path +
+                     "\\Google\\Chrome\\User Data\\Default\\";
+#elifdef XP_MACOSX
+    let chromepath = Services.dirsvc.get("Home", Ci.nsIFile).path +
+                     "/Library/Application Support/Google/Chrome/Default/";
+#else
+    let chromepath = Services.dirsvc.get("Home", Ci.nsIFile).path +
+                     "/.config/google-chrome/Default/";
+#endif
+
+    let result = 0;
+
+    // bookmark and preference are JSON format
+
+    try {
+      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+      file.initWithPath(chromepath + "Bookmarks");
+      if (file.exists()) {
+        this._paths.bookmarks = file.path
+        result += MIGRATE_BOOKMARKS;
+      }
+    } catch (e) {
+      Cu.reportError(e);
+    }
+
+    if (!this._paths.prefs)
+      this._paths.prefs = chromepath + "Preferences";
+
+    // history and cookies are SQLite database
+
+    try {
+      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+      file.initWithPath(chromepath + "History");
+      if (file.exists()) {
+        this._paths.history = file.path
+        result += MIGRATE_HISTORY;
+      }
+    } catch (e) {
+      Cu.reportError(e);
+    }
+
+    try {
+      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+      file.initWithPath(chromepath + "Cookies");
+      if (file.exists()) {
+        this._paths.cookies = file.path
+        result += MIGRATE_COOKIES;
+      }
+    } catch (e) {
+      Cu.reportError(e);
+    }
+
+    return result;
+  },
+
+  /*
+   * Whether we support migration of Chrome
+   *
+   * @return true if supported
+   */
+  sourceExists: function Chrome_sourceExists()
+  {
+    let result = this.getMigrateData(null, false);
+    return result != 0;
+  },
+
+  // Although Chrome supports multi-profiles, there is no way
+  // to get profile lists.
+  sourceHasMultipleProfiles: false,
+  sourceProfiles: null,
+
+  /*
+   * Return home page URL
+   *
+   * @return  home page URL
+   */
+  sourceHomePageURL: function Chrome_sourceHomePageURL()
+  {
+    try  {
+      if (this._homepageURL)
+        return this._homepageURL;
+
+      if (!this._paths.prefs)
+        this.getMigrateData(null, false);
+
+      // XXX reading and parsing JSON is synchronous.
+      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+      file.initWithPath(this._paths.prefs);
+      let fstream = Cc[FILE_INPUT_STREAM_CID].
+                    createInstance(Ci.nsIFileInputStream);
+      fstream.init(file, -1, 0, 0); 
+      this._homepageURL = JSON.parse(
+        NetUtil.readInputStreamToString(fstream, fstream.available(),
+                                        { charset: "UTF-8" })).homepage;
+      return this._homepageURL;
+    } catch (e) {
+      Cu.reportError(e);
+    }
+    return "";
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([
+    Ci.nsIBrowserProfileMigrator
+  ]),
+
+  classDescription: "Chrome Profile Migrator",
+  contractID: "@mozilla.org/profile/migrator;1?app=browser&type=chrome",
+  classID: Components.ID("{4cec1de4-1671-4fc3-a53e-6c539dc77a26}")
+};
+
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([ChromeProfileMigrator]);
--- a/browser/components/migration/src/Makefile.in
+++ b/browser/components/migration/src/Makefile.in
@@ -62,10 +62,18 @@ CPPSRCS += nsIEProfileMigrator.cpp \
            $(NULL)
 endif
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += nsSafariProfileMigrator.cpp \
            $(NULL)
 endif            
 
+EXTRA_PP_COMPONENTS = \
+  ChromeProfileMigrator.js \
+  $(NULL)
+
+EXTRA_COMPONENTS = \
+	BrowserProfileMigrators.manifest \
+	$(NULL)
+
 include $(topsrcdir)/config/rules.mk
 
--- a/browser/components/migration/src/nsProfileMigrator.cpp
+++ b/browser/components/migration/src/nsProfileMigrator.cpp
@@ -158,16 +158,17 @@ nsProfileMigrator::Import()
 
 NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
 
 #ifdef XP_WIN
 
 #define INTERNAL_NAME_IEXPLORE        "iexplore"
 #define INTERNAL_NAME_MOZILLA_SUITE   "apprunner"
 #define INTERNAL_NAME_OPERA           "opera"
+#define INTERNAL_NAME_CHROME          "chrome"
 #endif
 
 nsresult
 nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
                                                 nsCOMPtr<nsIBrowserProfileMigrator>& bpm)
 {
 #if XP_WIN
 
@@ -241,32 +242,37 @@ nsProfileMigrator::GetDefaultBrowserMigr
   if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_IEXPLORE)) {
     aKey = "ie";
     return NS_OK;
   }
   else if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_OPERA)) {
     aKey = "opera";
     return NS_OK;
   }
+  else if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_CHROME)) {
+    aKey = "chrome";
+    return NS_OK;
+  }
 
 #else
   bool exists = false;
 #define CHECK_MIGRATOR(browser) do {\
   bpm = do_CreateInstance(NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX browser);\
   if (bpm)\
     bpm->GetSourceExists(&exists);\
   if (exists) {\
     aKey = browser;\
     return NS_OK;\
   }} while(0)
 
 #if defined(XP_MACOSX)
   CHECK_MIGRATOR("safari");
 #endif
   CHECK_MIGRATOR("opera");
+  CHECK_MIGRATOR("chrome");
 
 #undef CHECK_MIGRATOR
 #endif
   return NS_ERROR_FAILURE;
 }
 
 bool
 nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName)
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -442,17 +442,16 @@ PlacesController.prototype = {
    * Gathers information about the selected nodes according to the following
    * rules:
    *    "link"              node is a URI
    *    "bookmark"          node is a bookamrk
    *    "livemarkChild"     node is a child of a livemark
    *    "tagChild"          node is a child of a tag
    *    "folder"            node is a folder
    *    "query"             node is a query
-   *    "dynamiccontainer"  node is a dynamic container
    *    "separator"         node is a separator line
    *    "host"              node is a host
    *
    * @returns an array of objects corresponding the selected nodes. Each
    *          object has each of the properties above set if its corresponding
    *          node matches the rule. In addition, the annotations names for each
    *          node are set on its corresponding object as properties.
    * Notes:
@@ -485,19 +484,16 @@ PlacesController.prototype = {
                 break;
               case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
               case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
                 nodeData["day"] = true;
                 break;
             }
           }
           break;
-        case Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER:
-          nodeData["dynamiccontainer"] = true;
-          break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER:
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT:
           nodeData["folder"] = true;
           break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR:
           nodeData["separator"] = true;
           break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI:
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -352,16 +352,18 @@
 @BINPATH@/components/satchel.manifest
 @BINPATH@/components/nsFormAutoComplete.js
 @BINPATH@/components/nsFormHistory.js
 @BINPATH@/components/nsInputListAutoComplete.js
 @BINPATH@/components/contentSecurityPolicy.manifest
 @BINPATH@/components/contentSecurityPolicy.js
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
+@BINPATH@/components/BrowserProfileMigrators.manifest
+@BINPATH@/components/ChromeProfileMigrator.js
 #ifdef XP_MACOSX
 @BINPATH@/components/libalerts_s.dylib
 #endif
 #ifdef MOZ_ENABLE_DBUS
 @BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
 #endif
 @BINPATH@/components/nsINIProcessor.manifest
 @BINPATH@/components/nsINIProcessor.js
--- a/browser/locales/en-US/chrome/browser/migration/migration.dtd
+++ b/browser/locales/en-US/chrome/browser/migration/migration.dtd
@@ -10,16 +10,18 @@
 <!ENTITY importFromNothing.label        "Don't import anything">
 <!ENTITY importFromNothing.accesskey    "D">
 <!ENTITY importFromSeamonkey.label      "Netscape 6, 7 or Mozilla 1.x">
 <!ENTITY importFromSeamonkey.accesskey  "N">
 <!ENTITY importFromOpera.label          "Opera">
 <!ENTITY importFromOpera.accesskey      "O">
 <!ENTITY importFromSafari.label         "Safari">
 <!ENTITY importFromSafari.accesskey     "S">
+<!ENTITY importFromChrome.label         "Chrome">
+<!ENTITY importFromChrome.accesskey     "C">
 <!ENTITY importFromHTMLFile.label       "From an HTML File">
 <!ENTITY importFromHTMLFile.accesskey   "F">
 
 <!ENTITY noMigrationSources.label       "No programs that contain bookmarks, history or password data could be found.">
 
 <!ENTITY importSource.title             "Import Settings and Data">
 <!ENTITY importItems.title              "Items to Import">
 <!ENTITY importItems.label              "Select which items to import:">
--- a/browser/locales/en-US/chrome/browser/migration/migration.properties
+++ b/browser/locales/en-US/chrome/browser/migration/migration.properties
@@ -1,54 +1,62 @@
 profileName_format=%S %S
 
 # Browser Specific
 sourceNameIE=Internet Explorer
 sourceNameSeamonkey=Netscape 6/7/Mozilla
 sourceNameOpera=Opera
 sourceNameSafari=Safari
+sourceNameChrome=Google Chrome
 
 importedBookmarksFolder=From %S
 importedSearchURLsFolder=Keyword Searches (From %S)
 importedSearchURLsTitle=Search on %S
 importedSearchUrlDesc=Type "%S <search query>" in the Location Bar to perform a search on %S.
 
 importedSeamonkeyBookmarksTitle=From Netscape 6/7/Mozilla
 importedSafariBookmarks=From Safari
 importedOperaHotlistTitle=From Opera
 importedOperaSearchUrls=Keyword Searches (From Opera)
 
 # Import Sources
 1_ie=Internet Options
 1_opera=Preferences
 1_seamonkey=Preferences
 1_safari=Preferences
+1_chrome=Preferences
 
 2_ie=Cookies
 2_opera=Cookies
 2_seamonkey=Cookies
 2_safari=Cookies
+2_chrome=Cookies
 
 4_ie=Browsing History
 4_opera=Browsing History
 4_seamonkey=Browsing History
 4_safari=Browsing History
+4_chrome=Browsing History
 
 8_ie=Saved Form History
 8_opera=Saved Form History
 8_seamonkey=Saved Form History
 8_safari=Saved Form History
+8_chrome=Saved Form History
 
 16_ie=Saved Passwords
 16_opera=Saved Passwords
 16_seamonkey=Saved Passwords
 16_safari=Saved Passwords
+16_chrome=Saved Passwords
 
 32_ie=Favorites
 32_opera=Bookmarks
 32_seamonkey=Bookmarks
 32_safari=Bookmarks
+32_chrome=Bookmarks
 
 64_ie=Other Data
 64_opera=Other Data
 64_seamonkey=Other Data
 64_safari=Other Data
+64_chrome=Other Data
 
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -217,17 +217,17 @@ menuitem.bookmark-item {
   list-style-image: url("chrome://browser/skin/places/livemark-item.png");
 }
 
 .bookmark-item[container][query] {
   list-style-image: url("chrome://browser/skin/places/query.png");
 }
 
 .bookmark-item[query][tagContainer] {
-  list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
+  list-style-image: url("chrome://browser/skin/places/tag.png");
 }
 
 .bookmark-item[query][dayContainer] {
   list-style-image: url("chrome://browser/skin/places/calendar.png");
 }
 
 .bookmark-item[query][hostContainer] {
   list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
deleted file mode 100644
index a788fffb00e59e3fff6931ad34cbc12a59f34254..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index f8536a4e1f9301b9d1304e575d17214325f9652f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index a788fffb00e59e3fff6931ad34cbc12a59f34254..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index f8536a4e1f9301b9d1304e575d17214325f9652f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -34,20 +34,20 @@ browser.jar:
   skin/classic/browser/Secure.png
   skin/classic/browser/Security-broken.png
   skin/classic/browser/setDesktopBackground.css
   skin/classic/browser/Toolbar.png
   skin/classic/browser/Toolbar-small.png
   skin/classic/browser/urlbar-arrow.png
   skin/classic/browser/feeds/feedIcon.png             (feeds/feedIcon.png)
   skin/classic/browser/feeds/feedIcon16.png           (feeds/feedIcon16.png)
-  skin/classic/browser/feeds/videoFeedIcon.png        (feeds/videoFeedIcon.png)
-  skin/classic/browser/feeds/videoFeedIcon16.png      (feeds/videoFeedIcon16.png)
-  skin/classic/browser/feeds/audioFeedIcon.png        (feeds/audioFeedIcon.png)
-  skin/classic/browser/feeds/audioFeedIcon16.png      (feeds/audioFeedIcon16.png)
+  skin/classic/browser/feeds/videoFeedIcon.png        (feeds/feedIcon.png)
+  skin/classic/browser/feeds/videoFeedIcon16.png      (feeds/feedIcon16.png)
+  skin/classic/browser/feeds/audioFeedIcon.png        (feeds/feedIcon.png)
+  skin/classic/browser/feeds/audioFeedIcon16.png      (feeds/feedIcon16.png)
   skin/classic/browser/feeds/subscribe.css            (feeds/subscribe.css)
   skin/classic/browser/feeds/subscribe-ui.css         (feeds/subscribe-ui.css)
   skin/classic/browser/places/bookmarksMenu.png       (places/bookmarksMenu.png)
   skin/classic/browser/places/bookmarksToolbar.png    (places/bookmarksToolbar.png)
   skin/classic/browser/places/calendar.png            (places/calendar.png)
 * skin/classic/browser/places/editBookmarkOverlay.css (places/editBookmarkOverlay.css)
   skin/classic/browser/places/livemark-item.png       (places/livemark-item.png)
   skin/classic/browser/places/pageStarred.png         (places/pageStarred.png)
--- a/browser/themes/gnomestripe/places/places.css
+++ b/browser/themes/gnomestripe/places/places.css
@@ -72,17 +72,17 @@ treechildren::-moz-tree-image(title, que
 
 treechildren::-moz-tree-image(query, OrganizerQuery_Downloads) {
   list-style-image: url("chrome://browser/skin/places/downloads.png");
   -moz-image-region: auto;
 }
 
 treechildren::-moz-tree-image(title, query, tagContainer),
 treechildren::-moz-tree-image(query, OrganizerQuery_Tags) {
-  list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
+  list-style-image: url("chrome://browser/skin/places/tag.png");
 }
 
 /* calendar icon for folders grouping items by date */
 treechildren::-moz-tree-image(title, query, dayContainer) {
   list-style-image: url("chrome://browser/skin/places/calendar.png");
 }
 
 treechildren::-moz-tree-image(title, query, hostContainer) {
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -237,17 +237,17 @@ toolbarbutton.bookmark-item > menupopup 
   list-style-image: url("chrome://browser/skin/page-livemarks.png");
 }
 
 .bookmark-item[query] {
   list-style-image: url("chrome://browser/skin/places/query.png");
 }
 
 .bookmark-item[query][tagContainer] {
-  list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
+  list-style-image: url("chrome://browser/skin/places/tag.png");
 }
 
 .bookmark-item[query][dayContainer] {
   list-style-image: url("chrome://browser/skin/places/history.png");
 }
 
 .bookmark-item[query][hostContainer] {
   list-style-image: url("chrome://global/skin/tree/folder.png");
@@ -1908,16 +1908,17 @@ toolbarbutton.chevron > .toolbarbutton-m
   box-shadow: @focusRingShadow@;
 }
 
 .tabbrowser-tab:not([selected="true"]):not(:hover):not(:-moz-lwtheme) {
   color: #222;
 }
 
 .tabbrowser-tab[selected="true"] {
+  color: #000;
   z-index: 1;
   position: relative;
 }
 
 .tabbrowser-tab:-moz-lwtheme {
   color: inherit;
   text-shadow: inherit;
 }
deleted file mode 100644
index 236b5f82106ed4e9f74eff40a29ee36701a894c2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index a489de3bf858b6ea84d1470c17ab157f50adc01d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 236b5f82106ed4e9f74eff40a29ee36701a894c2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index a489de3bf858b6ea84d1470c17ab157f50adc01d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -46,20 +46,20 @@ browser.jar:
   skin/classic/browser/toolbarbutton-dropmarker.png
   skin/classic/browser/urlbar-history-dropmarker.png
   skin/classic/browser/urlbar-arrow.png
   skin/classic/browser/urlbar-popup-blocked.png
   skin/classic/browser/feeds/subscribe.css                  (feeds/subscribe.css)
   skin/classic/browser/feeds/subscribe-ui.css               (feeds/subscribe-ui.css)
   skin/classic/browser/feeds/feedIcon.png                   (feeds/feedIcon.png)
   skin/classic/browser/feeds/feedIcon16.png                 (feeds/feedIcon16.png)
-  skin/classic/browser/feeds/videoFeedIcon.png              (feeds/videoFeedIcon.png)
-  skin/classic/browser/feeds/videoFeedIcon16.png            (feeds/videoFeedIcon16.png)
-  skin/classic/browser/feeds/audioFeedIcon.png              (feeds/audioFeedIcon.png)
-  skin/classic/browser/feeds/audioFeedIcon16.png            (feeds/audioFeedIcon16.png)
+  skin/classic/browser/feeds/videoFeedIcon.png              (feeds/feedIcon.png)
+  skin/classic/browser/feeds/videoFeedIcon16.png            (feeds/feedIcon16.png)
+  skin/classic/browser/feeds/audioFeedIcon.png              (feeds/feedIcon.png)
+  skin/classic/browser/feeds/audioFeedIcon16.png            (feeds/feedIcon16.png)
   skin/classic/browser/setDesktopBackground.css
   skin/classic/browser/inspector.css
   skin/classic/browser/monitor.png
   skin/classic/browser/monitor_16-10.png
   skin/classic/browser/places/allBookmarks.png              (places/allBookmarks.png)
 * skin/classic/browser/places/places.css                    (places/places.css)
 * skin/classic/browser/places/organizer.css                 (places/organizer.css)
   skin/classic/browser/places/query.png                     (places/query.png)
--- a/browser/themes/pinstripe/places/places.css
+++ b/browser/themes/pinstripe/places/places.css
@@ -139,17 +139,17 @@ treechildren::-moz-tree-image(query) {
 }
 
 treechildren::-moz-tree-image(query, OrganizerQuery_Downloads) {
   list-style-image: url("chrome://browser/skin/places/downloads.png");
 }
 
 treechildren::-moz-tree-image(title, query, tagContainer),
 treechildren::-moz-tree-image(query, OrganizerQuery_Tags) {
-  list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
+  list-style-image: url("chrome://browser/skin/places/tag.png");
 }
 
 /* calendar icon for folders grouping items by date */
 treechildren::-moz-tree-image(title, query, dayContainer) {
   list-style-image: url("chrome://browser/skin/places/history.png");
 }
 
 treechildren::-moz-tree-image(title, query, hostContainer) {
deleted file mode 100644
index ff2ecc2f351ef37d250264aa2bb273de08518165..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -616,17 +616,17 @@ menuitem.bookmark-item {
 }
 
 .bookmark-item[container][query] {
   list-style-image: url("chrome://browser/skin/places/query.png");
   -moz-image-region: auto;
 }
 
 .bookmark-item[query][tagContainer] {
-  list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
+  list-style-image: url("chrome://browser/skin/places/tag.png");
   -moz-image-region: auto;
 }
 
 .bookmark-item[query][dayContainer] {
   list-style-image: url("chrome://browser/skin/places/calendar.png");
   -moz-image-region: auto;
 }
 
deleted file mode 100644
index b4d5994995f24adf40fe10f407c9644e802b140d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index e69bc4496139006ad20e34db308bfcc0cbc396c2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 7c3aceb66f351208cf25ff02abe617cbb5e56456..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index d778807532bc0a1d47ac82370255600d503d66eb..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index b4d5994995f24adf40fe10f407c9644e802b140d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index e69bc4496139006ad20e34db308bfcc0cbc396c2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 7c3aceb66f351208cf25ff02abe617cbb5e56456..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index d778807532bc0a1d47ac82370255600d503d66eb..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -1,17 +1,17 @@
 browser.jar:
 % skin browser classic/1.0 %skin/classic/browser/ os=WINNT osversion<6
 % skin browser classic/1.0 %skin/classic/browser/ os!=WINNT
 # NOTE: If you add a new file here, you'll need to add it to the aero
 # section at the bottom of this file
         skin/classic/browser/sanitizeDialog.css                      (sanitizeDialog.css)
 *       skin/classic/browser/aboutPrivateBrowsing.css                (aboutPrivateBrowsing.css)
 *       skin/classic/browser/aboutSessionRestore.css                 (aboutSessionRestore.css)
-        skin/classic/browser/aboutSessionRestore-window-icon.png     (aboutSessionRestore-window-icon.png)
+        skin/classic/browser/aboutSessionRestore-window-icon.png     (preferences/application.png)
         skin/classic/browser/aboutCertError.css                      (aboutCertError.css)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/aboutSyncTabs.css
 #endif
         skin/classic/browser/actionicon-tab.png
         skin/classic/browser/appmenu-icons.png
         skin/classic/browser/appmenu-dropmarker.png
 *       skin/classic/browser/browser.css                             (browser.css)
@@ -46,20 +46,20 @@ browser.jar:
         skin/classic/browser/menu-forward.png                        (menu-forward.png)
         skin/classic/browser/monitor.png
         skin/classic/browser/monitor_16-10.png
         skin/classic/browser/urlbar-arrow.png
         skin/classic/browser/urlbar-popup-blocked.png
         skin/classic/browser/urlbar-history-dropmarker.png
         skin/classic/browser/feeds/feedIcon.png                      (feeds/feedIcon.png)
         skin/classic/browser/feeds/feedIcon16.png                    (feeds/feedIcon16.png)
-        skin/classic/browser/feeds/audioFeedIcon.png                 (feeds/audioFeedIcon.png)
-        skin/classic/browser/feeds/audioFeedIcon16.png               (feeds/audioFeedIcon16.png)
-        skin/classic/browser/feeds/videoFeedIcon.png                 (feeds/videoFeedIcon.png)
-        skin/classic/browser/feeds/videoFeedIcon16.png               (feeds/videoFeedIcon16.png)
+        skin/classic/browser/feeds/audioFeedIcon.png                 (feeds/feedIcon.png)
+        skin/classic/browser/feeds/audioFeedIcon16.png               (feeds/feedIcon16.png)
+        skin/classic/browser/feeds/videoFeedIcon.png                 (feeds/feedIcon.png)
+        skin/classic/browser/feeds/videoFeedIcon16.png               (feeds/feedIcon16.png)
         skin/classic/browser/feeds/subscribe.css                     (feeds/subscribe.css)
         skin/classic/browser/feeds/subscribe-ui.css                  (feeds/subscribe-ui.css)
         skin/classic/browser/inspector.css
         skin/classic/browser/places/places.css                       (places/places.css)
 *       skin/classic/browser/places/organizer.css                    (places/organizer.css)
         skin/classic/browser/places/bookmark.png                     (places/bookmark.png)
         skin/classic/browser/places/editBookmark.png                 (places/editBookmark.png)
         skin/classic/browser/places/query.png                        (places/query.png)
@@ -199,20 +199,20 @@ browser.jar:
         skin/classic/aero/browser/menu-forward.png                   (menu-forward-aero.png)
         skin/classic/aero/browser/monitor.png
         skin/classic/aero/browser/monitor_16-10.png
         skin/classic/aero/browser/urlbar-arrow.png
         skin/classic/aero/browser/urlbar-popup-blocked.png
         skin/classic/aero/browser/urlbar-history-dropmarker.png
         skin/classic/aero/browser/feeds/feedIcon.png                 (feeds/feedIcon-aero.png)
         skin/classic/aero/browser/feeds/feedIcon16.png               (feeds/feedIcon16-aero.png)
-        skin/classic/aero/browser/feeds/audioFeedIcon.png            (feeds/audioFeedIcon-aero.png)
-        skin/classic/aero/browser/feeds/audioFeedIcon16.png          (feeds/audioFeedIcon16-aero.png)
-        skin/classic/aero/browser/feeds/videoFeedIcon.png            (feeds/videoFeedIcon-aero.png)
-        skin/classic/aero/browser/feeds/videoFeedIcon16.png          (feeds/videoFeedIcon16-aero.png)
+        skin/classic/aero/browser/feeds/audioFeedIcon.png            (feeds/feedIcon-aero.png)
+        skin/classic/aero/browser/feeds/audioFeedIcon16.png          (feeds/feedIcon16-aero.png)
+        skin/classic/aero/browser/feeds/videoFeedIcon.png            (feeds/feedIcon-aero.png)
+        skin/classic/aero/browser/feeds/videoFeedIcon16.png          (feeds/feedIcon16-aero.png)
         skin/classic/aero/browser/feeds/subscribe.css                (feeds/subscribe.css)
         skin/classic/aero/browser/feeds/subscribe-ui.css             (feeds/subscribe-ui.css)
         skin/classic/aero/browser/inspector.css
 *       skin/classic/aero/browser/places/places.css                  (places/places-aero.css)
 *       skin/classic/aero/browser/places/organizer.css               (places/organizer-aero.css)
         skin/classic/aero/browser/places/bookmark.png                (places/bookmark.png)
         skin/classic/aero/browser/places/editBookmark.png            (places/editBookmark.png)
         skin/classic/aero/browser/places/query.png                   (places/query-aero.png)
@@ -223,26 +223,25 @@ browser.jar:
         skin/classic/aero/browser/places/editBookmarkOverlay.css     (places/editBookmarkOverlay.css)
         skin/classic/aero/browser/places/libraryToolbar.png          (places/libraryToolbar-aero.png)
         skin/classic/aero/browser/places/starred48.png               (places/starred48-aero.png)
         skin/classic/aero/browser/places/unstarred48.png             (places/unstarred48.png)
         skin/classic/aero/browser/places/tag.png                     (places/tag-aero.png)
         skin/classic/aero/browser/places/history.png                 (places/history-aero.png)
         skin/classic/aero/browser/places/allBookmarks.png            (places/allBookmarks-aero.png)
         skin/classic/aero/browser/places/unsortedBookmarks.png       (places/unsortedBookmarks-aero.png)
-        skin/classic/aero/browser/places/searching_16.png            (places/searching_16-aero.png)
+        skin/classic/aero/browser/places/searching_16.png            (places/searching_16.png)
         skin/classic/aero/browser/places/downloads.png               (places/downloads.png)
         skin/classic/aero/browser/preferences/alwaysAsk.png          (preferences/alwaysAsk-aero.png)
         skin/classic/aero/browser/preferences/application.png        (preferences/application-aero.png)
         skin/classic/aero/browser/preferences/mail.png               (preferences/mail-aero.png)
         skin/classic/aero/browser/preferences/Options.png            (preferences/Options-aero.png)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/preferences/Options-sync.png       (preferences/Options-sync.png)
 #endif
-        skin/classic/aero/browser/preferences/plugin.png             (preferences/plugin-aero.png)
         skin/classic/aero/browser/preferences/saveFile.png           (preferences/saveFile-aero.png)
 *       skin/classic/aero/browser/preferences/preferences.css        (preferences/preferences.css)
         skin/classic/aero/browser/preferences/applications.css       (preferences/applications.css)
         skin/classic/aero/browser/preferences/aboutPermissions.css   (preferences/aboutPermissions.css)
         skin/classic/aero/browser/tabbrowser/alltabs.png             (tabbrowser/alltabs.png)
         skin/classic/aero/browser/tabbrowser/newtab.png              (tabbrowser/newtab.png)
         skin/classic/aero/browser/tabbrowser/newtab-inverted.png     (tabbrowser/newtab-inverted.png)
         skin/classic/aero/browser/tabbrowser/connecting.png          (tabbrowser/connecting.png)
--- a/browser/themes/winstripe/places/places.css
+++ b/browser/themes/winstripe/places/places.css
@@ -76,17 +76,17 @@ treechildren::-moz-tree-image(container,
 /* query-nodes should be styled even if they're not expandable */
 treechildren::-moz-tree-image(title, query) {
   list-style-image: url("chrome://browser/skin/places/query.png");
   -moz-image-region: auto;
 }
 
 treechildren::-moz-tree-image(title, query, tagContainer),
 treechildren::-moz-tree-image(query, OrganizerQuery_Tags) {
-  list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
+  list-style-image: url("chrome://browser/skin/places/tag.png");
   -moz-image-region: auto;
 }
 
 treechildren::-moz-tree-image(query, OrganizerQuery_Downloads) {
   list-style-image: url("chrome://browser/skin/places/downloads.png");
   -moz-image-region: auto;
 }
 
deleted file mode 100644
index 2f97e742a3f0855c97a356c9f699b3bda3ac7c7b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 5d796cc4c57dd3da1669fd4e51ba8d954ed4c866..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/build/autoconf/mozcommonheader.m4
@@ -0,0 +1,41 @@
+dnl ***** BEGIN LICENSE BLOCK *****
+dnl Version: MPL 1.1/GPL 2.0/LGPL 2.1
+dnl
+dnl The contents of this file are subject to the Mozilla Public License Version
+dnl 1.1 (the "License"); you may not use this file except in compliance with
+dnl the License. You may obtain a copy of the License at
+dnl http://www.mozilla.org/MPL/
+dnl
+dnl Software distributed under the License is distributed on an "AS IS" basis,
+dnl WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+dnl for the specific language governing rights and limitations under the
+dnl License.
+dnl
+dnl The Original Code is mozilla.org code.
+dnl
+dnl The Initial Developer of the Original Code is the
+dnl Mozilla Foundation <http://www.mozilla.org>
+dnl
+dnl Portions created by the Initial Developer are Copyright (C) 2009
+dnl the Initial Developer. All Rights Reserved.
+dnl
+dnl
+dnl Alternatively, the contents of this file may be used under the terms of
+dnl either of the GNU General Public License Version 2 or later (the "GPL"),
+dnl or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+dnl in which case the provisions of the GPL or the LGPL are applicable instead
+dnl of those above. If you wish to allow use of your version of this file only
+dnl under the terms of either the GPL or the LGPL, and not to allow others to
+dnl use your version of this file under the terms of the MPL, indicate your
+dnl decision by deleting the provisions above and replace them with the notice
+dnl and other provisions required by the GPL or the LGPL. If you do not delete
+dnl the provisions above, a recipient may use your version of this file under
+dnl the terms of any one of the MPL, the GPL or the LGPL.
+dnl
+dnl ***** END LICENSE BLOCK *****
+
+AC_DEFUN(MOZ_CHECK_COMMON_HEADERS,
+	MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h sys/bitypes.h \
+        memory.h unistd.h gnu/libc-version.h nl_types.h malloc.h \
+        X11/XKBlib.h io.h cpuid.h)
+)
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -114,17 +114,16 @@ MOZ_MEMORY      = @MOZ_MEMORY@
 MOZ_PROFILING   = @MOZ_PROFILING@
 MOZ_ENABLE_PROFILER_SPS = @MOZ_ENABLE_PROFILER_SPS@
 MOZ_JPROF       = @MOZ_JPROF@
 MOZ_SHARK       = @MOZ_SHARK@
 MOZ_CALLGRIND   = @MOZ_CALLGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
 MOZ_ETW         = @MOZ_ETW@
 MOZ_TRACE_JSCALLS = @MOZ_TRACE_JSCALLS@
-MOZ_TRACEVIS    = @MOZ_TRACEVIS@
 DEHYDRA_PATH    = @DEHYDRA_PATH@
 
 NS_TRACE_MALLOC = @NS_TRACE_MALLOC@
 USE_ELF_DYNSTR_GC = @USE_ELF_DYNSTR_GC@
 USE_ELF_HACK = @USE_ELF_HACK@
 STDCXX_COMPAT = @STDCXX_COMPAT@
 MOZ_LIBSTDCXX_TARGET_VERSION=@MOZ_LIBSTDCXX_TARGET_VERSION@
 MOZ_LIBSTDCXX_HOST_VERSION=@MOZ_LIBSTDCXX_HOST_VERSION@
--- a/configure.in
+++ b/configure.in
@@ -3404,22 +3404,17 @@ dnl Checks for header files.
 dnl ========================================================
 AC_HEADER_DIRENT
 case "$target_os" in
 freebsd*|openbsd*)
 # for stuff like -lXshm
     CPPFLAGS="${CPPFLAGS} ${X_CFLAGS}"
     ;;
 esac
-MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h)
-MOZ_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h)
-MOZ_CHECK_HEADERS(gnu/libc-version.h nl_types.h)
-MOZ_CHECK_HEADERS(malloc.h)
-MOZ_CHECK_HEADERS(X11/XKBlib.h)
-MOZ_CHECK_HEADERS(io.h)
+MOZ_CHECK_COMMON_HEADERS
 
 dnl These are all the places some variant of statfs can be hiding.
 MOZ_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h)
 
 dnl Quota support
 MOZ_CHECK_HEADERS(sys/quota.h sys/sysmacros.h)
 MOZ_CHECK_HEADERS(linux/quota.h)
 
@@ -7321,27 +7316,16 @@ MOZ_ARG_ENABLE_BOOL(trace-jscalls,
 [  --enable-trace-jscalls  Enable JS call enter/exit callback (default=no)],
     MOZ_TRACE_JSCALLS=1,
     MOZ_TRACE_JSCALLS= )
 if test -n "$MOZ_TRACE_JSCALLS"; then
     AC_DEFINE(MOZ_TRACE_JSCALLS)
 fi
 
 dnl ========================================================
-dnl = Use TraceVis
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(tracevis,
-[  --enable-tracevis       Enable TraceVis tracing tool (default=no)],
-    MOZ_TRACEVIS=1,
-    MOZ_TRACEVIS= )
-if test -n "$MOZ_TRACEVIS"; then
-    AC_DEFINE(MOZ_TRACEVIS)
-fi
-
-dnl ========================================================
 dnl = Use incremental GC
 dnl ========================================================
 JSGC_INCREMENTAL=1
 MOZ_ARG_DISABLE_BOOL(gcincremental,
 [  --disable-gcincremental Disable incremental GC],
     JSGC_INCREMENTAL= )
 if test -n "$JSGC_INCREMENTAL"; then
     AC_DEFINE(JSGC_INCREMENTAL)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -59,17 +59,17 @@
 #include "nsIVariant.h"
 #include "nsIObserver.h"
 #include "nsGkAtoms.h"
 #include "nsAutoPtr.h"
 #include "nsPIDOMWindow.h"
 #include "nsSMILAnimationController.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDocumentEncoder.h"
-#include "nsIAnimationFrameListener.h"
+#include "nsIFrameRequestCallback.h"
 #include "nsEventStates.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsIBFCacheEntry.h"
 #include "nsDOMMemoryReporter.h"
 
 class nsIContent;
 class nsPresContext;
 class nsIPresShell;
@@ -1513,28 +1513,24 @@ public:
    * Lookup an image element using its associated ID, which is usually provided
    * by |-moz-element()|. Similar to GetElementById, with the difference that
    * elements set using mozSetImageElement have higher priority.
    * @param aId the ID associated the element we want to lookup
    * @return the element associated with |aId|
    */
   virtual Element* LookupImageElement(const nsAString& aElementId) = 0;
 
-  void ScheduleBeforePaintEvent(nsIAnimationFrameListener* aListener);
-  void BeforePaintEventFiring()
-  {
-    mHavePendingPaint = false;
-  }
+  void ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback);
 
-  typedef nsTArray< nsCOMPtr<nsIAnimationFrameListener> > AnimationListenerList;
+  typedef nsTArray< nsCOMPtr<nsIFrameRequestCallback> > FrameRequestCallbackList;
   /**
-   * Put this documents animation frame listeners into the provided
+   * Put this document's frame request callbacks into the provided
    * list, and forget about them.
    */
-  void TakeAnimationFrameListeners(AnimationListenerList& aListeners);
+  void TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks);
 
   // This returns true when the document tree is being teared down.
   bool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; }
 
   /*
    * Image Tracking
    *
    * Style and content images register their imgIRequests with their document
@@ -1741,19 +1737,16 @@ protected:
   bool mCreatingStaticClone;
 
   // True iff the document is being unlinked or deleted.
   bool mInUnlinkOrDeletion;
 
   // True if document has ever had script handling object.
   bool mHasHadScriptHandlingObject;
 
-  // True if we're waiting for a before-paint event.
-  bool mHavePendingPaint;
-
   // True if we're an SVG document being used as an image.
   bool mIsBeingUsedAsImage;
 
   // True is this document is synthetic : stand alone image, video, audio
   // file, etc.
   bool mIsSyntheticDocument;
 
   // True if this document has links whose state needs updating
@@ -1807,17 +1800,17 @@ protected:
   PRUint32 mExternalScriptsBeingEvaluated;
 
   // Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
   // updated on every set of mSecriptGlobalObject.
   nsPIDOMWindow *mWindow;
 
   nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
 
-  AnimationListenerList mAnimationFrameListeners;
+  FrameRequestCallbackList mFrameRequestCallbacks;
 
   // This object allows us to evict ourself from the back/forward cache.  The
   // pointer is non-null iff we're currently in the bfcache.
   nsIBFCacheEntry *mBFCacheEntry;
 
   // Our base target.
   nsString mBaseTarget;
 
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -46,16 +46,19 @@
 #include "nsIWindowMediator.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsISHistory.h"
 #include "nsISHEntry.h"
 #include "nsISHContainer.h"
 #include "nsIWindowWatcher.h"
 #include "mozilla/Services.h"
+#include "nsIXULWindow.h"
+#include "nsIAppShellService.h"
+#include "nsAppShellCID.h"
 
 static bool sInited = 0;
 PRUint32 nsCCUncollectableMarker::sGeneration = 0;
 
 NS_IMPL_ISUPPORTS1(nsCCUncollectableMarker, nsIObserver)
 
 /* static */
 nsresult
@@ -226,11 +229,24 @@ nsCCUncollectableMarker::Observe(nsISupp
     do_GetService(NS_WINDOWWATCHER_CONTRACTID);
   if (ww) {
     rv = ww->GetWindowEnumerator(getter_AddRefs(windowList));
     NS_ENSURE_SUCCESS(rv, rv);
 
     MarkWindowList(windowList);
   }
 
+  nsCOMPtr<nsIAppShellService> appShell = 
+    do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
+  if (appShell) {
+    nsCOMPtr<nsIXULWindow> hw;
+    appShell->GetHiddenWindow(getter_AddRefs(hw));
+    if (hw) {
+      nsCOMPtr<nsIDocShell> shell;
+      hw->GetDocShell(getter_AddRefs(shell));
+      nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
+      MarkDocShell(shellTreeNode);
+    }
+  }
+
   return NS_OK;
 }
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1876,19 +1876,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFullScreenElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStateObjectCached)
 
   // Traverse all our nsCOMArrays.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPreloadingImages)
 
-  for (PRUint32 i = 0; i < tmp->mAnimationFrameListeners.Length(); ++i) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAnimationFrameListeners[i]");
-    cb.NoteXPCOMChild(tmp->mAnimationFrameListeners[i]);
+  for (PRUint32 i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameRequestCallbacks[i]");
+    cb.NoteXPCOMChild(tmp->mFrameRequestCallbacks[i]);
   }
 
   // Traverse animation components
   if (tmp->mAnimationController) {
     tmp->mAnimationController->Traverse(&cb);
   }
 
   if (tmp->mSubDocuments && tmp->mSubDocuments->ops) {
@@ -1946,17 +1946,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     tmp->mListenerManager = nsnull;
   }
 
   if (tmp->mSubDocuments) {
     PL_DHashTableDestroy(tmp->mSubDocuments);
     tmp->mSubDocuments = nsnull;
   }
 
-  tmp->mAnimationFrameListeners.Clear();
+  tmp->mFrameRequestCallbacks.Clear();
 
   tmp->mRadioGroups.Clear();
   
   // nsDocument has a pretty complex destructor, so we're going to
   // assume that *most* cycles you actually want to break somewhere
   // else, and not unlink an awful lot here.
 
   tmp->mIdentifierMap.Clear();
@@ -3209,51 +3209,45 @@ void
 nsDocument::MaybeRescheduleAnimationFrameNotifications()
 {
   if (!mPresShell || !IsEventHandlingEnabled()) {
     // bail out for now, until one of those conditions changes
     return;
   }
 
   nsRefreshDriver* rd = mPresShell->GetPresContext()->RefreshDriver();
-  if (mHavePendingPaint) {
-    rd->ScheduleBeforePaintEvent(this);
-  }
-  if (!mAnimationFrameListeners.IsEmpty()) {
-    rd->ScheduleAnimationFrameListeners(this);
-  }
-}
-
-void
-nsIDocument::TakeAnimationFrameListeners(AnimationListenerList& aListeners)
-{
-  aListeners.AppendElements(mAnimationFrameListeners);
-  mAnimationFrameListeners.Clear();
+  if (!mFrameRequestCallbacks.IsEmpty()) {
+    rd->ScheduleFrameRequestCallbacks(this);
+  }
+}
+
+void
+nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks)
+{
+  aCallbacks.AppendElements(mFrameRequestCallbacks);
+  mFrameRequestCallbacks.Clear();
 }
 
 void
 nsDocument::DeleteShell()
 {
   mExternalResourceMap.HideViewers();
   if (IsEventHandlingEnabled()) {
     RevokeAnimationFrameNotifications();
   }
 
   mPresShell = nsnull;
 }
 
 void
 nsDocument::RevokeAnimationFrameNotifications()
 {
-  if (mHavePendingPaint) {
-    mPresShell->GetPresContext()->RefreshDriver()->RevokeBeforePaintEvent(this);
-  }
-  if (!mAnimationFrameListeners.IsEmpty()) {
+  if (!mFrameRequestCallbacks.IsEmpty()) {
     mPresShell->GetPresContext()->RefreshDriver()->
-      RevokeAnimationFrameListeners(this);
+      RevokeFrameRequestCallbacks(this);
   }
 }
 
 static void
 SubDocClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
 {
   SubDocMapEntry *e = static_cast<SubDocMapEntry *>(entry);
 
@@ -8069,40 +8063,24 @@ nsIDocument::CreateStaticClone(nsISuppor
       }
     }
   }
   mCreatingStaticClone = false;
   return clonedDoc.forget();
 }
 
 void
-nsIDocument::ScheduleBeforePaintEvent(nsIAnimationFrameListener* aListener)
-{
-  if (aListener) {
-    bool alreadyRegistered = !mAnimationFrameListeners.IsEmpty();
-    if (mAnimationFrameListeners.AppendElement(aListener) &&
-        !alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
-      mPresShell->GetPresContext()->RefreshDriver()->
-        ScheduleAnimationFrameListeners(this);
-    }
-
-    return;
-  }
-
-  if (!mHavePendingPaint) {
-    // We don't want to use GetShell() here, because we want to schedule the
-    // paint even if we're frozen.  Either we'll get unfrozen and then the
-    // event will fire, or we'll quietly go away at some point.
-    mHavePendingPaint =
-      !mPresShell ||
-      !IsEventHandlingEnabled() ||
-      mPresShell->GetPresContext()->RefreshDriver()->
-        ScheduleBeforePaintEvent(this);
-  }
-
+nsIDocument::ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback)
+{
+  bool alreadyRegistered = !mFrameRequestCallbacks.IsEmpty();
+  if (mFrameRequestCallbacks.AppendElement(aCallback) &&
+      !alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
+    mPresShell->GetPresContext()->RefreshDriver()->
+      ScheduleFrameRequestCallbacks(this);
+  }
 }
 
 nsresult
 nsDocument::GetStateObject(nsIVariant** aState)
 {
   // Get the document's current state object. This is the object backing both
   // history.state and popStateEvent.state.
   //
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -306,17 +306,17 @@ nsInProcessTabChildGlobal::InitTabChildG
 
   mCx = cx;
 
   nsContentUtils::XPConnect()->SetSecurityManagerForJSContext(cx, nsContentUtils::GetSecurityManager(), 0);
   nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
 
   JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
 
-  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_PRIVATE_IS_NSISUPPORTS);
+  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
   JS_SetVersion(cx, JSVERSION_LATEST);
   JS_SetErrorReporter(cx, ContentScriptErrorReporter);
 
   xpc_LocalizeContext(cx);
 
   JSAutoRequest ar(cx);
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -400,17 +400,17 @@ nsEventListenerManager::SetJSEventListen
 {
   nsresult rv = NS_OK;
   PRUint32 eventType = nsContentUtils::GetEventId(aName);
   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
 
   if (!ls) {
     // If we didn't find a script listener or no listeners existed
     // create and add a new one.
-    nsCOMPtr<nsIDOMEventListener> scriptListener;
+    nsCOMPtr<nsIJSEventListener> scriptListener;
     rv = NS_NewJSEventListener(aContext, aScopeObject, mTarget, aName,
                                aHandler, getter_AddRefs(scriptListener));
     if (NS_SUCCEEDED(rv)) {
       AddEventListener(scriptListener, eventType, aName,
                        NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT);
 
       ls = FindJSEventListener(eventType, aName);
     }
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -58,28 +58,36 @@ class nsIWidget;
 struct nsPoint;
 struct EventTypeData;
 class nsEventTargetChainItem;
 class nsPIDOMWindow;
 class nsCxPusher;
 class nsIEventListenerInfo;
 class nsIDocument;
 
-typedef struct {
+struct nsListenerStruct
+{
   nsRefPtr<nsIDOMEventListener> mListener;
   PRUint32                      mEventType;
   nsCOMPtr<nsIAtom>             mTypeAtom;
   PRUint16                      mFlags;
   bool                          mHandlerIsString;
 
   nsIJSEventListener* GetJSListener() const {
     return (mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) ?
       static_cast<nsIJSEventListener *>(mListener.get()) : nsnull;
   }
-} nsListenerStruct;
+
+  ~nsListenerStruct()
+  {
+    if ((mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) && mListener) {
+      static_cast<nsIJSEventListener*>(mListener.get())->Disconnect();
+    }
+  }
+};
 
 /*
  * Event listener manager
  */
 
 class nsEventListenerManager
 {
 
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -336,42 +336,47 @@ function MediaTestManager() {
   this.runTests = function(tests, startTest) {
     this.startTime = new Date();
     SimpleTest.info("Started " + this.startTime + " (" + this.startTime.getTime()/1000 + "s)");
     this.testNum = 0;
     this.tests = tests;
     this.startTest = startTest;
     this.tokens = [];
     this.isShutdown = false;
+    this.numTestsRunning = 0;
     // Always wait for explicit finish.
     SimpleTest.waitForExplicitFinish();
     this.nextTest();
   }
   
   // Registers that the test corresponding to 'token' has been started.
   // Don't call more than once per token.
   this.started = function(token) {
     this.tokens.push(token);
+    this.numTestsRunning++;
+    is(this.numTestsRunning, this.tokens.length, "[started] Length of array should match number of running tests");
   }
   
   // Registers that the test corresponding to 'token' has finished. Call when
   // you've finished your test. If all tests are complete this will finish the
   // run, otherwise it may start up the next run. It's ok to call multiple times
   // per token.
   this.finished = function(token) {
     var i = this.tokens.indexOf(token);
     if (i != -1) {
       // Remove the element from the list of running tests.
       this.tokens.splice(i, 1);
     }
+    this.numTestsRunning--;
+    is(this.numTestsRunning, this.tokens.length, "[finished] Length of array should match number of running tests");
     if (this.tokens.length < PARALLEL_TESTS) {
       this.nextTest();
     }
   }
-  
+
   // Starts the next batch of tests, or finishes if they're all done.
   // Don't call this directly, call finished(token) when you're done.
   this.nextTest = function() {
     // Force a GC after every completed testcase. This ensures that any decoders
     // with live threads waiting for the GC are killed promptly, to free up the
     // thread stacks' address space.
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     Components.utils.forceGC();
--- a/content/media/test/test_playback.html
+++ b/content/media/test/test_playback.html
@@ -30,32 +30,32 @@ function startTest(test, token) {
     if (test.duration) {
       ok(Math.abs(v.currentTime - test.duration) < 0.1,
          test.name + " current time at end: " + v.currentTime + " should be: " + test.duration);
     }
     is(test.name, v.name, "Name should match test.name #2");
     is(v.readyState, v.HAVE_CURRENT_DATA, test.name + " checking readyState");
     ok(v.readyState != v.NETWORK_LOADED, test.name + " shouldn't report NETWORK_LOADED");
     ok(v.ended, test.name + " checking playback has ended");
-    if (v.ended && v.seenSuspend) {
-      if (v.parentNode)
-        v.parentNode.removeChild(v);
+    if (v.ended && v.seenSuspend && !v.finished) {
+      v.finished = true;
+      v.parentNode.removeChild(v);
       manager.finished(v.token);
     }
   }}(test, v);
   var checkSuspended = function(test, v) { return function() {
     is(test.name, v.name, "Name should match test.name #3");
     if (v.seenSuspend)
       return;
 
     v.seenSuspend = true;
     ok(true, test.name + " got suspend");
-    if (v.ended && v.seenSuspend) {
-      if (v.parentNode)
-        v.parentNode.removeChild(v);
+    if (v.ended && !v.finished) {
+      v.finished = true;
+      v.parentNode.removeChild(v);
       manager.finished(v.token);
     }
   }}(test, v);
   v.prevTime = 0;
   var timeUpdate = function(test, v) { return function() {
     is(test.name, v.name, "Name should match test.name #4");
     checkMetadata(test.name, v, test);
     ok(v.prevTime <= v.currentTime,
--- a/content/media/test/test_timeupdate_small_files.html
+++ b/content/media/test/test_timeupdate_small_files.html
@@ -41,29 +41,39 @@ function ended(e) {
       v.removeEventListener("ended", ended, false);
       v.removeEventListener("timeupdate", timeupdate, false);
       v.parentNode.removeChild(v);
       manager.finished(v.token);
     },
     500);
 }
 
+var eventsToLog = ["play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
+  "loadeddata", "playing", "progress", "timeupdate", "ended", "suspend", "error", "stalled", "emptied", "abort",
+  "waiting", "pause"];
+function logEvent(event) {
+  ok(true, event.target.currentSrc + " got " + event.type);
+}
+
 function startTest(test, token) {
   var type = /^video/.test(test.type) ? "video" : "audio";
   var v = document.createElement(type);
   v.token = token;
   manager.started(token);
   v.src = test.name;
   v._name = test.name;
   v._timeupdateCount = 0;
   v._finished = false;
   v.gotEnded = false;
   v.autoplay = true;
   v.addEventListener("ended", ended, false);
   v.addEventListener("timeupdate", timeupdate, false);
+  for (var i = 0; i < eventsToLog.length; ++i) {
+    v.addEventListener(eventsToLog[i], logEvent, false);
+  }
   document.body.appendChild(v);
 }
 
 manager.runTests(gSmallTests, startTest);
 
 </script>
 </pre>
 </body>
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -322,25 +322,26 @@ nsXBLPrototypeHandler::ExecuteHandler(ns
   // Bind it to the bound element
   JSObject* scope = boundGlobal->GetGlobalJSObject();
   nsScriptObjectHolder boundHandler(boundContext);
   rv = boundContext->BindCompiledEventHandler(scriptTarget, scope,
                                               handler.getObject(), boundHandler);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Execute it.
-  nsCOMPtr<nsIDOMEventListener> eventListener;
+  nsCOMPtr<nsIJSEventListener> eventListener;
   rv = NS_NewJSEventListener(boundContext, scope,
                              scriptTarget, onEventAtom,
                              boundHandler.getObject(),
                              getter_AddRefs(eventListener));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Handle the event.
   eventListener->HandleEvent(aEvent);
+  eventListener->Disconnect();
   return NS_OK;
 }
 
 nsresult
 nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
                                           nsIScriptContext *aBoundContext,
                                           nsIAtom *aName,
                                           nsScriptObjectHolder &aHandler)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3952,26 +3952,26 @@ nsGlobalWindow::GetMozPaintCount(PRUint6
   if (!presShell)
     return NS_OK;
 
   *aResult = presShell->GetPaintCount();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::MozRequestAnimationFrame(nsIAnimationFrameListener* aListener)
-{
-  FORWARD_TO_INNER(MozRequestAnimationFrame, (aListener),
+nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback)
+{
+  FORWARD_TO_INNER(MozRequestAnimationFrame, (aCallback),
                    NS_ERROR_NOT_INITIALIZED);
 
   if (!mDoc) {
     return NS_OK;
   }
 
-  mDoc->ScheduleBeforePaintEvent(aListener);
+  mDoc->ScheduleFrameRequestCallback(aCallback);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetMozAnimationStartTime(PRInt64 *aTime)
 {
   FORWARD_TO_INNER(GetMozAnimationStartTime, (aTime), NS_ERROR_NOT_INITIALIZED);
 
--- a/dom/base/nsIJSEventListener.h
+++ b/dom/base/nsIJSEventListener.h
@@ -41,45 +41,54 @@
 #include "nsIScriptContext.h"
 #include "jsapi.h"
 #include "nsIDOMEventListener.h"
 
 class nsIScriptObjectOwner;
 class nsIAtom;
 
 #define NS_IJSEVENTLISTENER_IID \
-{ 0xafc5d047, 0xdb6b, 0x4076, \
-  { 0xb3, 0xfa, 0x57, 0x96, 0x1e, 0x21, 0x48, 0x42 } }
+{ 0x92f9212b, 0xa6aa, 0x4867, \
+  { 0x93, 0x8a, 0x56, 0xbe, 0x17, 0x67, 0x4f, 0xd4 } }
 
 // Implemented by script event listeners. Used to retrieve the
 // script object corresponding to the event target and the handler itself.
 // (Note this interface is now used to store script objects for all
 // script languages, so is no longer JS specific)
+//
+// Note, mTarget is a raw pointer and the owner of the nsIJSEventListener object
+// is expected to call Disconnect()!
 class nsIJSEventListener : public nsIDOMEventListener
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSEVENTLISTENER_IID)
 
   nsIJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
                      nsISupports *aTarget, JSObject *aHandler)
-    : mContext(aContext), mScopeObject(aScopeObject),
-      mTarget(do_QueryInterface(aTarget)), mHandler(aHandler)
+    : mContext(aContext), mScopeObject(aScopeObject), mHandler(aHandler)
   {
+    nsCOMPtr<nsISupports> base = do_QueryInterface(aTarget);
+    mTarget = base.get();
   }
 
   nsIScriptContext *GetEventContext() const
   {
     return mContext;
   }
 
   nsISupports *GetEventTarget() const
   {
     return mTarget;
   }
 
+  void Disconnect()
+  {
+    mTarget = nsnull;
+  }
+
   JSObject* GetEventScope() const
   {
     return mScopeObject;
   }
 
   JSObject *GetHandler() const
   {
     return mHandler;
@@ -89,24 +98,25 @@ public:
   // there is already a handler!  The handler must already be bound to
   // the right target.
   virtual void SetHandler(JSObject *aHandler) = 0;
 
   virtual PRInt64 SizeOf() const = 0;
 protected:
   virtual ~nsIJSEventListener()
   {
+    NS_ASSERTION(!mTarget, "Should have called Disconnect()!");
   }
   nsCOMPtr<nsIScriptContext> mContext;
   JSObject* mScopeObject;
-  nsCOMPtr<nsISupports> mTarget;
+  nsISupports* mTarget;
   JSObject *mHandler;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
 
 /* factory function.  aHandler must already be bound to aTarget */
 nsresult NS_NewJSEventListener(nsIScriptContext *aContext,
                                JSObject* aScopeObject, nsISupports* aTarget,
                                nsIAtom* aType, JSObject* aHandler,
-                               nsIDOMEventListener **aReturn);
+                               nsIJSEventListener **aReturn);
 
 #endif // nsIJSEventListener_h__
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -189,17 +189,17 @@ public:
 
 NS_IMPL_ISUPPORTS1(nsMemoryPressureObserver, nsIObserver)
 
 NS_IMETHODIMP
 nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
                                   const PRUnichar* aData)
 {
   if (sGCOnMemoryPressure) {
-    nsJSContext::GarbageCollectNow();
+    nsJSContext::GarbageCollectNow(true);
     nsJSContext::CycleCollectNow();
   }
   return NS_OK;
 }
 
 class nsRootedJSValueArray {
 public:
   explicit nsRootedJSValueArray(JSContext *cx) : avr(cx, vals.Length(), vals.Elements()) {}
@@ -924,18 +924,16 @@ static const char js_werror_option_str[]
 static const char js_relimit_option_str[]= JS_OPTIONS_DOT_STR "relimit";
 #ifdef JS_GC_ZEAL
 static const char js_zeal_option_str[]        = JS_OPTIONS_DOT_STR "gczeal";
 static const char js_zeal_frequency_str[]     = JS_OPTIONS_DOT_STR "gczeal.frequency";
 static const char js_zeal_compartment_str[]   = JS_OPTIONS_DOT_STR "gczeal.compartment_gc";
 #endif
 static const char js_methodjit_content_str[]  = JS_OPTIONS_DOT_STR "methodjit.content";
 static const char js_methodjit_chrome_str[]   = JS_OPTIONS_DOT_STR "methodjit.chrome";
-static const char js_profiling_content_str[]  = JS_OPTIONS_DOT_STR "jitprofiling.content";
-static const char js_profiling_chrome_str[]   = JS_OPTIONS_DOT_STR "jitprofiling.chrome";
 static const char js_methodjit_always_str[]   = JS_OPTIONS_DOT_STR "methodjit_always";
 static const char js_typeinfer_str[]          = JS_OPTIONS_DOT_STR "typeinference";
 static const char js_pccounts_content_str[]   = JS_OPTIONS_DOT_STR "pccounts.content";
 static const char js_pccounts_chrome_str[]    = JS_OPTIONS_DOT_STR "pccounts.chrome";
 static const char js_jit_hardening_str[]      = JS_OPTIONS_DOT_STR "jit_hardening";
 static const char js_memlog_option_str[] = JS_OPTIONS_DOT_STR "mem.log";
 
 int
@@ -956,49 +954,40 @@ nsJSContext::JSOptionChangedCallback(con
   nsIScriptGlobalObject *global = context->GetGlobalObject();
   // XXX should we check for sysprin instead of a chrome window, to make
   // XXX components be covered by the chrome pref instead of the content one?
   nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(global));
 
   bool useMethodJIT = Preferences::GetBool(chromeWindow ?
                                                js_methodjit_chrome_str :
                                                js_methodjit_content_str);
-  bool useProfiling = Preferences::GetBool(chromeWindow ?
-                                               js_profiling_chrome_str :
-                                               js_profiling_content_str);
   bool usePCCounts = Preferences::GetBool(chromeWindow ?
                                             js_pccounts_chrome_str :
                                             js_pccounts_content_str);
   bool useMethodJITAlways = Preferences::GetBool(js_methodjit_always_str);
   bool useTypeInference = !chromeWindow && Preferences::GetBool(js_typeinfer_str);
   bool useHardening = Preferences::GetBool(js_jit_hardening_str);
   nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
   if (xr) {
     bool safeMode = false;
     xr->GetInSafeMode(&safeMode);
     if (safeMode) {
       useMethodJIT = false;
-      useProfiling = false;
       usePCCounts = false;
       useTypeInference = false;
       useMethodJITAlways = true;
       useHardening = false;
     }
   }    
 
   if (useMethodJIT)
     newDefaultJSOptions |= JSOPTION_METHODJIT;
   else
     newDefaultJSOptions &= ~JSOPTION_METHODJIT;
 
-  if (useProfiling)
-    newDefaultJSOptions |= JSOPTION_PROFILING;
-  else
-    newDefaultJSOptions &= ~JSOPTION_PROFILING;
-
   if (usePCCounts)
     newDefaultJSOptions |= JSOPTION_PCCOUNT;
   else
     newDefaultJSOptions &= ~JSOPTION_PCCOUNT;
 
   if (useMethodJITAlways)
     newDefaultJSOptions |= JSOPTION_METHODJIT_ALWAYS;
   else
@@ -2945,24 +2934,16 @@ static JSFunctionSpec JProfFunctions[] =
     {"JProfStopProfiling",         JProfStopProfilingJS,       0, 0},
     {"JProfClearCircular",         JProfClearCircularJS,       0, 0},
     {"JProfSaveCircular",          JProfSaveCircularJS,        0, 0},
     {nsnull,                       nsnull,                     0, 0}
 };
 
 #endif /* defined(MOZ_JPROF) */
 
-#ifdef MOZ_TRACEVIS
-static JSFunctionSpec EthogramFunctions[] = {
-    {"initEthogram",               js_InitEthogram,            0, 0},
-    {"shutdownEthogram",           js_ShutdownEthogram,        0, 0},
-    {nsnull,                       nsnull,                     0, 0}
-};
-#endif
-
 nsresult
 nsJSContext::InitClasses(JSObject* aGlobalObj)
 {
   nsresult rv = InitializeExternalClasses();
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSAutoRequest ar(mContext);
 
@@ -2976,21 +2957,16 @@ nsJSContext::InitClasses(JSObject* aGlob
   ::JS_DefineFunctions(mContext, aGlobalObj, TraceMallocFunctions);
 #endif
 
 #ifdef MOZ_JPROF
   // Attempt to initialize JProf functions
   ::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
 #endif
 
-#ifdef MOZ_TRACEVIS
-  // Attempt to initialize Ethogram functions
-  ::JS_DefineFunctions(mContext, aGlobalObj, EthogramFunctions);
-#endif
-
   JSOptionChangedCallback(js_options_dot_str, this);
 
   return rv;
 }
 
 void
 nsJSContext::ClearScope(void *aGlobalObj, bool aClearFromProtoChain)
 {
@@ -3182,33 +3158,33 @@ nsJSContext::ScriptExecuted()
 {
   ScriptEvaluated(!::JS_IsRunning(mContext));
 
   return NS_OK;
 }
 
 //static
 void
-nsJSContext::GarbageCollectNow()
+nsJSContext::GarbageCollectNow(bool shrinkingGC)
 {
   NS_TIME_FUNCTION_MIN(1.0);
 
   KillGCTimer();
 
   // Reset sPendingLoadCount in case the timer that fired was a
   // timer we scheduled due to a normal GC timer firing while
   // documents were loading. If this happens we're waiting for a
   // document that is taking a long time to load, and we effectively
   // ignore the fact that the currently loading documents are still
   // loading and move on as if they weren't.
   sPendingLoadCount = 0;
   sLoadingInProgress = false;
 
   if (nsContentUtils::XPConnect()) {
-    nsContentUtils::XPConnect()->GarbageCollect();
+    nsContentUtils::XPConnect()->GarbageCollect(shrinkingGC);
   }
 }
 
 //Static
 void
 nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener)
 {
   if (!NS_IsMainThread()) {
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -177,17 +177,17 @@ public:
   virtual void EnterModalState();
   virtual void LeaveModalState();
 
   NS_DECL_NSIXPCSCRIPTNOTIFY
 
   static void LoadStart();
   static void LoadEnd();
 
-  static void GarbageCollectNow();
+  static void GarbageCollectNow(bool shrinkingGC = false);
   static void CycleCollectNow(nsICycleCollectorListener *aListener = nsnull);
 
   static void PokeGC();
   static void KillGCTimer();
 
   static void PokeCC();
   static void MaybePokeCC();
   static void KillCCTimer();
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -1543,16 +1543,17 @@ OpenDatabaseHelper::DispatchErrorEvent()
 
 void
 OpenDatabaseHelper::ReleaseMainThreadObjects()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mOpenDBRequest = nsnull;
   mDatabase = nsnull;
+  mDatabaseId = nsnull;
 
   HelperBase::ReleaseMainThreadObjects();
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(SetVersionHelper, AsyncConnectionHelper);
 
 nsresult
 SetVersionHelper::Init()
--- a/dom/interfaces/base/Makefile.in
+++ b/dom/interfaces/base/Makefile.in
@@ -50,17 +50,17 @@ SDK_XPIDLSRCS =                         
 	domstubs.idl				\
 	nsIDOMBarProp.idl			\
 	nsIDOMWindow.idl			\
 	nsIDOMWindowCollection.idl		\
 	nsIDOMWindowUtils.idl			\
 	$(NULL)
 
 XPIDLSRCS =					\
-	nsIAnimationFrameListener.idl           \
+	nsIFrameRequestCallback.idl             \
 	nsIBrowserDOMWindow.idl			\
     nsIContentPermissionPrompt.idl  \
 	nsIContentPrefService.idl		\
 	nsIContentURIGrouper.idl		\
 	nsIDOMClientInformation.idl		\
 	nsIDOMConstructor.idl			\
 	nsIDOMCRMFObject.idl			\
 	nsIDOMCrypto.idl			\
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -36,17 +36,17 @@
  * 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 ***** */
 
 #include "domstubs.idl"
 
-interface nsIAnimationFrameListener;
+interface nsIFrameRequestCallback;
 interface nsIControllers;
 interface nsIDOMBlob;
 interface nsIDOMLocation;
 interface nsIDOMMediaQueryList;
 interface nsIDOMOfflineResourceList;
 interface nsIDOMPerformance;
 interface nsIDOMStorage;
 interface nsIDOMStorageList;
@@ -413,17 +413,17 @@ interface nsIDOMWindow : nsISupports
   readonly attribute unsigned long long mozPaintCount;
 
   /**
    * Request a refresh of this browser window.
    *
    * @see <http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html>
    */
   void
-    mozRequestAnimationFrame([optional] in nsIAnimationFrameListener aListener);
+    mozRequestAnimationFrame(in nsIFrameRequestCallback aCallback);
 
   /**
    * The current animation start time in milliseconds since the epoch.
    */
   readonly attribute long long mozAnimationStartTime;
 
   /**
    * @see <http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking>
rename from dom/interfaces/base/nsIAnimationFrameListener.idl
rename to dom/interfaces/base/nsIFrameRequestCallback.idl
--- a/dom/interfaces/base/nsIAnimationFrameListener.idl
+++ b/dom/interfaces/base/nsIFrameRequestCallback.idl
@@ -31,23 +31,21 @@
  * 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 ***** */
 
 /**
- * Interface that represents a listener to be passed to
- * mozRequestAnimationFrame
+ * Interface that represents a callback to be passed to requestAnimationFrame
  */
 
 #include "domstubs.idl"
 
-[scriptable, function, uuid(ba240e38-c15a-4fb2-802a-8a48f09331bd)]
-interface nsIAnimationFrameListener : nsISupports
+[scriptable, function, uuid(e8d887f0-2ed7-406f-9f1d-edeb2c54c0a2)]
+interface nsIFrameRequestCallback : nsISupports
 {
   /**
-   * The timestamp is the same as it would be for the a corresponding
-   * MozBeforePaint event.
+   * The timestamp is the time to be used for the animation sample.
    */
-  void onBeforePaint(in DOMTimeStamp timeStamp);
+  void sample(in DOMTimeStamp timeStamp);
 };
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -910,17 +910,17 @@ TabChild::InitTabChildGlobal()
 
   mCx = cx;
 
   nsContentUtils::XPConnect()->SetSecurityManagerForJSContext(cx, nsContentUtils::GetSecurityManager(), 0);
   nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
 
   JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
 
-  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_PRIVATE_IS_NSISUPPORTS);
+  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
   JS_SetVersion(cx, JSVERSION_LATEST);
   JS_SetErrorReporter(cx, ContentScriptErrorReporter);
 
   xpc_LocalizeContext(cx);
 
   JSAutoRequest ar(cx);
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
--- a/dom/locales/en-US/chrome/layout/htmlparser.properties
+++ b/dom/locales/en-US/chrome/layout/htmlparser.properties
@@ -49,19 +49,19 @@ errGtInPublicId=“>” in public identifier.
 errNamelessDoctype=Nameless doctype.
 errConsecutiveHyphens=Consecutive hyphens did not terminate a comment. “--” is not permitted inside a comment, but e.g. “- -” is.
 errPrematureEndOfComment=Premature end of comment. Use “-->” to end a comment properly.
 errBogusComment=Bogus comment.
 errUnquotedAttributeLt=“<” in an unquoted attribute value. Probable cause: Missing “>” immediately before.
 errUnquotedAttributeGrave=“`” in an unquoted attribute value. Probable cause: Using the wrong character as a quote.
 errUnquotedAttributeQuote=Quote in an unquoted attribute value. Probable causes: Attributes running together or a URL query string in an unquoted attribute value.
 errUnquotedAttributeEquals=“=” in an unquoted attribute value. Probable causes: Attributes running together or a URL query string in an unquoted attribute value.
-errSlashNotFollowedByGt=A slash was not immediate followed by “>”.
+errSlashNotFollowedByGt=A slash was not immediately followed by “>”.
 errNoSpaceBetweenAttributes=No space between attributes.
-errUnquotedAttributeStartLt=“<” at the start of an unquoted attribute value. Probable cause: Missing “>” immediately before
+errUnquotedAttributeStartLt=“<” at the start of an unquoted attribute value. Probable cause: Missing “>” immediately before.
 errUnquotedAttributeStartGrave=“`” at the start of an unquoted attribute value. Probable cause: Using the wrong character as a quote.
 errUnquotedAttributeStartEquals=“=” at the start of an unquoted attribute value. Probable cause: Stray duplicate equals sign.
 errAttributeValueMissing=Attribute value missing.
 errBadCharBeforeAttributeNameLt=Saw “<” when expecting an attribute name. Probable cause: Missing “>” immediately before.
 errEqualsSignBeforeAttributeName=Saw “=” when expecting an attribute name. Probable cause: Attribute name missing.
 errBadCharAfterLt=Bad character after “<”. Probable cause: Unescaped “<”. Try escaping it as “&lt;”.
 errLtGt=Saw “<>”. Probable causes: Unescaped “<” (escape as “&lt;”) or mistyped start tag.
 errProcessingInstruction=Saw “<?”. Probable cause: Attempt to use an XML processing instruction in HTML. (XML processing instructions are not supported in HTML.)
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -3703,16 +3703,17 @@ PluginInstanceChild::ClearAllSurfaces()
 #endif
 }
 
 bool
 PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
+    *aResult = NPERR_NO_ERROR;
 
 #if defined(OS_WIN)
     SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1);
 #endif
 
     InfallibleTArray<PBrowserStreamChild*> streams;
     ManagedPBrowserStreamChild(streams);
 
--- a/dom/plugins/ipc/PluginMessageUtils.cpp
+++ b/dom/plugins/ipc/PluginMessageUtils.cpp
@@ -75,16 +75,32 @@ DeferNPObjectReleaseRunnable::Run()
   return NS_OK;
 }
 
 } // anonymous namespace
 
 namespace mozilla {
 namespace plugins {
 
+NPRemoteWindow::NPRemoteWindow() :
+  window(0), x(0), y(0), width(0), height(0), type(NPWindowTypeDrawable)
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+  , visualID(0)
+  , colormap(0)
+#endif /* XP_UNIX */
+#if defined(XP_WIN)
+  ,surfaceHandle(0)
+#endif
+{
+  clipRect.top = 0;
+  clipRect.left = 0;
+  clipRect.bottom = 0;
+  clipRect.right = 0;
+}
+
 RPCChannel::RacyRPCPolicy
 MediateRace(const RPCChannel::Message& parent,
             const RPCChannel::Message& child)
 {
   switch (parent.type()) {
   case PPluginInstance::Msg_Paint__ID:
   case PPluginInstance::Msg_NPP_SetWindow__ID:
   case PPluginInstance::Msg_NPP_HandleEvent_Shmem__ID:
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -105,16 +105,17 @@ struct IPCByteRange
 };  
 
 typedef std::vector<IPCByteRange> IPCByteRanges;
 
 typedef nsCString Buffer;
 
 struct NPRemoteWindow
 {
+  NPRemoteWindow();
   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)
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -98,31 +98,29 @@ nsJSEventListener::~nsJSEventListener()
 {
   if (mContext)
     nsContentUtils::DropScriptObjects(mContext->GetScriptTypeID(), this,
                                       &NS_CYCLE_COLLECTION_NAME(nsJSEventListener));
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTarget)
   if (tmp->mContext) {
     if (tmp->mContext->GetScriptTypeID() == nsIProgrammingLanguage::JAVASCRIPT) {
       NS_DROP_JS_OBJECTS(tmp, nsJSEventListener);
     }
     else {
       nsContentUtils::DropScriptObjects(tmp->mContext->GetScriptTypeID(), tmp,
                                   &NS_CYCLE_COLLECTION_NAME(nsJSEventListener));
     }
     tmp->mScopeObject = nsnull;
     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSEventListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSEventListener)
   NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(tmp->mContext->GetScriptTypeID(),
                                                  mScopeObject)
   NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(tmp->mContext->GetScriptTypeID(),
@@ -269,17 +267,17 @@ nsJSEventListener::SetHandler(JSObject *
 
 /*
  * Factory functions
  */
 
 nsresult
 NS_NewJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
                       nsISupports*aTarget, nsIAtom* aEventType,
-                      JSObject* aHandler, nsIDOMEventListener ** aReturn)
+                      JSObject* aHandler, nsIJSEventListener** aReturn)
 {
   NS_ENSURE_ARG(aEventType);
   nsJSEventListener* it =
     new nsJSEventListener(aContext, aScopeObject, aTarget, aEventType,
                           aHandler);
   NS_ADDREF(*aReturn = it);
 
   return NS_OK;
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -146,34 +146,32 @@ const char* gStringChars[] = {
 
 PR_STATIC_ASSERT(NS_ARRAY_LENGTH(gStringChars) == ID_COUNT);
 
 enum {
   PREF_strict = 0,
   PREF_werror,
   PREF_relimit,
   PREF_methodjit,
-  PREF_jitprofiling,
   PREF_methodjit_always,
 
 #ifdef JS_GC_ZEAL
   PREF_gczeal,
 #endif
 
   PREF_COUNT
 };
 
 #define JS_OPTIONS_DOT_STR "javascript.options."
 
 const char* gPrefsToWatch[] = {
   JS_OPTIONS_DOT_STR "strict",
   JS_OPTIONS_DOT_STR "werror",
   JS_OPTIONS_DOT_STR "relimit",
   JS_OPTIONS_DOT_STR "methodjit.content",
-  JS_OPTIONS_DOT_STR "jitprofiling.content",
   JS_OPTIONS_DOT_STR "methodjit_always"
 
 #ifdef JS_GC_ZEAL
   , PREF_WORKERS_GCZEAL
 #endif
 };
 
 PR_STATIC_ASSERT(NS_ARRAY_LENGTH(gPrefsToWatch) == PREF_COUNT);
@@ -197,19 +195,16 @@ PrefCallback(const char* aPrefName, void
       newOptions |= JSOPTION_WERROR;
     }
     if (Preferences::GetBool(gPrefsToWatch[PREF_relimit])) {
       newOptions |= JSOPTION_RELIMIT;
     }
     if (Preferences::GetBool(gPrefsToWatch[PREF_methodjit])) {
       newOptions |= JSOPTION_METHODJIT;
     }
-    if (Preferences::GetBool(gPrefsToWatch[PREF_jitprofiling])) {
-      newOptions |= JSOPTION_PROFILING;
-    }
     if (Preferences::GetBool(gPrefsToWatch[PREF_methodjit_always])) {
       newOptions |= JSOPTION_METHODJIT_ALWAYS;
     }
     RuntimeService::SetDefaultJSContextOptions(newOptions);
     rts->UpdateAllWorkerJSContextOptions();
   }
 #ifdef JS_GC_ZEAL
   else if (!strcmp(aPrefName, gPrefsToWatch[PREF_gczeal])) {
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -115,16 +115,17 @@
 #include "nsITransferable.h"
 #include "nsComputedDOMStyle.h"
 #include "nsTextEditUtils.h"
 #include "nsComputedDOMStyle.h"
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Element.h"
+#include "nsContentUtils.h"
 
 #define NS_ERROR_EDITOR_NO_SELECTION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,1)
 #define NS_ERROR_EDITOR_NO_TEXTNODE  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
 
 #ifdef NS_DEBUG_EDITOR
 static bool gNoisy = false;
 #endif
 
@@ -3144,57 +3145,62 @@ nsEditor::GetLengthOfDOMNode(nsIDOMNode 
 }
 
 
 nsresult 
 nsEditor::GetPriorNode(nsIDOMNode  *aParentNode, 
                        PRInt32      aOffset, 
                        bool         aEditableNode, 
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing)
+                       bool         bNoBlockCrossing,
+                       nsIContent  *aActiveEditorRoot)
 {
   // just another version of GetPriorNode that takes a {parent, offset}
   // instead of a node
   if (!aParentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
   *aResultNode = nsnull;
   
   // if we are at beginning of node, or it is a textnode, then just look before it
   if (!aOffset || IsTextNode(aParentNode))
   {
     if (bNoBlockCrossing && IsBlockNode(aParentNode))
     {
       // if we aren't allowed to cross blocks, don't look before this block
       return NS_OK;
     }
-    return GetPriorNode(aParentNode, aEditableNode, aResultNode, bNoBlockCrossing);
+    return GetPriorNode(aParentNode, aEditableNode, aResultNode,
+                        bNoBlockCrossing, aActiveEditorRoot);
   }
 
   // else look before the child at 'aOffset'
   nsCOMPtr<nsIDOMNode> child = GetChildAt(aParentNode, aOffset);
   if (child)
-    return GetPriorNode(child, aEditableNode, aResultNode, bNoBlockCrossing);
+    return GetPriorNode(child, aEditableNode, aResultNode, bNoBlockCrossing,
+                        aActiveEditorRoot);
 
   // unless there isn't one, in which case we are at the end of the node
   // and want the deep-right child.
   *aResultNode = GetRightmostChild(aParentNode, bNoBlockCrossing);
   if (!*aResultNode || !aEditableNode || IsEditable(*aResultNode))
     return NS_OK;
 
   // restart the search from the non-editable node we just found
-  nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
-  return GetPriorNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
+  nsCOMPtr<nsIDOMNode> notEditableNode = *aResultNode;
+  return GetPriorNode(notEditableNode, aEditableNode, aResultNode,
+                      bNoBlockCrossing, aActiveEditorRoot);
 }
 
 
 nsresult 
 nsEditor::GetNextNode(nsIDOMNode   *aParentNode, 
-                       PRInt32      aOffset, 
-                       bool         aEditableNode, 
-                       nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing)
+                      PRInt32      aOffset, 
+                      bool         aEditableNode, 
+                      nsCOMPtr<nsIDOMNode> *aResultNode,
+                      bool         bNoBlockCrossing,
+                      nsIContent  *aActiveEditorRoot)
 {
   // just another version of GetNextNode that takes a {parent, offset}
   // instead of a node
   if (!aParentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
   
   *aResultNode = nsnull;
 
   // if aParentNode is a text node, use it's location instead
@@ -3226,254 +3232,168 @@ nsEditor::GetNextNode(nsIDOMNode   *aPar
       return NS_OK;
     }
 
     if (!aEditableNode || IsEditable(*aResultNode))
       return NS_OK;
 
     // restart the search from the non-editable node we just found
     nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
-    return GetNextNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
+    return GetNextNode(notEditableNode, aEditableNode, aResultNode,
+                       bNoBlockCrossing, aActiveEditorRoot);
   }
     
   // unless there isn't one, in which case we are at the end of the node
   // and want the next one.
   if (bNoBlockCrossing && IsBlockNode(aParentNode))
   {
     // don't cross out of parent block
     return NS_OK;
   }
-  return GetNextNode(aParentNode, aEditableNode, aResultNode, bNoBlockCrossing);
+  return GetNextNode(aParentNode, aEditableNode, aResultNode, bNoBlockCrossing,
+                     aActiveEditorRoot);
 }
 
 
 nsresult 
 nsEditor::GetPriorNode(nsIDOMNode  *aCurrentNode, 
                        bool         aEditableNode, 
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing)
-{
-  nsresult result;
+                       bool         bNoBlockCrossing,
+                       nsIContent  *aActiveEditorRoot)
+{
   if (!aCurrentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
-  
-  *aResultNode = nsnull;  // init out-param
-
-  if (IsRootNode(aCurrentNode))
-  {
-    // Don't allow traversal above the root node! This helps
-    // prevent us from accidentally editing browser content
-    // when the editor is in a text widget.
-
+
+  nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
+
+  if (!IsDescendantOfBody(currentNode) ||
+      (aActiveEditorRoot &&
+       !nsContentUtils::ContentIsDescendantOf(currentNode,
+                                              aActiveEditorRoot))) {
+    *aResultNode = nsnull;
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMNode> candidate;
-  result = GetPriorNodeImpl(aCurrentNode, aEditableNode, address_of(candidate), bNoBlockCrossing);
-  NS_ENSURE_SUCCESS(result, result);
-  
-  if (!candidate)
-  {
-    // we could not find a prior node.  return null.
-    return NS_OK;
-  }
-  else if (!aEditableNode) *aResultNode = candidate;
-  else if (IsEditable(candidate)) *aResultNode = candidate;
-  else 
-  { // restart the search from the non-editable node we just found
-    nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(candidate);
-    return GetPriorNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
-  }
-  return result;
-}
-
-nsresult 
-nsEditor::GetPriorNodeImpl(nsIDOMNode  *aCurrentNode, 
-                           bool         aEditableNode, 
-                           nsCOMPtr<nsIDOMNode> *aResultNode,
-                           bool         bNoBlockCrossing)
+  *aResultNode =
+    do_QueryInterface(FindNode(currentNode, false, aEditableNode,
+                               bNoBlockCrossing, aActiveEditorRoot));
+  return NS_OK;
+}
+
+nsIContent*
+nsEditor::FindNextLeafNode(nsINode  *aCurrentNode, 
+                           bool      aGoForward,
+                           bool      bNoBlockCrossing,
+                           nsIContent *aActiveEditorRoot)
 {
   // called only by GetPriorNode so we don't need to check params.
-
-  // if aCurrentNode has a left sibling, return that sibling's rightmost child (or itself if it has no children)
-  nsCOMPtr<nsIDOMNode> prevSibling;
-  nsresult result = aCurrentNode->GetPreviousSibling(getter_AddRefs(prevSibling));
-  if ((NS_SUCCEEDED(result)) && prevSibling)
-  {
-    if (bNoBlockCrossing && IsBlockNode(prevSibling))
-    {
-      // don't look inside prevsib, since it is a block
-      *aResultNode = prevSibling;
-      return NS_OK;
+  NS_PRECONDITION(IsDescendantOfBody(aCurrentNode) && !IsRootNode(aCurrentNode) &&
+                  (!aActiveEditorRoot ||
+                   nsContentUtils::ContentIsDescendantOf(aCurrentNode,
+                                                         aActiveEditorRoot)),
+                  "Bogus arguments");
+
+  nsINode* cur = aCurrentNode;
+  for (;;) {
+    // if aCurrentNode has a sibling in the right direction, return
+    // that sibling's closest child (or itself if it has no children)
+    nsIContent* sibling =
+      aGoForward ? cur->GetNextSibling() : cur->GetPreviousSibling();
+    if (sibling) {
+      if (bNoBlockCrossing && IsBlockNode(sibling)) {
+        // don't look inside prevsib, since it is a block
+        return sibling;
+      }
+      nsIContent *leaf =
+        aGoForward ? GetLeftmostChild(sibling, bNoBlockCrossing) :
+                     GetRightmostChild(sibling, bNoBlockCrossing);
+      if (!leaf) { 
+        return sibling;
+      }
+
+      return leaf;
     }
-    *aResultNode = GetRightmostChild(prevSibling, bNoBlockCrossing);
-    if (!*aResultNode) 
-    { 
-      *aResultNode = prevSibling;
-      return NS_OK;
+
+    nsINode *parent = cur->GetNodeParent();
+    if (!parent) {
+      return nsnull;
     }
-    if (!IsDescendantOfBody(*aResultNode))
-    {
-      *aResultNode = nsnull;
-      return NS_OK;
+
+    NS_ASSERTION(IsDescendantOfBody(parent),
+                 "We started with a proper descendant of root, and should stop "
+                 "if we ever hit the root, so we better have a descendant of "
+                 "root now!");
+    if (IsRootNode(parent) ||
+        (bNoBlockCrossing && IsBlockNode(parent)) ||
+        parent == aActiveEditorRoot) {
+      return nsnull;
     }
+
+    cur = parent;
   }
-  else
-  {
-    // otherwise, walk up the parent tree until there is a child that comes before 
-    // the ancestor of aCurrentNode.  Then return that node's rightmost child
-    nsCOMPtr<nsIDOMNode> parent = do_QueryInterface(aCurrentNode);
-    nsCOMPtr<nsIDOMNode> node, notEditableNode;
-    do {
-      node = parent;
-      result = node->GetParentNode(getter_AddRefs(parent));
-      if ((NS_SUCCEEDED(result)) && parent)
-      {
-        if (!IsDescendantOfBody(parent))
-        {
-          *aResultNode = nsnull;
-          return NS_OK;
-        }
-        if ((bNoBlockCrossing && IsBlockNode(parent)) || IsRootNode(parent))
-        {
-          // we are at front of block or root, do not step out
-          *aResultNode = nsnull;
-          return NS_OK;
-        }
-        result = parent->GetPreviousSibling(getter_AddRefs(node));
-        if ((NS_SUCCEEDED(result)) && node)
-        {
-          if (bNoBlockCrossing && IsBlockNode(node))
-          {
-            // prev sibling is a block, do not step into it
-            *aResultNode = node;
-            return NS_OK;
-          }
-          *aResultNode = GetRightmostChild(node, bNoBlockCrossing);
-          if (!*aResultNode)  *aResultNode = node;
-          return NS_OK;
-        }
-      }
-    } while ((NS_SUCCEEDED(result)) && parent && !*aResultNode);
-  }
-  return result;
+
+  NS_NOTREACHED("What part of for(;;) do you not understand?");
+  return nsnull;
 }
 
 nsresult 
 nsEditor::GetNextNode(nsIDOMNode  *aCurrentNode, 
                       bool         aEditableNode, 
                       nsCOMPtr<nsIDOMNode> *aResultNode,
-                      bool         bNoBlockCrossing)
+                      bool         bNoBlockCrossing,
+                      nsIContent  *aActiveEditorRoot)
 {
   if (!aCurrentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
-  
-  *aResultNode = nsnull;  // init out-param
-
-  if (IsRootNode(aCurrentNode))
+
+  nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
+  if (!IsDescendantOfBody(currentNode) ||
+      (aActiveEditorRoot &&
+       !nsContentUtils::ContentIsDescendantOf(currentNode,
+                                              aActiveEditorRoot))) {
+    *aResultNode = nsnull;
+    return NS_OK;
+  }
+
+  *aResultNode =
+    do_QueryInterface(FindNode(currentNode, true, aEditableNode,
+                               bNoBlockCrossing, aActiveEditorRoot));
+  return NS_OK;
+}
+
+nsIContent*
+nsEditor::FindNode(nsINode *aCurrentNode,
+                   bool     aGoForward,
+                   bool     aEditableNode,
+                   bool     bNoBlockCrossing,
+                   nsIContent *aActiveEditorRoot)
+{
+  if (IsRootNode(aCurrentNode) || aCurrentNode == aActiveEditorRoot)
   {
     // Don't allow traversal above the root node! This helps
     // prevent us from accidentally editing browser content
     // when the editor is in a text widget.
 
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIDOMNode> candidate;
-  nsresult result = GetNextNodeImpl(aCurrentNode, aEditableNode,
-                                    address_of(candidate), bNoBlockCrossing);
-  NS_ENSURE_SUCCESS(result, result);
-  
-  if (!candidate)
-  {
-    // we could not find a next node.  return null.
-    *aResultNode = nsnull;
-    return NS_OK;
-  }
-  else if (!aEditableNode) *aResultNode = candidate;
-  else if (IsEditable(candidate)) *aResultNode = candidate;
-  else 
-  { // restart the search from the non-editable node we just found
-    nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(candidate);
-    return GetNextNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
+    return nsnull;
   }
-  return result;
-}
-
-
-nsresult 
-nsEditor::GetNextNodeImpl(nsIDOMNode  *aCurrentNode, 
-                          bool         aEditableNode, 
-                          nsCOMPtr<nsIDOMNode> *aResultNode,
-                          bool         bNoBlockCrossing)
-{
-  // called only by GetNextNode so we don't need to check params.
-
-  // if aCurrentNode has a right sibling, return that sibling's leftmost child (or itself if it has no children)
-  nsCOMPtr<nsIDOMNode> nextSibling;
-  nsresult result = aCurrentNode->GetNextSibling(getter_AddRefs(nextSibling));
-  if ((NS_SUCCEEDED(result)) && nextSibling)
-  {
-    if (bNoBlockCrossing && IsBlockNode(nextSibling))
-    {
-      // next sibling is a block, do not step into it
-      *aResultNode = nextSibling;
-      return NS_OK;
-    }
-    *aResultNode = GetLeftmostChild(nextSibling, bNoBlockCrossing);
-    if (!*aResultNode)
-    { 
-      *aResultNode = nextSibling;
-      return NS_OK; 
-    }
-    if (!IsDescendantOfBody(*aResultNode))
-    {
-      *aResultNode = nsnull;
-      return NS_OK;
-    }
+
+  nsIContent* candidate =
+    FindNextLeafNode(aCurrentNode, aGoForward, bNoBlockCrossing,
+                     aActiveEditorRoot);
+  
+  if (!candidate) {
+    return nsnull;
   }
-  else
-  {
-    // otherwise, walk up the parent tree until there is a child that comes after 
-    // the ancestor of aCurrentNode.  Then return that node's leftmost child
-    nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
-    nsCOMPtr<nsIDOMNode> node, notEditableNode;
-    do {
-      node = parent;
-      result = node->GetParentNode(getter_AddRefs(parent));
-      if ((NS_SUCCEEDED(result)) && parent)
-      {
-        if (!IsDescendantOfBody(parent))
-        {
-          *aResultNode = nsnull;
-          return NS_OK;
-        }
-        if ((bNoBlockCrossing && IsBlockNode(parent)) || IsRootNode(parent))
-        {
-          // we are at end of block or root, do not step out
-          *aResultNode = nsnull;
-          return NS_OK;
-        }
-        result = parent->GetNextSibling(getter_AddRefs(node));
-        if ((NS_SUCCEEDED(result)) && node)
-        {
-          if (bNoBlockCrossing && IsBlockNode(node))
-          {
-            // next sibling is a block, do not step into it
-            *aResultNode = node;
-            return NS_OK;
-          }
-          *aResultNode = GetLeftmostChild(node, bNoBlockCrossing);
-          if (!*aResultNode) *aResultNode = node;
-          return NS_OK; 
-        }
-      }
-    } while ((NS_SUCCEEDED(result)) && parent);
+
+  if (!aEditableNode || IsEditable(candidate)) {
+    return candidate;
   }
-  return result;
-}
-
+
+  return FindNode(candidate, aGoForward, aEditableNode, bNoBlockCrossing,
+                  aActiveEditorRoot);
+}
 
 already_AddRefed<nsIDOMNode>
 nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode, 
                             bool bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(aCurrentNode, nsnull);
   nsCOMPtr<nsIDOMNode> resultNode, temp = aCurrentNode;
   bool hasChildren;
@@ -3489,16 +3409,64 @@ nsEditor::GetRightmostChild(nsIDOMNode *
     } else {
       hasChildren = false;
     }
   }
 
   return resultNode.forget();
 }
 
+nsIContent*
+nsEditor::GetRightmostChild(nsINode *aCurrentNode,
+                            bool     bNoBlockCrossing)
+{
+  NS_ENSURE_TRUE(aCurrentNode, nsnull);
+  nsIContent *cur = aCurrentNode->GetLastChild();
+  if (!cur) {
+    return nsnull;
+  }
+  for (;;) {
+    if (bNoBlockCrossing && IsBlockNode(cur)) {
+      return cur;
+    }
+    nsIContent* next = cur->GetLastChild();
+    if (!next) {
+      return cur;
+    }
+    cur = next;
+  }
+
+  NS_NOTREACHED("What part of for(;;) do you not understand?");
+  return nsnull;
+}
+
+nsIContent*
+nsEditor::GetLeftmostChild(nsINode *aCurrentNode,
+                           bool     bNoBlockCrossing)
+{
+  NS_ENSURE_TRUE(aCurrentNode, nsnull);
+  nsIContent *cur = aCurrentNode->GetFirstChild();
+  if (!cur) {
+    return nsnull;
+  }
+  for (;;) {
+    if (bNoBlockCrossing && IsBlockNode(cur)) {
+      return cur;
+    }
+    nsIContent *next = cur->GetFirstChild();
+    if (!next) {
+      return cur;
+    }
+    cur = next;
+  }
+
+  NS_NOTREACHED("What part of for(;;) do you not understand?");
+  return nsnull;
+}
+
 already_AddRefed<nsIDOMNode>
 nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode,
                            bool bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(aCurrentNode, nsnull);
   nsCOMPtr<nsIDOMNode> resultNode, temp = aCurrentNode;
   bool hasChildren;
   aCurrentNode->HasChildNodes(&hasChildren);
@@ -3524,16 +3492,26 @@ nsEditor::IsBlockNode(nsIDOMNode *aNode)
   // stub to be overridden in nsHTMLEditor.
   // screwing around with the class hierarchy here in order
   // to not duplicate the code in GetNextNode/GetPrevNode
   // across both nsEditor/nsHTMLEditor.  
   return false;
 }
 
 bool 
+nsEditor::IsBlockNode(nsINode *aNode)
+{
+  // stub to be overridden in nsHTMLEditor.
+  // screwing around with the class hierarchy here in order
+  // to not duplicate the code in GetNextNode/GetPrevNode
+  // across both nsEditor/nsHTMLEditor.
+  return false;
+}
+
+bool
 nsEditor::CanContainTag(nsIDOMNode* aParent, const nsAString &aChildTag)
 {
   nsCOMPtr<nsIDOMElement> parentElement = do_QueryInterface(aParent);
   NS_ENSURE_TRUE(parentElement, false);
   
   nsAutoString parentStringTag;
   parentElement->GetTagName(parentStringTag);
   return TagCanContainTag(parentStringTag, aChildTag);
@@ -3558,106 +3536,161 @@ nsEditor::TagCanContain(const nsAString 
 }
 
 bool 
 nsEditor::TagCanContainTag(const nsAString &aParentTag, const nsAString &aChildTag)
 {
   return true;
 }
 
+bool
+nsEditor::IsRootNode(nsIDOMNode *inNode)
+{
+  NS_ENSURE_TRUE(inNode, false);
+
+  return inNode == GetRoot();
+}
+
 bool 
-nsEditor::IsRootNode(nsIDOMNode *inNode) 
+nsEditor::IsRootNode(nsINode *inNode) 
 {
   NS_ENSURE_TRUE(inNode, false);
 
   nsIDOMElement *rootElement = GetRoot();
 
-  nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(rootElement);
-
-  return inNode == rootNode;
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
+
+  return node == rootElement;
 }
 
 bool 
 nsEditor::IsDescendantOfBody(nsIDOMNode *inNode) 
 {
+  nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
+  return IsDescendantOfBody(node);
+}
+
+bool
+nsEditor::IsDescendantOfBody(nsINode *inNode)
+{
   NS_ENSURE_TRUE(inNode, false);
-  nsIDOMElement *rootElement = GetRoot();
-  NS_ENSURE_TRUE(rootElement, false);
-  nsCOMPtr<nsIDOMNode> root = do_QueryInterface(rootElement);
-
-  if (inNode == root.get()) return true;
-  
-  nsCOMPtr<nsIDOMNode> parent, node = do_QueryInterface(inNode);
-  
-  do
-  {
-    node->GetParentNode(getter_AddRefs(parent));
-    if (parent == root) return true;
-    node = parent;
-  } while (parent);
-  
-  return false;
+  nsCOMPtr<nsIContent> root = do_QueryInterface(GetRoot());
+  NS_ENSURE_TRUE(root, false);
+
+  return nsContentUtils::ContentIsDescendantOf(inNode, root);
 }
 
 bool 
 nsEditor::IsContainer(nsIDOMNode *aNode)
 {
   return aNode ? true : false;
 }
 
 bool
-nsEditor::IsTextInDirtyFrameVisible(nsIDOMNode *aNode)
+nsEditor::IsTextInDirtyFrameVisible(nsIContent *aNode)
 {
   // virtual method
   //
   // If this is a simple non-html editor,
   // the best we can do is to assume it's visible.
 
   return true;
 }
 
-static bool
-IsElementVisible(nsIContent* aContent) {
-  mozilla::dom::Element* element = aContent->AsElement();
+static inline bool
+IsElementVisible(dom::Element* aElement)
+{
+  if (aElement->GetPrimaryFrame()) {
+    // It's visible, for our purposes
+    return true;
+  }
+
+  nsIContent *cur = aElement;
+  for (; ;) {
+    cur = cur->GetFlattenedTreeParent();
+    if (!cur) {
+      // None of our ancestors have lazy bits set, so we shouldn't have a frame
+      return false;
+    }
+
+    if (cur->GetPrimaryFrame()) {
+      // None of our ancestors up to the nearest ancestor with a frame have
+      // lazy bits; that means we won't get a frame
+      return false;
+    }
+
+    if (cur->HasFlag(NODE_NEEDS_FRAME)) {
+      // Double-check that the parent doesn't have a leaf frame
+      nsIContent *parent = cur->GetFlattenedTreeParent();
+      if (parent) {
+        NS_ASSERTION(parent->GetPrimaryFrame(),
+                     "Why does our parent not have a frame?");
+        if (parent->GetPrimaryFrame()->IsLeaf()) {
+          // No frame for us
+          return false;
+        }
+      }
+
+      // |cur| will get a frame sometime.  What does that mean for us?
+      // |We have to figure that out!
+      break;
+    }
+  }
+
+  // Now it might be that we have no frame because we're in a
+  // display:none subtree, or it might be that we're just dealing with
+  // lazy frame construction and it hasn't happened yet.  Check which
+  // one it is.
   nsRefPtr<nsStyleContext> styleContext =
-    nsComputedDOMStyle::GetStyleContextForElementNoFlush(element,
+    nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
                                                          nsnull, nsnull);
   if (styleContext) {
     return styleContext->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_NONE;
   }
   return false;
 }
 
 bool 
 nsEditor::IsEditable(nsIDOMNode *aNode)
 {
+  nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
+  return IsEditable(content);
+}
+
+bool
+nsEditor::IsEditable(nsIContent *aNode)
+{
   NS_ENSURE_TRUE(aNode, false);
 
   if (IsMozEditorBogusNode(aNode) || !IsModifiableNode(aNode)) return false;
 
   // see if it has a frame.  If so, we'll edit it.
   // special case for textnodes: frame must have width.
-  nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
-  if (content)
-  {
-    if (content->IsElement() &&
-        !IsElementVisible(content)) // If the element is invisible, it's not editable
-      return false;
-    if (!content->IsNodeOfType(nsINode::eTEXT))
-      return true;  // not a text node; not invisible
-
-    return IsTextInDirtyFrameVisible(aNode);
+  if (aNode->IsElement() && !IsElementVisible(aNode->AsElement())) {
+    // If the element has no frame, it's not editable.  Note that we
+    // need to check IsElement() here, because some of our tests
+    // rely on frameless textnodes being visible.
+    return false;
   }
-  return false;  // didn't pass any editability test
+  if (aNode->NodeType() != nsIDOMNode::TEXT_NODE)
+    return true;  // not a text node; not invisible
+
+  return IsTextInDirtyFrameVisible(aNode);
 }
 
 bool
 nsEditor::IsMozEditorBogusNode(nsIDOMNode *aNode)
 {
   nsCOMPtr<nsIContent> element = do_QueryInterface(aNode);
+  return IsMozEditorBogusNode(element);
+}
+
+bool
+nsEditor::IsMozEditorBogusNode(nsIContent *element)
+{
   return element &&
          element->AttrValueIs(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
                               kMOZEditorBogusNodeValue, eCaseMatters);
 }
 
 nsresult
 nsEditor::CountEditableChildren(nsIDOMNode *aNode, PRUint32 &outCount) 
 {
@@ -3730,17 +3763,17 @@ NS_IMETHODIMP nsEditor::ResetModificatio
 }
 
 //END nsEditor Private methods
 
 
 
 ///////////////////////////////////////////////////////////////////////////
 // GetTag: digs out the atom for the tag of this node
-//                    
+//
 nsIAtom *
 nsEditor::GetTag(nsIDOMNode *aNode)
 {
   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
 
   if (!content) 
   {
     NS_ASSERTION(aNode, "null node passed to nsEditor::Tag()");
@@ -3821,16 +3854,21 @@ nsEditor::IsTextNode(nsIDOMNode *aNode)
     return false;
   }
   
   PRUint16 nodeType;
   aNode->GetNodeType(&nodeType);
   return (nodeType == nsIDOMNode::TEXT_NODE);
 }
 
+bool
+nsEditor::IsTextNode(nsINode *aNode)
+{
+  return aNode->NodeType() == nsIDOMNode::TEXT_NODE;
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // GetIndexOf: returns the position index of the node in the parent
 //
 PRInt32 
 nsEditor::GetIndexOf(nsIDOMNode *parent, nsIDOMNode *child)
 {
   nsCOMPtr<nsINode> parentNode = do_QueryInterface(parent);
@@ -5329,16 +5367,22 @@ nsEditor::DumpNode(nsIDOMNode *aNode, PR
 #endif
 
 bool
 nsEditor::IsModifiableNode(nsIDOMNode *aNode)
 {
   return true;
 }
 
+bool
+nsEditor::IsModifiableNode(nsINode *aNode)
+{
+  return true;
+}
+
 nsKeyEvent*
 nsEditor::GetNativeKeyEvent(nsIDOMKeyEvent* aDOMKeyEvent)
 {
   nsCOMPtr<nsIPrivateDOMEvent> privDOMEvent = do_QueryInterface(aDOMKeyEvent);
   NS_ENSURE_TRUE(privDOMEvent, nsnull);
   nsEvent* nativeEvent = privDOMEvent->GetInternalNSEvent();
   NS_ENSURE_TRUE(nativeEvent, nsnull);
   NS_ENSURE_TRUE(nativeEvent->eventStructType == NS_KEY_EVENT, nsnull);
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -164,16 +164,17 @@ public:
   /* ------------ nsIObserver methods -------------- */
   NS_DECL_NSIOBSERVER
 
   // nsIPhonetic
   NS_DECL_NSIPHONETIC
 
 public:
 
+  virtual bool IsModifiableNode(nsINode *aNode);
   
   NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, 
                                nsCOMPtr<nsIDOMNode> *aInOutNode, 
                                PRInt32 *aInOutOffset,
                                nsIDOMDocument *aDoc);
   nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert, 
                                       nsIDOMCharacterData *aTextNode, 
                                       PRInt32 aOffset,
@@ -362,28 +363,23 @@ protected:
    *  in the various selection interfaces, since this version makes sure
    *  that the editor's sync/async settings for reflowing, painting, and
    *  scrolling match.
    */
   NS_IMETHOD ScrollSelectionIntoView(bool aScrollToAnchor);
 
   // stub.  see comment in source.                     
   virtual bool IsBlockNode(nsIDOMNode *aNode);
+  virtual bool IsBlockNode(nsINode *aNode);
   
-  // helper for GetPriorNode
-  nsresult GetPriorNodeImpl(nsIDOMNode  *aCurrentNode, 
-                            bool         aEditableNode,
-                            nsCOMPtr<nsIDOMNode> *aResultNode,
-                            bool         bNoBlockCrossing = false);
-
-  // helper for GetNextNode
-  nsresult GetNextNodeImpl(nsIDOMNode  *aCurrentNode, 
-                           bool         aEditableNode,
-                           nsCOMPtr<nsIDOMNode> *aResultNode,
-                           bool         bNoBlockCrossing = false);
+  // helper for GetPriorNode and GetNextNode
+  nsIContent* FindNextLeafNode(nsINode  *aCurrentNode,
+                               bool      aGoForward,
+                               bool      bNoBlockCrossing,
+                               nsIContent *aActiveEditorRoot);
 
   // Get nsIWidget interface
   nsresult GetWidget(nsIWidget **aWidget);
 
 
   // install the event listeners for the editor 
   virtual nsresult InstallEventListeners();
 
@@ -474,61 +470,77 @@ public:
   static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount);
 
   /** get the node immediately prior to aCurrentNode
     * @param aCurrentNode   the node from which we start the search
     * @param aEditableNode  if true, only return an editable node
     * @param aResultNode    [OUT] the node that occurs before aCurrentNode in the tree,
     *                       skipping non-editable nodes if aEditableNode is true.
     *                       If there is no prior node, aResultNode will be nsnull.
+    * @param bNoBlockCrossing If true, don't move across "block" nodes, whatever that means.
+    * @param aActiveEditorRoot If non-null, only return descendants of aActiveEditorRoot.
     */
   nsresult GetPriorNode(nsIDOMNode  *aCurrentNode, 
                         bool         aEditableNode,
                         nsCOMPtr<nsIDOMNode> *aResultNode,
-                        bool         bNoBlockCrossing = false);
+                        bool         bNoBlockCrossing = false,
+                        nsIContent  *aActiveEditorRoot = nsnull);
 
   // and another version that takes a {parent,offset} pair rather than a node
   nsresult GetPriorNode(nsIDOMNode  *aParentNode, 
                         PRInt32      aOffset, 
                         bool         aEditableNode, 
                         nsCOMPtr<nsIDOMNode> *aResultNode,
-                        bool         bNoBlockCrossing = false);
+                        bool         bNoBlockCrossing = false,
+                        nsIContent  *aActiveEditorRoot = nsnull);
                        
   /** get the node immediately after to aCurrentNode
     * @param aCurrentNode   the node from which we start the search
     * @param aEditableNode  if true, only return an editable node
     * @param aResultNode    [OUT] the node that occurs after aCurrentNode in the tree,
     *                       skipping non-editable nodes if aEditableNode is true.
     *                       If there is no prior node, aResultNode will be nsnull.
     */
   nsresult GetNextNode(nsIDOMNode  *aCurrentNode, 
                        bool         aEditableNode,
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing = false);
+                       bool         bNoBlockCrossing = false,
+                       nsIContent  *aActiveEditorRoot = nsnull);
 
   // and another version that takes a {parent,offset} pair rather than a node
   nsresult GetNextNode(nsIDOMNode  *aParentNode, 
                        PRInt32      aOffset, 
                        bool         aEditableNode, 
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing = false);
+                       bool         bNoBlockCrossing = false,
+                       nsIContent  *aActiveEditorRoot = nsnull);
 
+  // Helper for GetNextNode and GetPriorNode
+  nsIContent* FindNode(nsINode *aCurrentNode,
+                       bool     aGoForward,
+                       bool     aEditableNode,
+                       bool     bNoBlockCrossing,
+                       nsIContent *aActiveEditorRoot);
   /**
    * Get the rightmost child of aCurrentNode;
    * return nsnull if aCurrentNode has no children.
    */
   already_AddRefed<nsIDOMNode> GetRightmostChild(nsIDOMNode *aCurrentNode, 
                                                  bool        bNoBlockCrossing = false);
+  nsIContent* GetRightmostChild(nsINode *aCurrentNode,
+                                bool     bNoBlockCrossing = false);
 
   /**
    * Get the leftmost child of aCurrentNode;
    * return nsnull if aCurrentNode has no children.
    */
   already_AddRefed<nsIDOMNode> GetLeftmostChild(nsIDOMNode  *aCurrentNode, 
                                                 bool        bNoBlockCrossing = false);
+  nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
+                               bool     bNoBlockCrossing = false);
 
   /** returns true if aNode is of the type implied by aTag */
   static inline bool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
   {
     return GetTag(aNode) == aTag;
   }
 
   // we should get rid of this method if we can
@@ -541,30 +553,34 @@ public:
 
   /** returns true if aParent can contain a child of type aTag */
   bool CanContainTag(nsIDOMNode* aParent, const nsAString &aTag);
   bool TagCanContain(const nsAString &aParentTag, nsIDOMNode* aChild);
   virtual bool TagCanContainTag(const nsAString &aParentTag, const nsAString &aChildTag);
 
   /** returns true if aNode is our root node */
   bool IsRootNode(nsIDOMNode *inNode);
+  bool IsRootNode(nsINode *inNode);
 
   /** returns true if aNode is a descendant of our root node */
   bool IsDescendantOfBody(nsIDOMNode *inNode);
+  bool IsDescendantOfBody(nsINode *inNode);
 
   /** returns true if aNode is a container */
   virtual bool IsContainer(nsIDOMNode *aNode);
 
   /** returns true if aNode is an editable node */
   bool IsEditable(nsIDOMNode *aNode);
+  bool IsEditable(nsIContent *aNode);
 
-  virtual bool IsTextInDirtyFrameVisible(nsIDOMNode *aNode);
+  virtual bool IsTextInDirtyFrameVisible(nsIContent *aNode);
 
   /** returns true if aNode is a MozEditorBogus node */
   bool IsMozEditorBogusNode(nsIDOMNode *aNode);
+  bool IsMozEditorBogusNode(nsIContent *aNode);
 
   /** counts number of editable child nodes */
   nsresult CountEditableChildren(nsIDOMNode *aNode, PRUint32 &outCount);
   
   /** Find the deep first and last children. Returned nodes are AddReffed */
   nsresult GetFirstEditableNode(nsIDOMNode *aRoot, nsCOMPtr<nsIDOMNode> *outFirstNode);
 #ifdef XXX_DEAD_CODE
   nsresult GetLastEditableNode(nsIDOMNode *aRoot, nsCOMPtr<nsIDOMNode> *outLastNode);
@@ -575,16 +591,17 @@ public:
   void     SetIsIMEComposing(); /* call this before |IsIMEComposing()| */
 
   /** from html rules code - migration in progress */
   static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
   static nsIAtom *GetTag(nsIDOMNode *aNode);
   virtual bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
   static bool IsTextOrElementNode(nsIDOMNode *aNode);
   static bool IsTextNode(nsIDOMNode *aNode);
+  static bool IsTextNode(nsINode *aNode);
   
   static PRInt32 GetIndexOf(nsIDOMNode *aParent, nsIDOMNode *aChild);
   static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, PRInt32 aOffset);
   static nsCOMPtr<nsIDOMNode> GetNodeAtRangeOffsetPoint(nsIDOMNode* aParentOrNode, PRInt32 aOffset);
 
   static nsresult GetStartNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outStartNode, PRInt32 *outStartOffset);
   static nsresult GetEndNodeAndOffset(nsISelection *aSelection, nsIDOMNode **outEndNode, PRInt32 *outEndOffset);
 #if DEBUG_JOE
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -908,16 +908,25 @@ nsHTMLEditor::NodeIsBlock(nsIDOMNode *aN
 bool
 nsHTMLEditor::IsBlockNode(nsIDOMNode *aNode)
 {
   bool isBlock;
   NodeIsBlockStatic(aNode, &isBlock);
   return isBlock;
 }
 
+bool
+nsHTMLEditor::IsBlockNode(nsINode *aNode)
+{
+  bool isBlock;
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
+  NodeIsBlockStatic(node, &isBlock);
+  return isBlock;
+}
+
 // Non-static version for the nsIEditor interface and JavaScript
 NS_IMETHODIMP 
 nsHTMLEditor::SetDocumentTitle(const nsAString &aTitle)
 {
   nsRefPtr<SetDocTitleTxn> txn = new SetDocTitleTxn();
   NS_ENSURE_TRUE(txn, NS_ERROR_OUT_OF_MEMORY);
 
   nsresult result = txn->Init(this, &aTitle);
@@ -3898,19 +3907,24 @@ nsHTMLEditor::FindUserSelectAllNode(nsID
   } 
 
   return resultNode.forget();
 }
 
 NS_IMETHODIMP_(bool)
 nsHTMLEditor::IsModifiableNode(nsIDOMNode *aNode)
 {
-  nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
-
-  return !content || content->IsEditable();
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  return IsModifiableNode(node);
+}
+
+bool
+nsHTMLEditor::IsModifiableNode(nsINode *aNode)
+{
+  return !aNode || aNode->IsEditable();
 }
 
 static nsresult SetSelectionAroundHeadChildren(nsCOMPtr<nsISelection> aSelection, nsWeakPtr aDocWeak)
 {
   nsresult res = NS_OK;
   // Set selection around <head> node
   nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(aDocWeak);
   NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
@@ -4687,41 +4701,51 @@ nsHTMLEditor::GetNextHTMLSibling(nsIDOMN
 ///////////////////////////////////////////////////////////////////////////
 // GetPriorHTMLNode: returns the previous editable leaf node, if there is
 //                   one within the <body>
 //
 nsresult
 nsHTMLEditor::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
-  nsresult res = GetPriorNode(inNode, true, address_of(*outNode), bNoBlockCrossing);
+
+  nsIContent* activeEditingHost = GetActiveEditingHost();
+  if (!activeEditingHost) {
+    *outNode = nsnull;
+    return NS_OK;
+  }
+
+  nsresult res = GetPriorNode(inNode, true, address_of(*outNode), bNoBlockCrossing, activeEditingHost);
   NS_ENSURE_SUCCESS(res, res);
   
-  // if it's not in the body, then zero it out
-  if (*outNode && !IsNodeInActiveEditor(*outNode)) {
-    *outNode = nsnull;
-  }
+  NS_ASSERTION(!*outNode || IsNodeInActiveEditor(*outNode),
+               "GetPriorNode screwed up");
   return res;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // GetPriorHTMLNode: same as above but takes {parent,offset} instead of node
 //                       
 nsresult
 nsHTMLEditor::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
-  nsresult res = GetPriorNode(inParent, inOffset, true, address_of(*outNode), bNoBlockCrossing);
+
+  nsIContent* activeEditingHost = GetActiveEditingHost();
+  if (!activeEditingHost) {
+    *outNode = nsnull;
+    return NS_OK;
+  }
+
+  nsresult res = GetPriorNode(inParent, inOffset, true, address_of(*outNode), bNoBlockCrossing, activeEditingHost);
   NS_ENSURE_SUCCESS(res, res);
   
-  // if it's not in the body, then zero it out
-  if (*outNode && !IsNodeInActiveEditor(*outNode)) {
-    *outNode = nsnull;
-  }
+  NS_ASSERTION(!*outNode || IsNodeInActiveEditor(*outNode),
+               "GetPriorNode screwed up");
   return res;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // GetNextHTMLNode: returns the next editable leaf node, if there is
 //                   one within the <body>
 //                       
@@ -4919,37 +4943,38 @@ nsHTMLEditor::GetLastEditableLeaf(nsIDOM
     }
   }
   
   *aOutLastLeaf = child;
   return res;
 }
 
 bool
-nsHTMLEditor::IsTextInDirtyFrameVisible(nsIDOMNode *aNode)
+nsHTMLEditor::IsTextInDirtyFrameVisible(nsIContent *aNode)
 {
   bool isEmptyTextNode;
-  nsresult res = IsVisTextNode(aNode, &isEmptyTextNode, false);
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
+  nsresult res = IsVisTextNode(node, &isEmptyTextNode, false);
   if (NS_FAILED(res))
   {
     // We are following the historical decision:
     //   if we don't know, we say it's visible...
 
     return true;
   }
 
   return !isEmptyTextNode;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsVisTextNode: figure out if textnode aTextNode has any visible content.
 //                  
 nsresult
-nsHTMLEditor::IsVisTextNode( nsIDOMNode *aNode, 
+nsHTMLEditor::IsVisTextNode( nsIDOMNode* aNode, 
                              bool *outIsEmptyNode, 
                              bool aSafeToAskFrames)
 {
   NS_ENSURE_TRUE(aNode && outIsEmptyNode, NS_ERROR_NULL_POINTER);
   *outIsEmptyNode = true;
   nsresult res = NS_OK;
 
   nsCOMPtr<nsIContent> textContent = do_QueryInterface(aNode);
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -379,16 +379,17 @@ public:
   NS_IMETHODIMP DeleteText(nsIDOMCharacterData *aTextNode,
                            PRUint32             aOffset,
                            PRUint32             aLength);
   NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert, 
                             nsCOMPtr<nsIDOMNode> *aInOutNode, 
                             PRInt32 *aInOutOffset,
                             nsIDOMDocument *aDoc);
   NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode *aNode);
+  virtual bool IsModifiableNode(nsINode *aNode);
 
   NS_IMETHOD SelectAll();
 
   NS_IMETHOD GetRootElement(nsIDOMElement **aRootElement);
 
   /* ------------ nsICSSLoaderObserver -------------- */
   NS_IMETHOD StyleSheetLoaded(nsCSSStyleSheet*aSheet, bool aWasAlternate,
                               nsresult aStatus);
@@ -412,17 +413,17 @@ public:
   // Use this to assure that selection is set after attribute nodes when 
   //  trying to collapse selection at begining of a block node
   //  e.g., when setting at beginning of a table cell
   // This will stop at a table, however, since we don't want to
   //  "drill down" into nested tables.
   // aSelection is optional -- if null, we get current seletion
   nsresult CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode);
 
-  virtual bool IsTextInDirtyFrameVisible(nsIDOMNode *aNode);
+  virtual bool IsTextInDirtyFrameVisible(nsIContent *aNode);
 
   nsresult IsVisTextNode( nsIDOMNode *aNode, 
                           bool *outIsEmptyNode, 
                           bool aSafeToAskFrames);
   nsresult IsEmptyNode(nsIDOMNode *aNode, bool *outIsEmptyBlock, 
                        bool aMozBRDoesntCount = false,
                        bool aListOrCellNotEmpty = false,
                        bool aSafeToAskFrames = false);
@@ -542,16 +543,17 @@ protected:
   //  failed to set selection to some other content in the document
   NS_IMETHOD SetSelectionAtDocumentStart(nsISelection *aSelection);
 
 // End of Table Editing utilities
   
   NS_IMETHOD IsRootTag(nsString &aTag, bool &aIsTag);
 
   virtual bool IsBlockNode(nsIDOMNode *aNode);
+  virtual bool IsBlockNode(nsINode *aNode);
   
   static nsCOMPtr<nsIDOMNode> GetEnclosingTable(nsIDOMNode *aNode);
 
   /** content-based query returns true if <aProperty aAttribute=aValue> effects aNode
     * If <aProperty aAttribute=aValue> contains aNode, 
     * but <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
     * more deeply nested than the first, then the first does not effect aNode.
     *
--- a/js/jetpack/JetpackChild.cpp
+++ b/js/jetpack/JetpackChild.cpp
@@ -125,18 +125,17 @@ JetpackChild::Init(base::ProcessHandle a
 
   if (!(mRuntime = JS_NewRuntime(32L * 1024L * 1024L)) ||
       !(mCx = JS_NewContext(mRuntime, 8192)))
     return false;
 
   JS_SetVersion(mCx, JSVERSION_LATEST);
   JS_SetOptions(mCx, JS_GetOptions(mCx) |
                 JSOPTION_DONT_REPORT_UNCAUGHT |
-                JSOPTION_ATLINE |
-                JSOPTION_JIT);
+                JSOPTION_ATLINE);
   JS_SetErrorReporter(mCx, ReportError);
 
   {
     JSAutoRequest request(mCx);
     JS_SetContextPrivate(mCx, this);
     JSObject* implGlobal =
       JS_NewCompartmentAndGlobalObject(mCx, const_cast<JSClass*>(&sGlobalClass), NULL);
     if (!implGlobal)
--- a/js/src/aclocal.m4
+++ b/js/src/aclocal.m4
@@ -4,14 +4,15 @@ dnl The contents of this file are under 
 dnl 
 
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/moznbytetype.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
+builtin(include, build/autoconf/mozcommonheader.m4)dnl
 builtin(include, build/autoconf/acwinpaths.m4)dnl
 builtin(include, build/autoconf/lto.m4)dnl
 builtin(include, build/autoconf/gcc-pr49911.m4)dnl
 builtin(include, build/autoconf/frameptr.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
new file mode 100644
--- /dev/null
+++ b/js/src/build/autoconf/mozcommonheader.m4
@@ -0,0 +1,41 @@
+dnl ***** BEGIN LICENSE BLOCK *****
+dnl Version: MPL 1.1/GPL 2.0/LGPL 2.1
+dnl
+dnl The contents of this file are subject to the Mozilla Public License Version
+dnl 1.1 (the "License"); you may not use this file except in compliance with
+dnl the License. You may obtain a copy of the License at
+dnl http://www.mozilla.org/MPL/
+dnl
+dnl Software distributed under the License is distributed on an "AS IS" basis,
+dnl WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+dnl for the specific language governing rights and limitations under the
+dnl License.
+dnl
+dnl The Original Code is mozilla.org code.
+dnl
+dnl The Initial Developer of the Original Code is the
+dnl Mozilla Foundation <http://www.mozilla.org>
+dnl
+dnl Portions created by the Initial Developer are Copyright (C) 2009
+dnl the Initial Developer. All Rights Reserved.
+dnl
+dnl
+dnl Alternatively, the contents of this file may be used under the terms of
+dnl either of the GNU General Public License Version 2 or later (the "GPL"),
+dnl or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+dnl in which case the provisions of the GPL or the LGPL are applicable instead
+dnl of those above. If you wish to allow use of your version of this file only
+dnl under the terms of either the GPL or the LGPL, and not to allow others to
+dnl use your version of this file under the terms of the MPL, indicate your
+dnl decision by deleting the provisions above and replace them with the notice
+dnl and other provisions required by the GPL or the LGPL. If you do not delete
+dnl the provisions above, a recipient may use your version of this file under
+dnl the terms of any one of the MPL, the GPL or the LGPL.
+dnl
+dnl ***** END LICENSE BLOCK *****
+
+AC_DEFUN(MOZ_CHECK_COMMON_HEADERS,
+	MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h sys/bitypes.h \
+        memory.h unistd.h gnu/libc-version.h nl_types.h malloc.h \
+        X11/XKBlib.h io.h cpuid.h)
+)
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -3243,22 +3243,17 @@ dnl Checks for header files.
 dnl ========================================================
 AC_HEADER_DIRENT
 case "$target_os" in
 freebsd*)
 # for stuff like -lXshm
     CPPFLAGS="${CPPFLAGS} ${X_CFLAGS}"
     ;;
 esac
-MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h)
-MOZ_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h)
-MOZ_CHECK_HEADERS(gnu/libc-version.h nl_types.h)
-MOZ_CHECK_HEADERS(malloc.h)
-MOZ_CHECK_HEADERS(X11/XKBlib.h)
-MOZ_CHECK_HEADERS(io.h)
+MOZ_CHECK_COMMON_HEADERS
 
 dnl These are all the places some variant of statfs can be hiding.
 MOZ_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h)
 
 dnl Quota support
 MOZ_CHECK_HEADERS(sys/quota.h)
 MOZ_CHECK_HEADERS(linux/quota.h)
 
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -424,24 +424,21 @@ frontend::CompileFunctionBody(JSContext 
                         break;
                     }
                 }
             }
         }
     }
 
     /*
-     * Farble the body so that it looks like a block statement to EmitTree,
-     * which is called from EmitFunctionBody (see BytecodeEmitter.cpp).
      * After we're done parsing, we must fold constants, analyze any nested
      * functions, and generate code for this function, including a stop opcode
      * at the end.
      */
-    tokenStream.mungeCurrentToken(TOK_LC);
-    ParseNode *pn = fn ? parser.functionBody() : NULL;
+    ParseNode *pn = fn ? parser.functionBody(Parser::StatementListBody) : NULL;
     if (pn) {
         if (!CheckStrictParameters(cx, &funbce)) {
             pn = NULL;
         } else if (!tokenStream.matchToken(TOK_EOF)) {
             parser.reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_SYNTAX_ERROR);
             pn = NULL;
         } else if (!FoldConstants(cx, pn, &funbce)) {
             /* FoldConstants reported the error already. */
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1449,17 +1449,18 @@ static ptrdiff_t
 EmitTraceOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
 {
     if (nextpn) {
         /*
          * Try to give the JSOP_TRACE the same line number as the next
          * instruction. nextpn is often a block, in which case the next
          * instruction typically comes from the first statement inside.
          */
-        if (nextpn->isKind(PNK_LC) && nextpn->isArity(PN_LIST) && nextpn->pn_head)
+        JS_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
+        if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
             nextpn = nextpn->pn_head;
         if (!UpdateLineNumberNotes(cx, bce, nextpn->pn_pos.begin.lineno))
             return -1;
     }
 
     uint32 index = bce->traceIndex;
     if (index < UINT16_MAX)
         bce->traceIndex++;
@@ -3340,17 +3341,17 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
     if (!EmitTree(cx, bce, pn->pn_left))
         return JS_FALSE;
 
     /* Switch bytecodes run from here till end of final case. */
     top = bce->offset();
 #if !JS_HAS_BLOCK_SCOPE
     PushStatement(bce, &stmtInfo, STMT_SWITCH, top);
 #else
-    if (pn2->isKind(PNK_LC)) {
+    if (pn2->isKind(PNK_STATEMENTLIST)) {
         PushStatement(bce, &stmtInfo, STMT_SWITCH, top);
     } else {
         /* Re-push the switch's statement info record. */
         if (!tps.repushBlock(cx, bce))
             return JS_FALSE;
 
         /*
          * Set the statement info record's idea of top. Reset top too, since
@@ -4267,18 +4268,18 @@ EmitVariables(JSContext *cx, BytecodeEmi
         next = pn2->pn_next;
 
         if (!pn2->isKind(PNK_NAME)) {
 #if JS_HAS_DESTRUCTURING
             if (pn2->isKind(PNK_RB) || pn2->isKind(PNK_RC)) {
                 /*
                  * Emit variable binding ops, but not destructuring ops.  The
                  * parser (see Parser::variables) has ensured that our caller
-                 * will be the PNK_FOR/PNK_IN case in EmitTree, and that case
-                 * will emit the destructuring code only after emitting an
+                 * will be the PNK_FOR/PNK_FORIN case in EmitTree, and that
+                 * case will emit the destructuring code only after emitting an
                  * enumerating opcode and a branch that tests whether the
                  * enumeration ended.
                  */
                 JS_ASSERT(forInVar);
                 JS_ASSERT(pn->pn_count == 1);
                 if (!EmitDestructuringDecls(cx, bce, pn->getOp(), pn2))
                     return JS_FALSE;
                 break;
@@ -5314,30 +5315,30 @@ EmitXMLTag(JSContext *cx, BytecodeEmitte
                           : cx->runtime->atomState.stagoAtom;
         if (!bce->makeAtomIndex(tagAtom, &index))
             return false;
         EMIT_INDEX_OP(JSOP_STRING, index);
     }
 
     JS_ASSERT(pn->pn_count != 0);
     ParseNode *pn2 = pn->pn_head;
-    if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
+    if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
         return false;
     if (!EmitTree(cx, bce, pn2))
         return false;
     if (Emit1(cx, bce, JSOP_ADD) < 0)
         return false;
 
     uint32 i;
     for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) {
-        if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
+        if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
             return false;
         if (!EmitTree(cx, bce, pn2))
             return false;
-        if ((i & 1) && pn2->isKind(PNK_LC)) {
+        if ((i & 1) && pn2->isKind(PNK_XMLCURLYEXPR)) {
             if (Emit1(cx, bce, JSOP_TOATTRVAL) < 0)
                 return false;
         }
         if (Emit1(cx, bce, (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0)
             return false;
     }
 
     {
@@ -5608,17 +5609,17 @@ EmitNormalFor(JSContext *cx, BytecodeEmi
             JS_ASSERT(pn3->isOp(JSOP_NOP));
             if (!MaybeEmitGroupAssignment(cx, bce, op, pn3, &op))
                 return false;
         }
 #endif
         if (op == JSOP_POP) {
             if (!EmitTree(cx, bce, pn3))
                 return false;
-            if (pn3->isKind(PNK_VAR) || pn3->isKind(PNK_LET)) {
+            if (pn3->isKind(PNK_VAR) || pn3->isKind(PNK_CONST) || pn3->isKind(PNK_LET)) {
                 /*
                  * Check whether a destructuring-initialized var decl
                  * was optimized to a group assignment.  If so, we do
                  * not need to emit a pop below, so switch to a nop,
                  * just for the decompiler.
                  */
                 JS_ASSERT(pn3->isArity(PN_LIST));
                 if (pn3->pn_xflags & PNX_GROUPINIT)
@@ -5730,17 +5731,18 @@ EmitNormalFor(JSContext *cx, BytecodeEmi
 
     /* Now fixup all breaks and continues. */
     return PopStatementBCE(cx, bce);
 }
 
 static inline bool
 EmitFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
 {
-    return pn->pn_left->isKind(PNK_IN)
+    JS_ASSERT(pn->pn_left->isKind(PNK_FORIN) || pn->pn_left->isKind(PNK_FORHEAD));
+    return pn->pn_left->isKind(PNK_FORIN)
            ? EmitForIn(cx, bce, pn, top)
            : EmitNormalFor(cx, bce, pn, top);
 }
 
 JSBool
 frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
     JSBool useful, wantval;
@@ -5782,17 +5784,17 @@ frontend::EmitTree(JSContext *cx, Byteco
 #endif
 
         fun = pn->pn_funbox->function();
         JS_ASSERT(fun->isInterpreted());
         if (fun->script()) {
             /*
              * This second pass is needed to emit JSOP_NOP with a source note
              * for the already-emitted function definition prolog opcode. See
-             * comments in the PNK_LC case.
+             * comments in the PNK_STATEMENTLIST case.
              */
             JS_ASSERT(pn->isOp(JSOP_NOP));
             JS_ASSERT(bce->inFunction());
             if (!EmitFunctionDefNop(cx, bce, pn->pn_index))
                 return JS_FALSE;
             break;
         }
 
@@ -5993,17 +5995,17 @@ frontend::EmitTree(JSContext *cx, Byteco
          */
         if (!SetSrcNoteOffset(cx, bce, noteIndex2, 0, beq - top))
             return JS_FALSE;
         if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, beq - jmp))
             return JS_FALSE;
         ok = PopStatementBCE(cx, bce);
         break;
 
-      case PNK_DO:
+      case PNK_DOWHILE:
         /* Emit an annotated nop so we know to decompile a 'do' keyword. */
         noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
         if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
             return JS_FALSE;
 
         noteIndex2 = NewSrcNote(cx, bce, SRC_TRACE);
         if (noteIndex2 < 0)
             return JS_FALSE;
@@ -6113,16 +6115,17 @@ frontend::EmitTree(JSContext *cx, Byteco
         break;
 
       case PNK_CATCH:
         if (!EmitCatch(cx, bce, pn))
             return false;
         break;
 
       case PNK_VAR:
+      case PNK_CONST:
         if (!EmitVariables(cx, bce, pn, JS_FALSE, &noteIndex))
             return JS_FALSE;
         break;
 
       case PNK_RETURN:
         /* Push a return value */
         pn2 = pn->pn_kid;
         if (pn2) {
@@ -6170,28 +6173,28 @@ frontend::EmitTree(JSContext *cx, Byteco
         }
         if (pn->pn_hidden && NewSrcNote(cx, bce, SRC_HIDDEN) < 0)
             return JS_FALSE;
         if (Emit1(cx, bce, JSOP_YIELD) < 0)
             return JS_FALSE;
         break;
 #endif
 
-      case PNK_LC:
+#if JS_HAS_XML_SUPPORT
+      case PNK_XMLCURLYEXPR:
+        JS_ASSERT(pn->isArity(PN_UNARY));
+        if (!EmitTree(cx, bce, pn->pn_kid))
+            return JS_FALSE;
+        if (Emit1(cx, bce, pn->getOp()) < 0)
+            return JS_FALSE;
+        break;
+#endif
+
+      case PNK_STATEMENTLIST:
       {
-#if JS_HAS_XML_SUPPORT
-        if (pn->isArity(PN_UNARY)) {
-            if (!EmitTree(cx, bce, pn->pn_kid))
-                return JS_FALSE;
-            if (Emit1(cx, bce, pn->getOp()) < 0)
-                return JS_FALSE;
-            break;
-        }
-#endif
-
         JS_ASSERT(pn->isArity(PN_LIST));
 
         noteIndex = -1;
         tmp = bce->offset();
         if (pn->pn_xflags & PNX_NEEDBRACES) {
             noteIndex = NewSrcNote2(cx, bce, SRC_BRACE, 0);
             if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
                 return JS_FALSE;
@@ -6214,17 +6217,17 @@ frontend::EmitTree(JSContext *cx, Byteco
              */
             JS_ASSERT(bce->inFunction());
             if (pn->pn_xflags & PNX_DESTRUCT) {
                 /*
                  * Assign the destructuring arguments before defining any
                  * functions, see bug 419662.
                  */
                 JS_ASSERT(pnchild->isKind(PNK_SEMI));
-                JS_ASSERT(pnchild->pn_kid->isKind(PNK_VAR));
+                JS_ASSERT(pnchild->pn_kid->isKind(PNK_VAR) || pnchild->pn_kid->isKind(PNK_CONST));
                 if (!EmitTree(cx, bce, pnchild))
                     return JS_FALSE;
                 pnchild = pnchild->pn_next;
             }
 
             for (pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
                 if (pn2->isKind(PNK_FUNCTION)) {
                     if (pn2->isOp(JSOP_NOP)) {
@@ -6349,19 +6352,19 @@ frontend::EmitTree(JSContext *cx, Byteco
          */
         atom = pn->pn_atom;
 
         jsatomid index;
         if (!bce->makeAtomIndex(atom, &index))
             return JS_FALSE;
 
         pn2 = pn->expr();
-        noteType = (pn2->isKind(PNK_LC) ||
+        noteType = (pn2->isKind(PNK_STATEMENTLIST) ||
                     (pn2->isKind(PNK_LEXICALSCOPE) &&
-                     pn2->expr()->isKind(PNK_LC)))
+                     pn2->expr()->isKind(PNK_STATEMENTLIST)))
                    ? SRC_LABELBRACE
                    : SRC_LABEL;
         noteIndex = NewSrcNote2(cx, bce, noteType, ptrdiff_t(index));
         if (noteIndex < 0)
             return JS_FALSE;
 
         top = EmitJump(cx, bce, JSOP_LABEL, 0);
         if (top < 0)
@@ -6531,20 +6534,18 @@ frontend::EmitTree(JSContext *cx, Byteco
                 tmp = GetJumpOffset(bce, pc);
                 CHECK_AND_SET_JUMP_OFFSET(cx, bce, pc, off - top);
                 *pc = pn->getOp();
                 top += tmp;
             } while ((pn2 = pn2->pn_next)->pn_next);
         }
         break;
 
-      case PNK_PLUS:
-      case PNK_MINUS:
-        if (pn->isArity(PN_UNARY))
-            goto unary_plusminus;
+      case PNK_ADD:
+      case PNK_SUB:
       case PNK_BITOR:
       case PNK_BITXOR:
       case PNK_BITAND:
       case PNK_STRICTEQ:
       case PNK_EQ:
       case PNK_STRICTNE:
       case PNK_NE:
       case PNK_LT:
@@ -6624,25 +6625,26 @@ frontend::EmitTree(JSContext *cx, Byteco
                 return false;
         }
         break;
 #endif
 
       case PNK_THROW:
 #if JS_HAS_XML_SUPPORT
       case PNK_AT:
-      case PNK_DEFAULT:
+      case PNK_DEFXMLNS:
         JS_ASSERT(pn->isArity(PN_UNARY));
         /* FALL THROUGH */
 #endif
       case PNK_TYPEOF:
       case PNK_VOID:
       case PNK_NOT:
       case PNK_BITNOT:
-      unary_plusminus:
+      case PNK_POS:
+      case PNK_NEG:
       {
         /* Unary op, including unary +/-. */
         op = pn->getOp();
         pn2 = pn->pn_kid;
 
         JS_ASSERT(op != JSOP_XMLNAME);
         if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME))
             op = JSOP_TYPEOFEXPR;
@@ -7286,17 +7288,17 @@ frontend::EmitTree(JSContext *cx, Byteco
           case PNK_XMLSTAGO:
             break;
           default:
             if (Emit1(cx, bce, JSOP_STARTXML) < 0)
                 return JS_FALSE;
         }
 
         for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
-            if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
+            if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
                 return JS_FALSE;
             if (!EmitTree(cx, bce, pn2))
                 return JS_FALSE;
             if (pn2 != pn->pn_head && Emit1(cx, bce, JSOP_ADD) < 0)
                 return JS_FALSE;
         }
 
         if (pn->pn_xflags & PNX_XMLROOT) {
@@ -7325,17 +7327,17 @@ frontend::EmitTree(JSContext *cx, Byteco
         break;
 
       case PNK_XMLNAME:
         JS_ASSERT(!bce->inStrictMode());
 
         if (pn->isArity(PN_LIST)) {
             JS_ASSERT(pn->pn_count != 0);
             for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
-                if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
+                if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
                     return JS_FALSE;
                 if (!EmitTree(cx, bce, pn2))
                     return JS_FALSE;
                 if (pn2 != pn->pn_head && Emit1(cx, bce, JSOP_ADD) < 0)
                     return JS_FALSE;
             }
         } else {
             JS_ASSERT(pn->isArity(PN_NULLARY));
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -47,53 +47,53 @@
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
 using namespace js;
 
 static ParseNode *
-ContainsStmt(ParseNode *pn, ParseNodeKind kind)
+ContainsVarOrConst(ParseNode *pn)
 {
     if (!pn)
         return NULL;
-    if (pn->isKind(kind))
+    if (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST))
         return pn;
     switch (pn->getArity()) {
       case PN_LIST:
         for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
-            if (ParseNode *pnt = ContainsStmt(pn2, kind))
+            if (ParseNode *pnt = ContainsVarOrConst(pn2))
                 return pnt;
         }
         break;
       case PN_TERNARY:
-        if (ParseNode *pnt = ContainsStmt(pn->pn_kid1, kind))
+        if (ParseNode *pnt = ContainsVarOrConst(pn->pn_kid1))
             return pnt;
-        if (ParseNode *pnt = ContainsStmt(pn->pn_kid2, kind))
+        if (ParseNode *pnt = ContainsVarOrConst(pn->pn_kid2))
             return pnt;
-        return ContainsStmt(pn->pn_kid3, kind);
+        return ContainsVarOrConst(pn->pn_kid3);
       case PN_BINARY:
         /*
          * Limit recursion if pn is a binary expression, which can't contain a
          * var statement.
          */
         if (!pn->isOp(JSOP_NOP))
             return NULL;
-        if (ParseNode *pnt = ContainsStmt(pn->pn_left, kind))
+        if (ParseNode *pnt = ContainsVarOrConst(pn->pn_left))
             return pnt;
-        return ContainsStmt(pn->pn_right, kind);
+        return ContainsVarOrConst(pn->pn_right);
       case PN_UNARY:
         if (!pn->isOp(JSOP_NOP))
             return NULL;
-        return ContainsStmt(pn->pn_kid, kind);
+        return ContainsVarOrConst(pn->pn_kid);
       case PN_NAME:
-        return ContainsStmt(pn->maybeExpr(), kind);
+        return ContainsVarOrConst(pn->maybeExpr());
       case PN_NAMESET:
-        return ContainsStmt(pn->pn_tree, kind);
+        return ContainsVarOrConst(pn->pn_tree);
       default:;
     }
     return NULL;
 }
 
 /*
  * Fold from one constant type to another.
  * XXX handles only strings and numbers for now
@@ -496,17 +496,17 @@ js::FoldConstants(JSContext *cx, ParseNo
             if (!FoldConstants(cx, pn2, tc, inCond))
                 return false;
             break;
         }
 
         /* First kid may be null (for default case in switch). */
         if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(PNK_WHILE)))
             return false;
-        if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_DO)))
+        if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_DOWHILE)))
             return false;
         break;
 
       case PN_UNARY:
         pn1 = pn->pn_kid;
 
         /*
          * Kludge to deal with typeof expressions: because constant folding
@@ -547,17 +547,17 @@ js::FoldConstants(JSContext *cx, ParseNo
         break;
 
       case PN_NULLARY:
         break;
     }
 
     switch (pn->getKind()) {
       case PNK_IF:
-        if (ContainsStmt(pn2, PNK_VAR) || ContainsStmt(pn3, PNK_VAR))
+        if (ContainsVarOrConst(pn2) || ContainsVarOrConst(pn3))
             break;
         /* FALL THROUGH */
 
       case PNK_HOOK:
         /* Reduce 'if (C) T; else E' into T for true C, E for false. */
         switch (pn1->getKind()) {
           case PNK_NUMBER:
             if (pn1->pn_dval == 0 || JSDOUBLE_IS_NaN(pn1->pn_dval))
@@ -589,17 +589,17 @@ js::FoldConstants(JSContext *cx, ParseNo
         if (!pn2 || (pn->isKind(PNK_SEMI) && !pn->pn_kid)) {
             /*
              * False condition and no else, or an empty then-statement was
              * moved up over pn.  Either way, make pn an empty block (not an
              * empty statement, which does not decompile, even when labeled).
              * NB: pn must be a PNK_IF as PNK_HOOK can never have a null kid
              * or an empty statement for a child.
              */
-            pn->setKind(PNK_LC);
+            pn->setKind(PNK_STATEMENTLIST);
             pn->setArity(PN_LIST);
             pn->makeEmpty();
         }
         tc->freeTree(pn2);
         if (pn3 && pn3 != pn2)
             tc->freeTree(pn3);
         break;
 
@@ -678,19 +678,17 @@ js::FoldConstants(JSContext *cx, ParseNo
          * compiled from that same string.  += is special and so must be
          * handled below.
          */
         goto do_binary_op;
 
       case PNK_ADDASSIGN:
         JS_ASSERT(pn->isOp(JSOP_ADD));
         /* FALL THROUGH */
-      case PNK_PLUS:
-        if (pn->isArity(PN_UNARY))
-            goto unary_plusminus;
+      case PNK_ADD:
         if (pn->isArity(PN_LIST)) {
             /*
              * Any string literal term with all others number or string means
              * this is a concatenation.  If any term is not a string or number
              * literal, we can't fold.
              */
             JS_ASSERT(pn->pn_count > 2);
             if (pn->pn_xflags & PNX_CANTFOLD)
@@ -762,20 +760,17 @@ js::FoldConstants(JSContext *cx, ParseNo
             tc->freeTree(pn1);
             tc->freeTree(pn2);
             break;
         }
 
         /* Can't concatenate string literals, let's try numbers. */
         goto do_binary_op;
 
-      case PNK_MINUS:
-        if (pn->isArity(PN_UNARY))
-            goto unary_plusminus;
-        /* FALL THROUGH */
+      case PNK_SUB:
       case PNK_STAR:
       case PNK_LSH:
       case PNK_RSH:
       case PNK_URSH:
       case PNK_DIV:
       case PNK_MOD:
       do_binary_op:
         if (pn->isArity(PN_LIST)) {
@@ -814,17 +809,18 @@ js::FoldConstants(JSContext *cx, ParseNo
             }
         }
         break;
 
       case PNK_TYPEOF:
       case PNK_VOID:
       case PNK_NOT:
       case PNK_BITNOT:
-      unary_plusminus:
+      case PNK_POS:
+      case PNK_NEG:
         if (pn1->isKind(PNK_NUMBER)) {
             jsdouble d;
 
             /* Operate on one numeric constant. */
             d = pn1->pn_dval;
             switch (pn->getOp()) {
               case JSOP_BITNOT:
                 d = ~js_DoubleToECMAInt32(d);
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -400,30 +400,30 @@ ParseNode::append(ParseNodeKind kind, JS
     JS_ASSERT(left->isKind(kind) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC));
 
     if (left->pn_arity != PN_LIST) {
         ParseNode *pn1 = left->pn_left, *pn2 = left->pn_right;
         left->setArity(PN_LIST);
         left->pn_parens = false;
         left->initList(pn1);
         left->append(pn2);
-        if (kind == PNK_PLUS) {
+        if (kind == PNK_ADD) {
             if (pn1->isKind(PNK_STRING))
                 left->pn_xflags |= PNX_STRCAT;
             else if (!pn1->isKind(PNK_NUMBER))
                 left->pn_xflags |= PNX_CANTFOLD;
             if (pn2->isKind(PNK_STRING))
                 left->pn_xflags |= PNX_STRCAT;
             else if (!pn2->isKind(PNK_NUMBER))
                 left->pn_xflags |= PNX_CANTFOLD;
         }
     }
     left->append(right);
     left->pn_pos.end = right->pn_pos.end;
-    if (kind == PNK_PLUS) {
+    if (kind == PNK_ADD) {
         if (right->isKind(PNK_STRING))
             left->pn_xflags |= PNX_STRCAT;
         else if (!right->isKind(PNK_NUMBER))
             left->pn_xflags |= PNX_CANTFOLD;
     }
 
     return left;
 }
@@ -432,29 +432,29 @@ ParseNode *
 ParseNode::newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
                              TreeContext *tc)
 {
     if (!left || !right)
         return NULL;
 
     /*
      * Flatten a left-associative (left-heavy) tree of a given operator into
-     * a list, to reduce js_FoldConstants and js_EmitTree recursion.
+     * a list to reduce js::FoldConstants and js::frontend::EmitTree recursion.
      */
     if (left->isKind(kind) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC))
         return append(kind, op, left, right);
 
     /*
      * Fold constant addition immediately, to conserve node space and, what's
-     * more, so js_FoldConstants never sees mixed addition and concatenation
+     * more, so js::FoldConstants never sees mixed addition and concatenation
      * operations with more than one leading non-string operand in a PN_LIST
      * generated for expressions such as 1 + 2 + "pt" (which should evaluate
      * to "3pt", not "12pt").
      */
-    if (kind == PNK_PLUS &&
+    if (kind == PNK_ADD &&
         left->isKind(PNK_NUMBER) &&
         right->isKind(PNK_NUMBER) &&
         tc->parser->foldConstants)
     {
         left->pn_dval += right->pn_dval;
         left->pn_pos.end = right->pn_pos.end;
         tc->freeTree(right);
         return left;
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -63,27 +63,30 @@ enum ParseNodeKind {
     PNK_COMMA,
     PNK_HOOK,
     PNK_COLON,
     PNK_OR,
     PNK_AND,
     PNK_BITOR,
     PNK_BITXOR,
     PNK_BITAND,
-    PNK_PLUS,
-    PNK_MINUS,
+    PNK_POS,
+    PNK_NEG,
+    PNK_ADD,
+    PNK_SUB,
     PNK_STAR,
     PNK_DIV,
     PNK_MOD,
     PNK_INC,
     PNK_DEC,
     PNK_DOT,
     PNK_LB,
     PNK_RB,
-    PNK_LC,
+    PNK_STATEMENTLIST,
+    PNK_XMLCURLYEXPR,
     PNK_RC,
     PNK_LP,
     PNK_RP,
     PNK_NAME,
     PNK_NUMBER,
     PNK_STRING,
     PNK_REGEXP,
     PNK_TRUE,
@@ -92,35 +95,37 @@ enum ParseNodeKind {
     PNK_THIS,
     PNK_FUNCTION,
     PNK_IF,
     PNK_ELSE,
     PNK_SWITCH,
     PNK_CASE,
     PNK_DEFAULT,
     PNK_WHILE,
-    PNK_DO,
+    PNK_DOWHILE,
     PNK_FOR,
     PNK_BREAK,
     PNK_CONTINUE,
     PNK_IN,
     PNK_VAR,
+    PNK_CONST,
     PNK_WITH,
     PNK_RETURN,
     PNK_NEW,
     PNK_DELETE,
     PNK_DEFSHARP,
     PNK_USESHARP,
     PNK_TRY,
     PNK_CATCH,
     PNK_CATCHLIST,
     PNK_FINALLY,
     PNK_THROW,
     PNK_INSTANCEOF,
     PNK_DEBUGGER,
+    PNK_DEFXMLNS,
     PNK_XMLSTAGO,
     PNK_XMLETAGO,
     PNK_XMLPTAGC,
     PNK_XMLTAGC,
     PNK_XMLNAME,
     PNK_XMLATTR,
     PNK_XMLSPACE,
     PNK_XMLTEXT,
@@ -136,16 +141,17 @@ enum ParseNodeKind {
     PNK_XMLELEM,
     PNK_XMLLIST,
     PNK_YIELD,
     PNK_ARRAYCOMP,
     PNK_ARRAYPUSH,
     PNK_LEXICALSCOPE,
     PNK_LET,
     PNK_SEQ,
+    PNK_FORIN,
     PNK_FORHEAD,
     PNK_ARGSBODY,
     PNK_UPVARS,
 
     /*
      * The following parse node kinds occupy contiguous ranges to enable easy
      * range-testing.
      */
@@ -196,83 +202,86 @@ enum ParseNodeKind {
  * Label        Variant     Members
  * -----        -------     -------
  * <Definitions>
  * PNK_FUNCTION name        pn_funbox: ptr to js::FunctionBox holding function
  *                            object containing arg and var properties.  We
  *                            create the function object at parse (not emit)
  *                            time to specialize arg and var bytecodes early.
  *                          pn_body: PNK_UPVARS if the function's source body
- *                                   depends on outer names, else PNK_ARGSBODY
- *                                   if formal parameters, else PNK_LC node for
- *                                   function body statements, else PNK_RETURN
- *                                   for expression closure, else PNK_SEQ for
- *                                   expression closure with destructured
- *                                   formal parameters
+ *                                     depends on outer names,
+ *                                   PNK_ARGSBODY if formal parameters,
+ *                                   PNK_STATEMENTLIST node for function body
+ *                                     statements,
+ *                                   PNK_RETURN for expression closure, or
+ *                                   PNK_SEQ for expression closure with
+ *                                     destructured formal parameters
  *                          pn_cookie: static level and var index for function
  *                          pn_dflags: PND_* definition/use flags (see below)
  *                          pn_blockid: block id number
- * PNK_ARGSBODY list        list of formal parameters followed by PNK_LC node
- *                            for function body statements as final element
+ * PNK_ARGSBODY list        list of formal parameters followed by
+ *                            PNK_STATEMENTLIST node for function body
+ *                            statements as final element
  *                          pn_count: 1 + number of formal parameters
  * PNK_UPVARS   nameset     pn_names: lexical dependencies (js::Definitions)
  *                            defined in enclosing scopes, or ultimately not
  *                            defined (free variables, either global property
  *                            references or reference errors).
- *                          pn_tree: PNK_ARGSBODY or PNK_LC node
+ *                          pn_tree: PNK_ARGSBODY or PNK_STATEMENTLIST node
  *
  * <Statements>
- * PNK_LC       list        pn_head: list of pn_count statements
+ * PNK_STATEMENTLIST list   pn_head: list of pn_count statements
  * PNK_IF       ternary     pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
  *                            In body of a comprehension or desugared generator
  *                            expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
- *                            or (if the push was optimized away) empty PNK_LC.
+ *                            or (if the push was optimized away) empty
+ *                            PNK_STATEMENTLIST.
  * PNK_SWITCH   binary      pn_left: discriminant
  *                          pn_right: list of PNK_CASE nodes, with at most one
  *                            PNK_DEFAULT node, or if there are let bindings
  *                            in the top level of the switch body's cases, a
  *                            PNK_LEXICALSCOPE node that contains the list of
  *                            PNK_CASE nodes.
  * PNK_CASE,    binary      pn_left: case expr
- *                          pn_right: PNK_LC node for this case's statements
+ *                          pn_right: PNK_STATEMENTLIST node for this case's
+ *                            statements
  * PNK_DEFAULT  binary      pn_left: null
- *                          pn_right: PNK_LC node for this default's statements
+ *                          pn_right: PNK_STATEMENTLIST node for this default's
+ *                            statements
  *                          pn_val: constant value if lookup or table switch
  * PNK_WHILE    binary      pn_left: cond, pn_right: body
- * PNK_DO       binary      pn_left: body, pn_right: cond
- * PNK_FOR      binary      pn_left: either
- *                            for/in loop: a ternary PNK_IN node with
- *                              pn_kid1:  PNK_VAR to left of 'in', or NULL
- *                                its pn_xflags may have PNX_POPVAR
- *                                and PNX_FORINVAR bits set
- *                              pn_kid2: PNK_NAME or destructuring expr
- *                                to left of 'in'; if pn_kid1, then this
- *                                is a clone of pn_kid1->pn_head
- *                              pn_kid3: object expr to right of 'in'
- *                            for(;;) loop: a ternary PNK_FORHEAD node with
- *                              pn_kid1:  init expr before first ';'
- *                              pn_kid2:  cond expr before second ';'
- *                              pn_kid3:  update expr after second ';'
- *                              any kid may be null
+ * PNK_DOWHILE  binary      pn_left: body, pn_right: cond
+ * PNK_FOR      binary      pn_left: either PNK_FORIN (for-in statement) or
+ *                            PNK_FORHEAD (for(;;) statement)
  *                          pn_right: body
+ * PNK_FORIN    ternary     pn_kid1:  PNK_VAR to left of 'in', or NULL
+ *                            its pn_xflags may have PNX_POPVAR
+ *                            and PNX_FORINVAR bits set
+ *                          pn_kid2: PNK_NAME or destructuring expr
+ *                            to left of 'in'; if pn_kid1, then this
+ *                            is a clone of pn_kid1->pn_head
+ *                          pn_kid3: object expr to right of 'in'
+ * PNK_FORHEAD  ternary     pn_kid1:  init expr before first ';' or NULL
+ *                          pn_kid2:  cond expr before second ';' or NULL
+ *                          pn_kid3:  update expr after second ';' or NULL
  * PNK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
  * PNK_TRY      ternary     pn_kid1: try block
  *                          pn_kid2: null or PNK_CATCHLIST list of
  *                          PNK_LEXICALSCOPE nodes, each with pn_expr pointing
  *                          to a PNK_CATCH node
  *                          pn_kid3: null or finally block
  * PNK_CATCH    ternary     pn_kid1: PNK_NAME, PNK_RB, or PNK_RC catch var node
  *                                   (PNK_RB or PNK_RC if destructuring)
  *                          pn_kid2: null or the catch guard expression
  *                          pn_kid3: catch block statements
  * PNK_BREAK    name        pn_atom: label or null
  * PNK_CONTINUE name        pn_atom: label or null
  * PNK_WITH     binary      pn_left: head expr, pn_right: body
- * PNK_VAR      list        pn_head: list of PNK_NAME or PNK_ASSIGN nodes
- *                                   each name node has either
+ * PNK_VAR,     list        pn_head: list of PNK_NAME or PNK_ASSIGN nodes
+ * PNK_CONST                         each name node has either
  *                                     pn_used: false
  *                                     pn_atom: variable name
  *                                     pn_expr: initializer or null
  *                                   or
  *                                     pn_used: true
  *                                     pn_atom: variable name
  *                                     pn_lexdef: def node
  *                                   each assignment node has
@@ -315,29 +324,30 @@ enum ParseNodeKind {
  * PNK_STRICTNE
  * PNK_LT,      binary      pn_left: left-assoc REL expr, pn_right: SH expr
  * PNK_LE,
  * PNK_GT,
  * PNK_GE
  * PNK_LSH,     binary      pn_left: left-assoc SH expr, pn_right: ADD expr
  * PNK_RSH,
  * PNK_URSH
- * PNK_PLUS,    binary      pn_left: left-assoc ADD expr, pn_right: MUL expr
- *                          pn_xflags: if a left-associated binary PNK_PLUS
+ * PNK_ADD      binary      pn_left: left-assoc ADD expr, pn_right: MUL expr
+ *                          pn_xflags: if a left-associated binary PNK_ADD
  *                            tree has been flattened into a list (see above
  *                            under <Expressions>), pn_xflags will contain
  *                            PNX_STRCAT if at least one list element is a
  *                            string literal (PNK_STRING); if such a list has
  *                            any non-string, non-number term, pn_xflags will
  *                            contain PNX_CANTFOLD.
- *                          pn_
- * PNK_MINUS                pn_op: JSOP_ADD, JSOP_SUB
+ * PNK_SUB      binary      pn_left: left-assoc SH expr, pn_right: ADD expr
  * PNK_STAR,    binary      pn_left: left-assoc MUL expr, pn_right: UNARY expr
  * PNK_DIV,                 pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
  * PNK_MOD
+ * PNK_POS,     unary       pn_kid: UNARY expr
+ * PNK_NEG
  * PNK_TYPEOF,  unary       pn_kid: UNARY expr
  * PNK_VOID,
  * PNK_NOT,
  * PNK_BITNOT
  * PNK_INC,     unary       pn_kid: MEMBER expr
  * PNK_DEC
  * PNK_NEW      list        pn_head: list of ctor, arg1, arg2, ... argN
  *                          pn_count: 1 + N (where N is number of args)
@@ -378,17 +388,17 @@ enum ParseNodeKind {
  * PNK_FALSE,
  * PNK_NULL,
  * PNK_THIS
  *
  * <E4X node descriptions>
  * PNK_XMLUNARY unary       pn_kid: PNK_AT, PNK_ANYNAME, or PNK_DBLCOLON node
  *                          pn_op: JSOP_XMLNAME, JSOP_BINDXMLNAME, or
  *                                 JSOP_SETXMLNAME
- * PNK_DEFAULT  name        pn_atom: default XML namespace string literal
+ * PNK_DEFXMLNS name        pn_kid: namespace expr
  * PNK_FILTER   binary      pn_left: container expr, pn_right: filter expr
  * PNK_DBLDOT   binary      pn_left: container expr, pn_right: selector expr
  * PNK_ANYNAME  nullary     pn_op: JSOP_ANYNAME
  *                          pn_atom: cx->runtime->atomState.starAtom
  * PNK_AT       unary       pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
  * PNK_DBLCOLON binary      pn_op: JSOP_QNAME
  *                          pn_left: PNK_ANYNAME or PNK_NAME node
  *                          pn_right: PNK_STRING "*" node, or expr within []
@@ -409,32 +419,32 @@ enum ParseNodeKind {
  * PNK_XMLNAME  nullary     pn_atom: XML name, with no {expr} embedded
  * PNK_XMLNAME  list        pn_head: tag name or {expr}, ... name or {expr}
  * PNK_XMLATTR, nullary     pn_atom: attribute value string; pn_op: JSOP_STRING
  * PNK_XMLCDATA,
  * PNK_XMLCOMMENT
  * PNK_XMLPI    nullary     pn_pitarget: XML processing instruction target
  *                          pn_pidata: XML PI data, or null if no data
  * PNK_XMLTEXT  nullary     pn_atom: marked-up text, or null if empty string
- * PNK_LC       unary       {expr} in XML tag or content; pn_kid is expr
+ * PNK_XMLCURLYEXPR unary   {expr} in XML tag or content; pn_kid is expr
  *
  * So an XML tag with no {expr} and three attributes is a list with the form:
  *
  *    (tagname attrname1 attrvalue1 attrname2 attrvalue2 attrname2 attrvalue3)
  *
  * An XML tag with embedded expressions like so:
  *
  *    <name1{expr1} name2{expr2}name3={expr3}>
  *
  * would have the form:
  *
  *    ((name1 {expr1}) (name2 {expr2} name3) {expr3})
  *
  * where () bracket a list with elements separated by spaces, and {expr} is a
- * PNK_LC unary node with expr as its kid.
+ * PNK_XMLCURLYEXPR unary node with expr as its kid.
  *
  * Thus, the attribute name/value pairs occupy successive odd and even list
  * locations, where pn_head is the PNK_XMLNAME node at list location 0.  The
  * parser builds the same sort of structures for elements:
  *
  *    <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a>
  *
  * translates to:
@@ -705,20 +715,21 @@ struct ParseNode {
                                            still valid, but this use no longer
                                            optimizable via an upvar opcode */
 #define PND_CLOSED      0x800           /* variable is closed over */
 
 /* Flags to propagate from uses to definition. */
 #define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED)
 
 /* PN_LIST pn_xflags bits. */
-#define PNX_STRCAT      0x01            /* PNK_PLUS list has string term */
-#define PNX_CANTFOLD    0x02            /* PNK_PLUS list has unfoldable term */
-#define PNX_POPVAR      0x04            /* PNK_VAR last result needs popping */
-#define PNX_FORINVAR    0x08            /* PNK_VAR is left kid of PNK_IN node,
+#define PNX_STRCAT      0x01            /* PNK_ADD list has string term */
+#define PNX_CANTFOLD    0x02            /* PNK_ADD list has unfoldable term */
+#define PNX_POPVAR      0x04            /* PNK_VAR or PNK_CONST last result
+                                           needs popping */
+#define PNX_FORINVAR    0x08            /* PNK_VAR is left kid of PNK_FORIN node
                                            which is left kid of PNK_FOR */
 #define PNX_ENDCOMMA    0x10            /* array literal has comma at end */
 #define PNX_XMLROOT     0x20            /* top-most node in XML literal tree */
 #define PNX_GROUPINIT   0x40            /* var [a, b] = [c, d]; unit list */
 #define PNX_NEEDBRACES  0x80            /* braces necessary due to closure */
 #define PNX_FUNCDEFS   0x100            /* contains top-level function statements */
 #define PNX_SETCALL    0x100            /* call expression in lvalue context */
 #define PNX_DESTRUCT   0x200            /* destructuring special cases:
@@ -980,18 +991,18 @@ struct LexicalScopeNode : public ParseNo
 
 ParseNode *
 CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
 
 /*
  * js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants
  * of js::ParseNode, allocated only for function, var, const, and let
  * declarations that define truly lexical bindings. This means that a child of
- * a PNK_VAR list may be a Definition instead of a ParseNode. The pn_defn
- * bit is set for all Definitions, clear otherwise.
+ * a PNK_VAR list may be a Definition as well as a ParseNode. The pn_defn bit
+ * is set for all Definitions, clear otherwise.
  *
  * In an upvars list, defn->resolve() is the outermost definition the
  * name may reference. If a with block or a function that calls eval encloses
  * the use, the name may end up referring to something else at runtime.
  *
  * Note that not all var declarations are definitions: JS allows multiple var
  * declarations in a function or script, but only the first creates the hoisted
  * binding. JS programmers do redeclare variables for good refactoring reasons,
@@ -1024,17 +1035,17 @@ CloneLeftHandSide(ParseNode *opn, TreeCo
  *               dn = lookup x in tc->lexdeps;
  *               if (dn)                                    // use before def
  *                   remove x from tc->lexdeps;
  *               else                                       // def before use
  *                   dn = allocate a PN_NAME Definition;
  *               map x to dn via tc->decls;
  *               pn = dn;
  *           }
- *           insert pn into its parent PNK_VAR list;
+ *           insert pn into its parent PNK_VAR/PNK_CONST list;
  *       } else {
  *           pn = allocate a ParseNode for this reference to x;
  *           dn = lookup x in tc's lexical scope chain;
  *           if (!dn) {
  *               dn = lookup x in tc->lexdeps;
  *               if (!dn) {
  *                   dn = pre-allocate a Definition for x;
  *                   map x to dn in tc->lexdeps;
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -256,17 +256,17 @@ Parser::trace(JSTracer *trc)
         tc->trace(trc);
 }
 
 static bool
 GenerateBlockIdForStmtNode(ParseNode *pn, TreeContext *tc)
 {
     JS_ASSERT(tc->topStmt);
     JS_ASSERT(STMT_MAYBE_SCOPE(tc->topStmt));
-    JS_ASSERT(pn->isKind(PNK_LC) || pn->isKind(PNK_LEXICALSCOPE));
+    JS_ASSERT(pn->isKind(PNK_STATEMENTLIST) || pn->isKind(PNK_LEXICALSCOPE));
     if (!GenerateBlockId(tc, tc->topStmt->blockid))
         return false;
     pn->pn_blockid = tc->topStmt->blockid;
     return true;
 }
 
 /*
  * Parse a top-level JS script.
@@ -316,17 +316,17 @@ JS_STATIC_ASSERT(UpvarCookie::FREE_LEVEL
 
 static int
 HasFinalReturn(ParseNode *pn)
 {
     ParseNode *pn2, *pn3;
     uintN rv, rv2, hasDefault;
 
     switch (pn->getKind()) {
-      case PNK_LC:
+      case PNK_STATEMENTLIST:
         if (!pn->pn_head)
             return ENDS_IN_OTHER;
         return HasFinalReturn(pn->last());
 
       case PNK_IF:
         if (!pn->pn_kid3)
             return ENDS_IN_OTHER;
         return HasFinalReturn(pn->pn_kid2) & HasFinalReturn(pn->pn_kid3);
@@ -334,17 +334,17 @@ HasFinalReturn(ParseNode *pn)
       case PNK_WHILE:
         pn2 = pn->pn_left;
         if (pn2->isKind(PNK_TRUE))
             return ENDS_IN_RETURN;
         if (pn2->isKind(PNK_NUMBER) && pn2->pn_dval)
             return ENDS_IN_RETURN;
         return ENDS_IN_OTHER;
 
-      case PNK_DO:
+      case PNK_DOWHILE:
         pn2 = pn->pn_right;
         if (pn2->isKind(PNK_FALSE))
             return HasFinalReturn(pn->pn_left);
         if (pn2->isKind(PNK_TRUE))
             return ENDS_IN_RETURN;
         if (pn2->isKind(PNK_NUMBER)) {
             if (pn2->pn_dval == 0)
                 return HasFinalReturn(pn->pn_left);
@@ -363,17 +363,17 @@ HasFinalReturn(ParseNode *pn)
         hasDefault = ENDS_IN_OTHER;
         pn2 = pn->pn_right;
         if (pn2->isKind(PNK_LEXICALSCOPE))
             pn2 = pn2->expr();
         for (pn2 = pn2->pn_head; rv && pn2; pn2 = pn2->pn_next) {
             if (pn2->isKind(PNK_DEFAULT))
                 hasDefault = ENDS_IN_RETURN;
             pn3 = pn2->pn_right;
-            JS_ASSERT(pn3->isKind(PNK_LC));
+            JS_ASSERT(pn3->isKind(PNK_STATEMENTLIST));
             if (pn3->pn_head) {
                 rv2 = HasFinalReturn(pn3->last());
                 if (rv2 == ENDS_IN_OTHER && pn2->pn_next)
                     /* Falling through to next case or default. */;
                 else
                     rv &= rv2;
             }
         }
@@ -566,32 +566,33 @@ js::CheckStrictParameters(JSContext *cx,
                 return false;
         }
     }
 
     return true;
 }
 
 ParseNode *
-Parser::functionBody()
+Parser::functionBody(FunctionBodyType type)
 {
     JS_ASSERT(tc->inFunction());
 
     StmtInfo stmtInfo;
     PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
     stmtInfo.flags = SIF_BODY_BLOCK;
 
     uintN oldflags = tc->flags;
     tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID);
 
     ParseNode *pn;
-#if JS_HAS_EXPR_CLOSURES
-    if (tokenStream.currentToken().type == TOK_LC) {
+    if (type == StatementListBody) {
         pn = statements();
     } else {
+        JS_ASSERT(type == ExpressionBody);
+        JS_ASSERT(JS_HAS_EXPR_CLOSURES);
         pn = UnaryNode::create(PNK_RETURN, tc);
         if (pn) {
             pn->pn_kid = assignExpr();
             if (!pn->pn_kid) {
                 pn = NULL;
             } else {
                 if (tc->flags & TCF_FUN_IS_GENERATOR) {
                     ReportBadReturn(context, tc, pn, JSREPORT_ERROR,
@@ -600,19 +601,16 @@ Parser::functionBody()
                     pn = NULL;
                 } else {
                     pn->setOp(JSOP_RETURN);
                     pn->pn_pos.end = pn->pn_kid->pn_pos.end;
                 }
             }
         }
     }
-#else
-    pn = statements();
-#endif
 
     if (pn) {
         JS_ASSERT(!(tc->topStmt->flags & SIF_SCOPE));
         PopStatementTC(tc);
 
         /* Check for falling off the end of a function that returns a value. */
         if (context->hasStrictOption() && (tc->flags & TCF_RETURN_EXPR) &&
             !CheckFinalReturn(context, tc, pn)) {
@@ -670,16 +668,18 @@ Define(ParseNode *pn, JSAtom *atom, Tree
         if (pnu != dn->dn_uses) {
             *pnup = pn->dn_uses;
             pn->dn_uses = dn->dn_uses;
             dn->dn_uses = pnu;
 
             if ((!pnu || pnu->pn_blockid < tc->bodyid) && foundLexdep)
                 tc->lexdeps->remove(atom);
         }
+
+        pn->pn_dflags |= dn->pn_dflags & PND_CLOSED;
     }
 
     Definition *toAdd = (Definition *) pn;
     bool ok = let ? tc->decls.addShadow(atom, toAdd) : tc->decls.addUnique(atom, toAdd);
     if (!ok)
         return false;
     pn->setDefn(true);
     pn->pn_dflags &= ~PND_PLACEHOLDER;
@@ -1504,38 +1504,39 @@ Parser::functionDef(PropertyName *funNam
         return NULL;
     }
     if (type == Setter && fun->nargs != 1) {
         reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_ACCESSOR_WRONG_ARGS,
                           "setter", "one", "");
         return NULL;
     }
 
+    FunctionBodyType bodyType = StatementListBody;
 #if JS_HAS_EXPR_CLOSURES
-    TokenKind tt = tokenStream.getToken(TSF_OPERAND);
-    if (tt != TOK_LC) {
+    if (tokenStream.getToken(TSF_OPERAND) != TOK_LC) {
         tokenStream.ungetToken();
         fun->flags |= JSFUN_EXPR_CLOSURE;
+        bodyType = ExpressionBody;
     }
 #else
     MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);
 #endif
 
-    ParseNode *body = functionBody();
+    ParseNode *body = functionBody(bodyType);
     if (!body)
         return NULL;
 
     if (funName && !CheckStrictBinding(context, &funtc, funName, pn))
         return NULL;
 
     if (!CheckStrictParameters(context, &funtc))
         return NULL;
 
 #if JS_HAS_EXPR_CLOSURES
-    if (tt == TOK_LC)
+    if (bodyType == StatementListBody)
         MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
     else if (kind == Statement && !MatchOrInsertSemicolon(context, &tokenStream))
         return NULL;
 #else
     MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
 #endif
     pn->pn_pos.end = tokenStream.currentToken().pos.end;
 
@@ -1761,52 +1762,49 @@ Parser::recognizeDirectivePrologue(Parse
 /*
  * Parse the statements in a block, creating a TOK_LC node that lists the
  * statements' trees.  If called from block-parsing code, the caller must
  * match { before and } after.
  */
 ParseNode *
 Parser::statements()
 {
-    ParseNode *pn2, *saveBlock;
-    TokenKind tt;
-
     JS_CHECK_RECURSION(context, return NULL);
 
-    ParseNode *pn = ListNode::create(PNK_LC, tc);
+    ParseNode *pn = ListNode::create(PNK_STATEMENTLIST, tc);
     if (!pn)
         return NULL;
     pn->makeEmpty();
     pn->pn_blockid = tc->blockid();
-    saveBlock = tc->blockNode;
+    ParseNode *saveBlock = tc->blockNode;
     tc->blockNode = pn;
 
     bool inDirectivePrologue = tc->atBodyLevel();
     tokenStream.setOctalCharacterEscape(false);
     for (;;) {
-        tt = tokenStream.peekToken(TSF_OPERAND);
+        TokenKind tt = tokenStream.peekToken(TSF_OPERAND);
         if (tt <= TOK_EOF || tt == TOK_RC) {
             if (tt == TOK_ERROR) {
                 if (tokenStream.isEOF())
                     tokenStream.setUnexpectedEOF();
                 return NULL;
             }
             break;
         }
-        pn2 = statement();
-        if (!pn2) {
+        ParseNode *next = statement();
+        if (!next) {
             if (tokenStream.isEOF())
                 tokenStream.setUnexpectedEOF();
             return NULL;
         }
 
-        if (inDirectivePrologue && !recognizeDirectivePrologue(pn2, &inDirectivePrologue))
+        if (inDirectivePrologue && !recognizeDirectivePrologue(next, &inDirectivePrologue))
             return NULL;
 
-        if (pn2->isKind(PNK_FUNCTION)) {
+        if (next->isKind(PNK_FUNCTION)) {
             /*
              * PNX_FUNCDEFS notifies the emitter that the block contains body-
              * level function definitions that should be processed before the
              * rest of nodes.
              *
              * TCF_HAS_FUNCTION_STMT is for the TOK_LC case in Statement. It
              * is relevant only for function definitions not at body-level,
              * which we call function statements.
@@ -1814,17 +1812,17 @@ Parser::statements()
             if (tc->atBodyLevel()) {
                 pn->pn_xflags |= PNX_FUNCDEFS;
             } else {
                 tc->flags |= TCF_HAS_FUNCTION_STMT;
                 /* Function statements extend the Call object at runtime. */
                 tc->noteHasExtensibleScope();
             }
         }
-        pn->append(pn2);
+        pn->append(next);
     }
 
     /*
      * Handle the case where there was a let declaration under this block.  If
      * it replaced tc->blockNode with a new block node then we must refresh pn
      * and then restore tc->blockNode.
      */
     if (tc->blockNode != pn)
@@ -2810,17 +2808,17 @@ Parser::letBlock(JSBool statement)
     /* This is a let block or expression of the form: let (a, b, c) .... */
     StmtInfo stmtInfo;
     ParseNode *pnblock = PushLexicalScope(context, &tokenStream, tc, &stmtInfo);
     if (!pnblock)
         return NULL;
     ParseNode *pn = pnblock;
     pn->pn_expr = pnlet;
 
-    pnlet->pn_left = variables(true);
+    pnlet->pn_left = variables(PNK_LP, true);
     if (!pnlet->pn_left)
         return NULL;
     pnlet->pn_left->pn_xflags = PNX_POPVAR;
 
     MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_LET);
 
     if (statement && !tokenStream.matchToken(TOK_LC, TSF_OPERAND)) {
         /*
@@ -2946,17 +2944,17 @@ Parser::switchStatement()
     /*
      * NB: we must push stmtInfo before calling GenerateBlockIdForStmtNode
      * because that function states tc->topStmt->blockid.
      */
     StmtInfo stmtInfo;
     PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
 
     /* pn2 is a list of case nodes. The default case has pn_left == NULL */
-    ParseNode *pn2 = ListNode::create(PNK_LC, tc);
+    ParseNode *pn2 = ListNode::create(PNK_STATEMENTLIST, tc);
     if (!pn2)
         return NULL;
     pn2->makeEmpty();
     if (!GenerateBlockIdForStmtNode(pn2, tc))
         return NULL;
     ParseNode *saveBlock = tc->blockNode;
     tc->blockNode = pn2;
 
@@ -2998,17 +2996,17 @@ Parser::switchStatement()
         pn2->append(pn3);
         if (pn2->pn_count == JS_BIT(16)) {
             reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_TOO_MANY_CASES);
             return NULL;
         }
 
         MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
 
-        ParseNode *pn4 = ListNode::create(PNK_LC, tc);
+        ParseNode *pn4 = ListNode::create(PNK_STATEMENTLIST, tc);
         if (!pn4)
             return NULL;
         pn4->makeEmpty();
         while ((tt = tokenStream.peekToken(TSF_OPERAND)) != TOK_RC &&
                tt != TOK_CASE && tt != TOK_DEFAULT) {
             if (tt == TOK_ERROR)
                 return NULL;
             ParseNode *pn5 = statement();
@@ -3103,36 +3101,38 @@ Parser::forStatement()
              * recognized as an operator, leaving it available to be parsed as
              * part of a for/in loop.
              *
              * A side effect of this restriction is that (unparenthesized)
              * expressions involving an 'in' operator are illegal in the init
              * clause of an ordinary for loop.
              */
             tc->flags |= TCF_IN_FOR_INIT;
-            if (tt == TOK_VAR) {
+            if (tt == TOK_VAR || tt == TOK_CONST) {
                 forDecl = true;
-                (void) tokenStream.getToken();
-                pn1 = variables(false);
+                tokenStream.consumeKnownToken(tt);
+                pn1 = variables(tt == TOK_VAR ? PNK_VAR : PNK_CONST, false);
+            }
 #if JS_HAS_BLOCK_SCOPE
-            } else if (tt == TOK_LET) {
+            else if (tt == TOK_LET) {
                 let = true;
                 (void) tokenStream.getToken();
                 if (tokenStream.peekToken() == TOK_LP) {
                     pn1 = letBlock(JS_FALSE);
                 } else {
                     forDecl = true;
                     pnlet = PushLexicalScope(context, &tokenStream, tc, &blockInfo);
                     if (!pnlet)
                         return NULL;
                     blockInfo.flags |= SIF_FOR_BLOCK;
-                    pn1 = variables(false);
+                    pn1 = variables(PNK_LET, false);
                 }
+            }
 #endif
-            } else {
+            else {
                 pn1 = expr();
             }
             tc->flags &= ~TCF_IN_FOR_INIT;
             if (!pn1)
                 return NULL;
         }
     }
 
@@ -3308,17 +3308,17 @@ Parser::forStatement()
         pn3 = expr();
         if (!pn3)
             return NULL;
 #if JS_HAS_BLOCK_SCOPE
         if (let)
             tc->topStmt = save;
 #endif
 
-        pn4 = TernaryNode::create(PNK_IN, tc);
+        pn4 = TernaryNode::create(PNK_FORIN, tc);
         if (!pn4)
             return NULL;
     } else {
         if (pn->pn_iflags & JSITER_FOREACH) {
             reportErrorNumber(pn, JSREPORT_ERROR, JSMSG_BAD_FOR_EACH_LOOP);
             return NULL;
         }
         pn->setOp(JSOP_NOP);
@@ -3643,19 +3643,17 @@ Parser::letStatement()
         if (stmt && (stmt->flags & SIF_SCOPE)) {
             JS_ASSERT(tc->blockChainBox == stmt->blockBox);
         } else {
             if (!stmt || (stmt->flags & SIF_BODY_BLOCK)) {
                 /*
                  * ES4 specifies that let at top level and at body-block scope
                  * does not shadow var, so convert back to var.
                  */
-                tokenStream.mungeCurrentToken(TOK_VAR, JSOP_DEFVAR);
-
-                pn = variables(false);
+                pn = variables(PNK_VAR, false);
                 if (!pn)
                     return NULL;
                 pn->pn_xflags |= PNX_POPVAR;
                 break;
             }
 
             /*
              * Some obvious assertions here, but they may help clarify the
@@ -3707,17 +3705,17 @@ Parser::letStatement()
             pn1->setOp(JSOP_LEAVEBLOCK);
             pn1->pn_pos = tc->blockNode->pn_pos;
             pn1->pn_objbox = blockbox;
             pn1->pn_expr = tc->blockNode;
             pn1->pn_blockid = tc->blockNode->pn_blockid;
             tc->blockNode = pn1;
         }
 
-        pn = variables(false);
+        pn = variables(PNK_LET, false);
         if (!pn)
             return NULL;
         pn->pn_xflags = PNX_POPVAR;
     } while (0);
 
     /* Check termination of this primitive statement. */
     return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
 }
@@ -3752,17 +3750,17 @@ Parser::expressionStatement()
         PushStatement(tc, &stmtInfo, STMT_LABEL, -1);
         stmtInfo.label = label;
         ParseNode *pn = statement();
         if (!pn)
             return NULL;
 
         /* Normalize empty statement to empty block for the decompiler. */
         if (pn->isKind(PNK_SEMI) && !pn->pn_kid) {
-            pn->setKind(PNK_LC);
+            pn->setKind(PNK_STATEMENTLIST);
             pn->setArity(PN_LIST);
             pn->makeEmpty();
         }
 
         /* Pop the label, set pn_expr, and return early. */
         PopStatement(tc);
         pn2->setKind(PNK_COLON);
         pn2->pn_pos.end = pn->pn_pos.end;
@@ -3884,17 +3882,17 @@ Parser::statement()
         PopStatement(tc);
         pn->pn_pos.end = pn3->pn_pos.end;
         pn->pn_right = pn3;
         return pn;
       }
 
       case TOK_DO:
       {
-        pn = BinaryNode::create(PNK_DO, tc);
+        pn = BinaryNode::create(PNK_DOWHILE, tc);
         if (!pn)
             return NULL;
         StmtInfo stmtInfo;
         PushStatement(tc, &stmtInfo, STMT_DO_LOOP, -1);
         ParseNode *pn2 = statement();
         if (!pn2)
             return NULL;
         pn->pn_left = pn2;
@@ -4030,17 +4028,26 @@ Parser::statement()
             pn->pn_pos.end = tokenStream.currentToken().pos.end;
         break;
       }
 
       case TOK_WITH:
         return withStatement();
 
       case TOK_VAR:
-        pn = variables(false);
+        pn = variables(PNK_VAR, false);
+        if (!pn)
+            return NULL;
+
+        /* Tell js_EmitTree to generate a final POP. */
+        pn->pn_xflags |= PNX_POPVAR;
+        break;
+
+      case TOK_CONST:
+        pn = variables(PNK_CONST, false);
         if (!pn)
             return NULL;
 
         /* Tell js_EmitTree to generate a final POP. */
         pn->pn_xflags |= PNX_POPVAR;
         break;
 
 #if JS_HAS_BLOCK_SCOPE
@@ -4096,17 +4103,17 @@ Parser::statement()
         break;
 
 #if JS_HAS_XML_SUPPORT
       case TOK_DEFAULT:
       {
         if (tc->inStrictMode())
             return expressionStatement();
 
-        pn = UnaryNode::create(PNK_DEFAULT, tc);
+        pn = UnaryNode::create(PNK_DEFXMLNS, tc);
         if (!pn)
             return NULL;
         if (!tokenStream.matchToken(TOK_NAME) ||
             tokenStream.currentToken().name() != context->runtime->atomState.xmlAtom ||
             !tokenStream.matchToken(TOK_NAME) ||
             tokenStream.currentToken().name() != context->runtime->atomState.namespaceAtom ||
             !tokenStream.matchToken(TOK_ASSIGN))
         {
@@ -4135,28 +4142,28 @@ Parser::statement()
         return expressionStatement();
     }
 
     /* Check termination of this primitive statement. */
     return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
 }
 
 ParseNode *
-Parser::variables(bool inLetHead)
+Parser::variables(ParseNodeKind kind, bool inLetHead)
 {
     /*
-     * The three options here are:
-     * - TOK_VAR: We're parsing var declarations.
-     * - TOK_LET: We are parsing a let declaration.
-     * - TOK_LP: We are parsing the head of a let block.
+     * The four options here are:
+     * - PNK_VAR:   We're parsing var declarations.
+     * - PNK_CONST: We're parsing const declarations.
+     * - PNK_LET:   We are parsing a let declaration.
+     * - PNK_LP:    We are parsing the head of a let block.
      */
-    TokenKind tt = tokenStream.currentToken().type;
-    JS_ASSERT(tt == TOK_VAR || tt == TOK_LET || tt == TOK_LP);
-
-    bool let = (tt == TOK_LET || tt == TOK_LP);
+    JS_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET || kind == PNK_LP);
+
+    bool let = (kind == PNK_LET || kind == PNK_LP);
 
 #if JS_HAS_BLOCK_SCOPE
     bool popScope = (inLetHead || (let && (tc->flags & TCF_IN_FOR_INIT)));
     StmtInfo *save = tc->topStmt, *saveScope = tc->topScopeStmt;
 #endif
 
     /* Make sure that statement set up the tree context correctly. */
     StmtInfo *scopeStmt = tc->topScopeStmt;
@@ -4164,18 +4171,18 @@ Parser::variables(bool inLetHead)
         while (scopeStmt && !(scopeStmt->flags & SIF_SCOPE)) {
             JS_ASSERT(!STMT_MAYBE_SCOPE(scopeStmt));
             scopeStmt = scopeStmt->downScope;
         }
         JS_ASSERT(scopeStmt);
     }
 
     BindData data;
-    data.op = let ? JSOP_NOP : tokenStream.currentToken().t_op;
-    ParseNode *pn = ListNode::create(tt == TOK_LET ? PNK_LET : tt == TOK_VAR ? PNK_VAR : PNK_LP, tc);
+    data.op = let ? JSOP_NOP : kind == PNK_VAR ? JSOP_DEFVAR : JSOP_DEFCONST;
+    ParseNode *pn = ListNode::create(kind, tc);
     if (!pn)
         return NULL;
     pn->setOp(data.op);
     pn->makeEmpty();
 
     /*
      * SpiderMonkey const is really "write once per initialization evaluation"
      * var, whereas let is block scoped. ES-Harmony wants block-scoped const so
@@ -4186,17 +4193,17 @@ Parser::variables(bool inLetHead)
         data.binder = BindLet;
         data.let.overflow = JSMSG_TOO_MANY_LOCALS;
     } else {
         data.binder = BindVarOrConst;
     }
 
     ParseNode *pn2;
     do {
-        tt = tokenStream.getToken();
+        TokenKind tt = tokenStream.getToken();
 #if JS_HAS_DESTRUCTURING
         if (tt == TOK_LB || tt == TOK_LC) {
             tc->flags |= TCF_DECL_DESTRUCTURING;
             pn2 = primaryExpr(tt, JS_FALSE);
             tc->flags &= ~TCF_DECL_DESTRUCTURING;
             if (!pn2)
                 return NULL;
 
@@ -4376,17 +4383,17 @@ BEGIN_EXPR_PARSER(mulExpr1)
 END_EXPR_PARSER(mulExpr1)
 
 BEGIN_EXPR_PARSER(addExpr1)
 {
     ParseNode *pn = mulExpr1i();
     while (pn && tokenStream.isCurrentTokenType(TOK_PLUS, TOK_MINUS)) {
         TokenKind tt = tokenStream.currentToken().type;
         JSOp op = (tt == TOK_PLUS) ? JSOP_ADD : JSOP_SUB;
-        ParseNodeKind kind = (tt == TOK_PLUS) ? PNK_PLUS : PNK_MINUS;
+        ParseNodeKind kind = (tt == TOK_PLUS) ? PNK_ADD : PNK_SUB;
         pn = ParseNode::newBinaryOrAppend(kind, op, pn, mulExpr1n(), tc);
     }
     return pn;
 }
 END_EXPR_PARSER(addExpr1)
 
 inline ParseNodeKind
 ShiftTokenToParseNodeKind(const Token &token)
@@ -4777,19 +4784,19 @@ Parser::unaryExpr()
         return unaryOpExpr(PNK_TYPEOF, JSOP_TYPEOF);
       case TOK_VOID:
         return unaryOpExpr(PNK_VOID, JSOP_VOID);
       case TOK_NOT:
         return unaryOpExpr(PNK_NOT, JSOP_NOT);
       case TOK_BITNOT:
         return unaryOpExpr(PNK_BITNOT, JSOP_BITNOT);
       case TOK_PLUS:
-        return unaryOpExpr(PNK_PLUS, JSOP_POS);
+        return unaryOpExpr(PNK_POS, JSOP_POS);
       case TOK_MINUS:
-        return unaryOpExpr(PNK_MINUS, JSOP_NEG);
+        return unaryOpExpr(PNK_NEG, JSOP_NEG);
 
       case TOK_INC:
       case TOK_DEC:
         pn = UnaryNode::create((tt == TOK_INC) ? PNK_INC : PNK_DEC, tc);
         if (!pn)
             return NULL;
         pn2 = memberExpr(JS_TRUE);
         if (!pn2)
@@ -5401,17 +5408,17 @@ Parser::comprehensionTail(ParseNode *kid
         vars->append(pn3);
         vars->pn_xflags |= PNX_FORINVAR;
 
         /* Definitions can't be passed directly to EmitAssignment as lhs. */
         pn3 = CloneLeftHandSide(pn3, tc);
         if (!pn3)
             return NULL;
 
-        pn2->pn_left = new_<TernaryNode>(PNK_IN, JSOP_NOP, vars, pn3, pn4);
+        pn2->pn_left = new_<TernaryNode>(PNK_FORIN, JSOP_NOP, vars, pn3, pn4);
         if (!pn2->pn_left)
             return NULL;
         *pnp = pn2;
         pnp = &pn2->pn_right;
     } while (tokenStream.matchToken(TOK_FOR));
 
     if (tokenStream.matchToken(TOK_IF)) {
         pn2 = TernaryNode::create(PNK_IF, tc);
@@ -6033,17 +6040,17 @@ Parser::attributeIdentifier()
  * Make a TOK_LC unary node whose pn_kid is an expression.
  */
 ParseNode *
 Parser::xmlExpr(JSBool inTag)
 {
     JS_ASSERT(!tc->inStrictMode());
 
     JS_ASSERT(tokenStream.currentToken().type == TOK_LC);
-    ParseNode *pn = UnaryNode::create(PNK_LC, tc);
+    ParseNode *pn = UnaryNode::create(PNK_XMLCURLYEXPR, tc);
     if (!pn)
         return NULL;
 
     /*
      * Turn off XML tag mode. We save the old value of the flag because it may
      * already be off: XMLExpr is called both from within a tag, and from
      * within text contained in an element, but outside of any start, end, or
      * point tag.
@@ -6078,17 +6085,17 @@ Parser::atomNode(ParseNodeKind kind, JSO
  *
  *      XMLNameExpr:
  *              XMLName XMLNameExpr?
  *              { Expr } XMLNameExpr?
  *
  * Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces
  * a list of names and/or expressions, a single expression, or a single name.
  * If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME.  Otherwise if
- * PN_UNARY, getKind() will be PNK_LC.
+ * PN_UNARY, getKind() will be PNK_XMLCURLYEXPR.
  */
 ParseNode *
 Parser::xmlNameExpr()
 {
     JS_ASSERT(!tc->inStrictMode());
 
     ParseNode *pn, *pn2, *list;
     TokenKind tt;
@@ -6130,34 +6137,34 @@ Parser::xmlNameExpr()
 }
 
 /*
  * Macro to test whether an XMLNameExpr or XMLTagContent node can be folded
  * at compile time into a JSXML tree.
  */
 #define XML_FOLDABLE(pn)        ((pn)->isArity(PN_LIST)                     \
                                  ? ((pn)->pn_xflags & PNX_CANTFOLD) == 0    \
-                                 : !(pn)->isKind(PNK_LC))
+                                 : !(pn)->isKind(PNK_XMLCURLYEXPR))
 
 /*
  * Parse the productions:
  *
  *      XMLTagContent:
  *              XMLNameExpr
  *              XMLTagContent S XMLNameExpr S? = S? XMLAttr
  *              XMLTagContent S XMLNameExpr S? = S? { Expr }
  *
  * Return a PN_LIST, PN_UNARY, or PN_NULLARY according to how XMLTagContent
  * produces a list of name and attribute values and/or braced expressions, a
  * single expression, or a single name.
  *
  * If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME for the case where
  * XMLTagContent: XMLNameExpr.  If getKind() is not PNK_XMLNAME but getArity()
  * is PN_LIST, getKind() will be tagkind.  If PN_UNARY, getKind() will be
- * PNK_LC and we parsed exactly one expression.
+ * PNK_XMLCURLYEXPR and we parsed exactly one expression.
  */
 ParseNode *
 Parser::xmlTagContent(ParseNodeKind tagkind, JSAtom **namep)
 {
     JS_ASSERT(!tc->inStrictMode());
 
     ParseNode *pn, *pn2, *list;
     TokenKind tt;
@@ -6328,17 +6335,17 @@ Parser::xmlElementOrList(JSBool allowLis
         tt = tokenStream.getToken();
         if (tt == TOK_XMLPTAGC) {
             /* Point tag (/>): recycle pn if pn2 is a list of tag contents. */
             if (pn2->isKind(PNK_XMLSTAGO)) {
                 pn->makeEmpty();
                 freeTree(pn);
                 pn = pn2;
             } else {
-                JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_LC));
+                JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR));
                 pn->initList(pn2);
                 if (!XML_FOLDABLE(pn2))
                     pn->pn_xflags |= PNX_CANTFOLD;
             }
             pn->setKind(PNK_XMLPTAGC);
             pn->pn_xflags |= PNX_XMLROOT;
         } else {
             /* We had better have a tag-close (>) at this point. */
@@ -6390,17 +6397,17 @@ Parser::xmlElementOrList(JSBool allowLis
             if (endAtom && startAtom && endAtom != startAtom) {
                 /* End vs. start tag name mismatch: point to the tag name. */
                 reportErrorNumber(pn2, JSREPORT_UC | JSREPORT_ERROR, JSMSG_XML_TAG_NAME_MISMATCH,
                                   startAtom->chars());
                 return NULL;
             }
 
             /* Make a TOK_XMLETAGO list with pn2 as its single child. */
-            JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_LC));
+            JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR));
             list = ListNode::create(PNK_XMLETAGO, tc);
             if (!list)
                 return NULL;
             list->initList(pn2);
             pn->append(list);
             if (!XML_FOLDABLE(pn2)) {
                 list->pn_xflags |= PNX_CANTFOLD;
                 pn->pn_xflags |= PNX_CANTFOLD;
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -152,17 +152,23 @@ struct Parser : private AutoGCRooter
     void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
 
     /* new_ methods for creating parse nodes. These report OOM on context. */
     JS_DECLARE_NEW_METHODS(allocParseNode, inline)
 
     /* Public entry points for parsing. */
     ParseNode *statement();
     bool recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMember);
-    ParseNode *functionBody();
+
+    /*
+     * Parse a function body.  Pass StatementListBody if the body is a list of
+     * statements; pass ExpressionBody if the body is a single expression.
+     */
+    enum FunctionBodyType { StatementListBody, ExpressionBody };
+    ParseNode *functionBody(FunctionBodyType type);
 
   private:
     /*
      * JS parsers, from lowest to highest precedence.
      *
      * Each parser must be called during the dynamic scope of a TreeContext
      * object, pointed to by this->tc.
      *
@@ -183,17 +189,17 @@ struct Parser : private AutoGCRooter
     ParseNode *switchStatement();
     ParseNode *forStatement();
     ParseNode *tryStatement();
     ParseNode *withStatement();
 #if JS_HAS_BLOCK_SCOPE
     ParseNode *letStatement();
 #endif
     ParseNode *expressionStatement();
-    ParseNode *variables(bool inLetHead);
+    ParseNode *variables(ParseNodeKind kind, bool inLetHead);
     ParseNode *expr();
     ParseNode *assignExpr();
     ParseNode *condExpr1();
     ParseNode *orExpr1();
     ParseNode *andExpr1i();
     ParseNode *andExpr1n();
     ParseNode *bitOrExpr1i();
     ParseNode *bitOrExpr1n();
--- a/js/src/frontend/SemanticAnalysis.cpp
+++ b/js/src/frontend/SemanticAnalysis.cpp
@@ -528,17 +528,17 @@ ConsiderUnbranding(FunctionBox *funbox)
     bool returnsExpr = !!(funbox->tcflags & TCF_RETURN_EXPR);
 #if JS_HAS_EXPR_CLOSURES
     {
         ParseNode *pn2 = funbox->node->pn_body;
         if (pn2->isKind(PNK_UPVARS))
             pn2 = pn2->pn_tree;
         if (pn2->isKind(PNK_ARGSBODY))
             pn2 = pn2->last();
-        if (!pn2->isKind(PNK_LC))
+        if (!pn2->isKind(PNK_STATEMENTLIST))
             returnsExpr = true;
     }
 #endif
     if (!returnsExpr) {
         uintN methodSets = 0, slowMethodSets = 0;
 
         for (ParseNode *method = funbox->methods; method; method = method->pn_link) {
             JS_ASSERT(method->isOp(JSOP_LAMBDA) || method->isOp(JSOP_LAMBDA_FC));
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -2246,16 +2246,17 @@ TokenKindToString(TokenKind tt)
       case TOK_DEFAULT:         return "TOK_DEFAULT";
       case TOK_WHILE:           return "TOK_WHILE";
       case TOK_DO:              return "TOK_DO";
       case TOK_FOR:             return "TOK_FOR";
       case TOK_BREAK:           return "TOK_BREAK";
       case TOK_CONTINUE:        return "TOK_CONTINUE";
       case TOK_IN:              return "TOK_IN";
       case TOK_VAR:             return "TOK_VAR";
+      case TOK_CONST:           return "TOK_CONST";
       case TOK_WITH:            return "TOK_WITH";
       case TOK_RETURN:          return "TOK_RETURN";
       case TOK_NEW:             return "TOK_NEW";
       case TOK_DELETE:          return "TOK_DELETE";
       case TOK_DEFSHARP:        return "TOK_DEFSHARP";
       case TOK_USESHARP:        return "TOK_USESHARP";
       case TOK_TRY:             return "TOK_TRY";
       case TOK_CATCH:           return "TOK_CATCH";
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -100,16 +100,17 @@ enum TokenKind {
     TOK_DEFAULT,                   /* default keyword */
     TOK_WHILE,                     /* while keyword */
     TOK_DO,                        /* do keyword */
     TOK_FOR,                       /* for keyword */
     TOK_BREAK,                     /* break keyword */
     TOK_CONTINUE,                  /* continue keyword */
     TOK_IN,                        /* in keyword */
     TOK_VAR,                       /* var keyword */
+    TOK_CONST,                     /* const keyword */
     TOK_WITH,                      /* with keyword */
     TOK_RETURN,                    /* return keyword */
     TOK_NEW,                       /* new keyword */
     TOK_DELETE,                    /* delete keyword */
     TOK_DEFSHARP,                  /* #n= for object/array initializers */
     TOK_USESHARP,                  /* #n# for object/array initializers */
     TOK_TRY,                       /* try keyword */
     TOK_CATCH,                     /* catch keyword */
@@ -538,24 +539,17 @@ class TokenStream
 
     bool isStrictMode() { return !!(flags & TSF_STRICT_MODE_CODE); }
     bool isXMLTagMode() { return !!(flags & TSF_XMLTAGMODE); }
     bool isXMLOnlyMode() { return !!(flags & TSF_XMLONLYMODE); }
     bool isUnexpectedEOF() { return !!(flags & TSF_UNEXPECTED_EOF); }
     bool isEOF() const { return !!(flags & TSF_EOF); }
     bool hasOctalCharacterEscape() const { return flags & TSF_OCTAL_CHAR; }
 
-    /* Mutators. */
     bool reportCompileErrorNumberVA(ParseNode *pn, uintN flags, uintN errorNumber, va_list ap);
-    void mungeCurrentToken(TokenKind newKind) { tokens[cursor].type = newKind; }
-    void mungeCurrentToken(JSOp newOp) { tokens[cursor].t_op = newOp; }
-    void mungeCurrentToken(TokenKind newKind, JSOp newOp) {
-        mungeCurrentToken(newKind);
-        mungeCurrentToken(newOp);
-    }
 
   private:
     static JSAtom *atomize(JSContext *cx, CharBuffer &cb);
     bool putIdentInTokenbuf(const jschar *identStart);
 
     /*
      * Enables flags in the associated tokenstream for the object lifetime.
      * Useful for lexically-scoped flag toggles.
@@ -661,16 +655,20 @@ class TokenStream
         return false;
     }
 
     bool matchToken(TokenKind tt, uintN withFlags) {
         Flagger flagger(this, withFlags);
         return matchToken(tt);
     }
 
+    void consumeKnownToken(TokenKind tt) {
+        JS_ALWAYS_TRUE(matchToken(tt));
+    }
+
     /*
      * Give up responsibility for managing the sourceMap filename's memory.
      */
     const jschar *releaseSourceMap() {
         const jschar* sm = sourceMap;
         sourceMap = NULL;
         return sm;
     }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug684922.js
@@ -0,0 +1,6 @@
+// |jit-test| error: InternalError
+var op = Object.prototype;
+op.b = op;
+op.__iterator__ = Iterator;
+for (var c in {}) {}
+
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug685321.js
@@ -0,0 +1,11 @@
+function f() {
+    function g() {
+        for (var i = 0; i < 3; i++)
+        x = i;
+    };
+    var [x] = 0;
+    g();
+    assertEq(x, 2);
+    print(x);
+}
+f();
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -256,17 +256,16 @@ END_TEST(testDebugger_newScriptHook)
 
 BEGIN_TEST(testDebugger_singleStepThrow)
     {
         CHECK(JS_SetDebugModeForCompartment(cx, cx->compartment, true));
         CHECK(JS_SetInterrupt(rt, onStep, NULL));
 
         uint32 opts = JS_GetOptions(cx);
         opts |= JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS;
-        opts &= ~JSOPTION_JIT;
         JS_SetOptions(cx, opts);
 
         CHECK(JS_DefineFunction(cx, global, "setStepMode", setStepMode, 0, 0));
         EXEC("var e;\n"
              "setStepMode();\n"
              "function f() { throw 0; }\n"
              "try { f(); }\n"
              "catch (x) { e = x; }\n");
--- a/js/src/jsapi-tests/testFuncCallback.cpp
+++ b/js/src/jsapi-tests/testFuncCallback.cpp
@@ -113,30 +113,27 @@ BEGIN_TEST(testFuncCallback_bug507012)
     CHECK_EQUAL(enters, 1);
     CHECK_EQUAL(leaves, 1);
     CHECK_EQUAL(depth, 0);
     CHECK_EQUAL(overlays, enters + leaves);
     interpreted = enters = leaves = depth = overlays = 0;
 #endif
 
     // Uncomment this to validate whether you're hitting all runmodes (interp,
-    // tjit, mjit, ...?) Unfortunately, that still doesn't cover all
+    // mjit, ...?) Unfortunately, that still doesn't cover all
     // transitions between the various runmodes, but it's a start.
     //JS_DumpAllProfiles(cx);
 
     return true;
 }
 
-// Not strictly necessary, but part of the test attempts to check
-// whether these callbacks still trigger when traced, so force
-// JSOPTION_JIT just to be sure. Once the method jit and tracing jit
-// are integrated, this'll probably have to change (and we'll probably
-// want to test in all modes.)
+// Make sure that the method jit is enabled.
+// We'll probably want to test in all modes.
 virtual
 JSContext *createContext()
 {
     JSContext *cx = JSAPITest::createContext();
     if (cx)
-        JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_METHODJIT | JSOPTION_PCCOUNT);
+        JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_PCCOUNT);
     return cx;
 }
 
 END_TEST(testFuncCallback_bug507012)
--- a/js/src/jsapi-tests/testGCOutOfMemory.cpp
+++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp
@@ -19,38 +19,31 @@ ErrorCounter(JSContext *cx, const char *
 }
 
 BEGIN_TEST(testGCOutOfMemory)
 {
     JS_SetErrorReporter(cx, ErrorCounter);
 
     jsvalRoot root(cx);
 
-    /*
-     * 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);
     JS_GC(cx);
-    JS_ToggleOptions(cx, JSOPTION_JIT);
     EVAL("(function() {"
          "    var array = [];"
          "    for (var i = max >> 2; i != 0;) {"
          "        --i;"
          "        array.push({});"
          "    }"
          "})();", root.addr());
     CHECK_EQUAL(errorCount, 1);
--- a/js/src/jsapi-tests/testTrap.cpp
+++ b/js/src/jsapi-tests/testTrap.cpp
@@ -34,19 +34,16 @@ BEGIN_TEST(testTrap_gc)
     CHECK(script);
 
     // execute
     jsvalRoot v2(cx);
     CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
     CHECK(JSVAL_IS_OBJECT(v2));
     CHECK_EQUAL(emptyTrapCallCount, 0);
 
-    // Disable JIT for debugging
-    JS_SetOptions(cx, JS_GetOptions(cx) & ~JSOPTION_JIT);
-
     // Enable debug mode
     CHECK(JS_SetDebugMode(cx, JS_TRUE));
 
     static const char trapClosureText[] = "some trap closure";
 
     // scope JSScript  usage to make sure that it is not used after
     // JS_ExecuteScript. This way we avoid using Anchor.
     JSString *trapClosure;
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -369,17 +369,17 @@ class JSAPITest
             5000000
 #else
             500000
 #endif
         ;
 
         JS_SetNativeStackQuota(cx, MAX_STACK_SIZE);
 
-        JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT);
+        JS_SetOptions(cx, JSOPTION_VAROBJFIX);
         JS_SetVersion(cx, JSVERSION_LATEST);
         JS_SetErrorReporter(cx, &reportError);
         return cx;
     }
 
     virtual JSClass * getGlobalClass() {
         return basicGlobalClass();
     }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2152,30 +2152,32 @@ JS_StringToVersion(const char *string);
 
 #define JSOPTION_RELIMIT        JS_BIT(9)       /* Throw exception on any
                                                    regular expression which
                                                    backtracks more than n^3
                                                    times, where n is length
                                                    of the input string */
 /* JS_BIT(10) is currently unused. */
 
-#define JSOPTION_JIT            JS_BIT(11)      /* Deprecated; does nothing */
+/* JS_BIT(11) is currently unused. */
 
 #define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12)      /* A promise to the compiler
                                                    that a null rval out-param
                                                    will be passed to each call
                                                    to JS_ExecuteScript. */
 #define JSOPTION_UNROOTED_GLOBAL JS_BIT(13)     /* The GC will not root the
                                                    contexts' global objects
                                                    (see JS_GetGlobalObject),
                                                    leaving that up to the
                                                    embedding. */
 
 #define JSOPTION_METHODJIT      JS_BIT(14)      /* Whole-method JIT. */
-#define JSOPTION_PROFILING      JS_BIT(15)      /* Profiler to make tracer/methodjit choices. */
+
+/* JS_BIT(15) is currently unused. */
+
 #define JSOPTION_METHODJIT_ALWAYS \
                                 JS_BIT(16)      /* Always whole-method JIT,
                                                    don't tune at run-time. */
 #define JSOPTION_PCCOUNT        JS_BIT(17)      /* Collect per-op execution counts */
 
 #define JSOPTION_TYPE_INFERENCE JS_BIT(18)      /* Perform type inference. */
 #define JSOPTION_SOFTEN         JS_BIT(19)      /* Disable JIT hardening. */
 
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -127,16 +127,22 @@ JS_NewObjectWithUniqueType(JSContext *cx
 
 JS_FRIEND_API(uint32)
 JS_ObjectCountDynamicSlots(JSObject *obj)
 {
     if (obj->hasSlotsArray())
         return obj->numDynamicSlots(obj->numSlots());
     return 0;
 }
+    
+JS_PUBLIC_API(void)
+JS_ShrinkingGC(JSContext *cx)
+{
+    js_GC(cx, NULL, GC_SHRINK, gcstats::PUBLIC_API);
+}
 
 JS_FRIEND_API(JSPrincipals *)
 JS_GetCompartmentPrincipals(JSCompartment *compartment)
 {
     return compartment->principals;
 }
 
 JS_FRIEND_API(JSBool)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -65,16 +65,19 @@ extern JS_FRIEND_API(JSBool)
 JS_SplicePrototype(JSContext *cx, JSObject *obj, JSObject *proto);
 
 extern JS_FRIEND_API(JSObject *)
 JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
 
 extern JS_FRIEND_API(uint32)
 JS_ObjectCountDynamicSlots(JSObject *obj);
 
+extern JS_FRIEND_API(void)
+JS_ShrinkingGC(JSContext *cx);
+
 extern JS_FRIEND_API(size_t)
 JS_GetE4XObjectsCreated(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
 JS_SetProtoCalled(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
 JS_GetCustomIteratorCount(JSContext *cx);
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -349,16 +349,18 @@ js::GetPropertyNames(JSContext *cx, JSOb
     return Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), props);
 }
 
 size_t sCustomIteratorCount = 0;
 
 static inline bool
 GetCustomIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
 {
+    JS_CHECK_RECURSION(cx, return false);
+
     /* Check whether we have a valid __iterator__ method. */
     JSAtom *atom = cx->runtime->atomState.iteratorAtom;
     if (!js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, vp))
         return false;
 
     /* If there is no custom __iterator__ method, we are done here. */
     if (!vp->isObject()) {
         vp->setUndefined();
--- a/js/src/jskeyword.tbl
+++ b/js/src/jskeyword.tbl
@@ -78,17 +78,17 @@ JS_KEYWORD(extends,     TOK_RESERVED,   
 JS_KEYWORD(import,      TOK_RESERVED,   JSOP_NOP,       JSVERSION_DEFAULT)
 JS_KEYWORD(super,       TOK_RESERVED,   JSOP_NOP,       JSVERSION_DEFAULT)
 
 /*
  * ES5 reserved keywords with long-implemented behavior, allowed in our
  * implementation to ease code migration.
  */
 #if JS_HAS_CONST
-JS_KEYWORD(const,       TOK_VAR,        JSOP_DEFCONST,  JSVERSION_DEFAULT)
+JS_KEYWORD(const,       TOK_CONST,      JSOP_DEFCONST,  JSVERSION_DEFAULT)
 #else
 JS_KEYWORD(const,       TOK_RESERVED,   JSOP_NOP,       JSVERSION_DEFAULT)
 #endif
 #if JS_HAS_BLOCK_SCOPE
 JS_KEYWORD(let,         TOK_LET,             JSOP_NOP,  JSVERSION_1_7)
 #else
 JS_KEYWORD(let,         TOK_STRICT_RESERVED, JSOP_NOP,  JSVERSION_1_7)
 #endif
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -1775,20 +1775,20 @@ ASTSerializer::binop(ParseNodeKind kind,
       case PNK_EQ:
         return BINOP_EQ;
       case PNK_NE:
         return BINOP_NE;
       case PNK_STRICTEQ:
         return BINOP_STRICTEQ;
       case PNK_STRICTNE:
         return BINOP_STRICTNE;
-      case PNK_PLUS:
-        return BINOP_PLUS;
-      case PNK_MINUS:
-        return BINOP_MINUS;
+      case PNK_ADD:
+        return BINOP_ADD;
+      case PNK_SUB:
+        return BINOP_SUB;
       case PNK_STAR:
         return BINOP_STAR;
       case PNK_DIV:
         return BINOP_DIV;
       case PNK_MOD:
         return BINOP_MOD;
       case PNK_BITOR:
         return BINOP_BITOR;
@@ -1805,17 +1805,18 @@ ASTSerializer::binop(ParseNodeKind kind,
       default:
         return BINOP_ERR;
     }
 }
 
 bool
 ASTSerializer::statements(ParseNode *pn, NodeVector &elts)
 {
-    JS_ASSERT(pn->isKind(PNK_LC) && pn->isArity(PN_LIST));
+    JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
+    JS_ASSERT(pn->isArity(PN_LIST));
 
     if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode *next = pn->pn_head; next; next = next->pn_next) {
         Value elt;
         if (!sourceElement(next, &elt))
             return false;
@@ -1855,17 +1856,17 @@ ASTSerializer::xmls(ParseNode *pn, NodeV
     }
 
     return true;
 }
 
 bool
 ASTSerializer::blockStatement(ParseNode *pn, Value *dst)
 {
-    JS_ASSERT(pn->isKind(PNK_LC));
+    JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
 
     NodeVector stmts(cx);
     return statements(pn, stmts) &&
            builder.blockStatement(stmts, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::program(ParseNode *pn, Value *dst)
@@ -1882,35 +1883,39 @@ ASTSerializer::sourceElement(ParseNode *
 {
     /* SpiderMonkey allows declarations even in pure statement contexts. */
     return statement(pn, dst);
 }
 
 bool
 ASTSerializer::declaration(ParseNode *pn, Value *dst)
 {
-    JS_ASSERT(pn->isKind(PNK_FUNCTION) || pn->isKind(PNK_VAR) || pn->isKind(PNK_LET));
+    JS_ASSERT(pn->isKind(PNK_FUNCTION) ||
+              pn->isKind(PNK_VAR) ||
+              pn->isKind(PNK_LET) ||
+              pn->isKind(PNK_CONST));
 
     switch (pn->getKind()) {
       case PNK_FUNCTION:
         return function(pn, AST_FUNC_DECL, dst);
 
       case PNK_VAR:
+      case PNK_CONST:
         return variableDeclaration(pn, false, dst);
 
       default:
         JS_ASSERT(pn->isKind(PNK_LET));
         return variableDeclaration(pn, true, dst);
     }
 }
 
 bool
 ASTSerializer::variableDeclaration(ParseNode *pn, bool let, Value *dst)
 {
-    JS_ASSERT(let ? pn->isKind(PNK_LET) : pn->isKind(PNK_VAR));
+    JS_ASSERT(let ? pn->isKind(PNK_LET) : (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST)));
 
     /* Later updated to VARDECL_CONST if we find a PND_CONST declarator. */
     VarDeclKind kind = let ? VARDECL_LET : VARDECL_VAR;
 
     NodeVector dtors(cx);
 
     /* In a for-in context, variable declarations contain just a single pattern. */
     if (pn->pn_xflags & PNX_FORINVAR) {
@@ -2066,30 +2071,31 @@ ASTSerializer::tryStatement(ParseNode *p
 bool
 ASTSerializer::forInit(ParseNode *pn, Value *dst)
 {
     if (!pn) {
         dst->setMagic(JS_SERIALIZE_NO_NODE);
         return true;
     }
 
-    return pn->isKind(PNK_VAR)
+    return (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST))
            ? variableDeclaration(pn, false, dst)
            : pn->isKind(PNK_LET)
            ? variableDeclaration(pn, true, dst)
            : expression(pn, dst);
 }
 
 bool
 ASTSerializer::statement(ParseNode *pn, Value *dst)
 {
     JS_CHECK_RECURSION(cx, return false);
     switch (pn->getKind()) {
       case PNK_FUNCTION:
       case PNK_VAR:
+      case PNK_CONST:
       case PNK_LET:
         return declaration(pn, dst);
 
       case PNK_NAME:
         LOCAL_ASSERT(pn->isUsed());
         return statement(pn->pn_lexdef, dst);
 
       case PNK_SEMI:
@@ -2106,21 +2112,21 @@ ASTSerializer::statement(ParseNode *pn, 
             NodeVector dtors(cx);
             Value stmt;
 
             return letHead(pn->pn_left, dtors) &&
                    statement(pn->pn_right, &stmt) &&
                    builder.letStatement(dtors, stmt, &pn->pn_pos, dst);
         }
 
-        if (!pn->isKind(PNK_LC))
+        if (!pn->isKind(PNK_STATEMENTLIST))
             return statement(pn, dst);
         /* FALL THROUGH */
 
-      case PNK_LC:
+      case PNK_STATEMENTLIST:
         return blockStatement(pn, dst);
 
       case PNK_IF:
       {
         Value test, cons, alt;
 
         return expression(pn->pn_kid1, &test) &&
                statement(pn->pn_kid2, &cons) &&
@@ -2141,17 +2147,17 @@ ASTSerializer::statement(ParseNode *pn, 
 
         return expression(pn->pn_left, &expr) &&
                statement(pn->pn_right, &stmt) &&
                (pn->isKind(PNK_WITH)
                 ? builder.withStatement(expr, stmt, &pn->pn_pos, dst)
                 : builder.whileStatement(expr, stmt, &pn->pn_pos, dst));
       }
 
-      case PNK_DO:
+      case PNK_DOWHILE:
       {
         Value stmt, test;
 
         return statement(pn->pn_left, &stmt) &&
                expression(pn->pn_right, &test) &&
                builder.doWhileStatement(stmt, test, &pn->pn_pos, dst);
       }
 
@@ -2160,17 +2166,17 @@ ASTSerializer::statement(ParseNode *pn, 
         ParseNode *head = pn->pn_left;
 
         Value stmt;
         if (!statement(pn->pn_right, &stmt))
             return false;
 
         bool isForEach = pn->pn_iflags & JSITER_FOREACH;
 
-        if (head->isKind(PNK_IN)) {
+        if (head->isKind(PNK_FORIN)) {
             Value var, expr;
 
             return (!head->pn_kid1
                     ? pattern(head->pn_kid2, NULL, &var)
                     : variableDeclaration(head->pn_kid1,
                                           head->pn_kid1->isKind(PNK_LET),
                                           &var)) &&
                    expression(head->pn_kid3, &expr) &&
@@ -2195,17 +2201,17 @@ ASTSerializer::statement(ParseNode *pn, 
 
         LOCAL_ASSERT(prelude->isKind(PNK_VAR) && loop->isKind(PNK_FOR));
 
         Value var;
         if (!variableDeclaration(prelude, false, &var))
             return false;
 
         ParseNode *head = loop->pn_left;
-        JS_ASSERT(head->isKind(PNK_IN));
+        JS_ASSERT(head->isKind(PNK_FORIN));
 
         bool isForEach = loop->pn_iflags & JSITER_FOREACH;
 
         Value expr, stmt;
 
         return expression(head->pn_kid3, &expr) &&
                statement(loop->pn_right, &stmt) &&
                builder.forInStatement(var, expr, stmt, isForEach, &pn->pn_pos, dst);
@@ -2241,17 +2247,17 @@ ASTSerializer::statement(ParseNode *pn, 
                 ? builder.throwStatement(arg, &pn->pn_pos, dst)
                 : builder.returnStatement(arg, &pn->pn_pos, dst));
       }
 
       case PNK_DEBUGGER:
         return builder.debuggerStatement(&pn->pn_pos, dst);
 
 #if JS_HAS_XML_SUPPORT
-      case PNK_DEFAULT:
+      case PNK_DEFXMLNS:
       {
         LOCAL_ASSERT(pn->isArity(PN_UNARY));
 
         Value ns;
 
         return expression(pn->pn_kid, &ns) &&
                builder.xmlDefaultNamespace(ns, &pn->pn_pos, dst);
       }
@@ -2301,17 +2307,17 @@ ASTSerializer::leftAssociate(ParseNode *
 
 bool
 ASTSerializer::comprehensionBlock(ParseNode *pn, Value *dst)
 {
     LOCAL_ASSERT(pn->isArity(PN_BINARY));
 
     ParseNode *in = pn->pn_left;
 
-    LOCAL_ASSERT(in && in->isKind(PNK_IN));
+    LOCAL_ASSERT(in && in->isKind(PNK_FORIN));
 
     bool isForEach = pn->pn_iflags & JSITER_FOREACH;
 
     Value patt, src;
     return pattern(in->pn_kid2, NULL, &patt) &&
            expression(in->pn_kid3, &src) &&
            builder.comprehensionBlock(patt, src, isForEach, &in->pn_pos, dst);
 }
@@ -2332,17 +2338,17 @@ ASTSerializer::comprehension(ParseNode *
     }
 
     Value filter = MagicValue(JS_SERIALIZE_NO_NODE);
 
     if (next->isKind(PNK_IF)) {
         if (!optExpression(next->pn_kid1, &filter))
             return false;
         next = next->pn_kid2;
-    } else if (next->isKind(PNK_LC) && next->pn_count == 0) {
+    } else if (next->isKind(PNK_STATEMENTLIST) && next->pn_count == 0) {
         /* FoldConstants optimized away the push. */
         NodeVector empty(cx);
         return builder.arrayExpression(empty, &pn->pn_pos, dst);
     }
 
     LOCAL_ASSERT(next->isKind(PNK_ARRAYPUSH));
 
     Value body;
@@ -2449,21 +2455,18 @@ ASTSerializer::expression(ParseNode *pn,
         LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
 
         Value lhs, rhs;
         return pattern(pn->pn_left, NULL, &lhs) &&
                expression(pn->pn_right, &rhs) &&
                builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
       }
 
-      case PNK_PLUS:
-      case PNK_MINUS:
-        if (pn->isArity(PN_UNARY))
-            goto unary_plusminus;
-        /* FALL THROUGH */
+      case PNK_ADD:
+      case PNK_SUB:
       case PNK_STRICTEQ:
       case PNK_EQ:
       case PNK_STRICTNE:
       case PNK_NE:
       case PNK_LT:
       case PNK_LE:
       case PNK_GT:
       case PNK_GE:
@@ -2490,17 +2493,18 @@ ASTSerializer::expression(ParseNode *pn,
         }
         return leftAssociate(pn, dst);
 
       case PNK_DELETE:
       case PNK_TYPEOF:
       case PNK_VOID:
       case PNK_NOT:
       case PNK_BITNOT:
-      unary_plusminus: {
+      case PNK_POS:
+      case PNK_NEG: {
         UnaryOperator op = unop(pn->getKind(), pn->getOp());
         LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT);
 
         Value expr;
         return expression(pn->pn_kid, &expr) &&
                builder.unaryExpression(op, expr, &pn->pn_pos, dst);
       }
 
@@ -2711,17 +2715,17 @@ ASTSerializer::expression(ParseNode *pn,
 }
 
 bool
 ASTSerializer::xml(ParseNode *pn, Value *dst)
 {
     JS_CHECK_RECURSION(cx, return false);
     switch (pn->getKind()) {
 #ifdef JS_HAS_XML_SUPPORT
-      case PNK_LC:
+      case PNK_XMLCURLYEXPR:
       {
         Value expr;
         return expression(pn->pn_kid, &expr) &&
                builder.xmlEscapeExpression(expr, &pn->pn_pos, dst);
       }
 
       case PNK_XMLELEM:
       {
@@ -3026,17 +3030,18 @@ ASTSerializer::functionArgsAndBody(Parse
     ParseNode *pndestruct;
 
     /* Extract the destructuring assignments. */
     if (pnbody->isArity(PN_LIST) && (pnbody->pn_xflags & PNX_DESTRUCT)) {
         ParseNode *head = pnbody->pn_head;
         LOCAL_ASSERT(head && head->isKind(PNK_SEMI));
 
         pndestruct = head->pn_kid;
-        LOCAL_ASSERT(pndestruct && pndestruct->isKind(PNK_VAR));
+        LOCAL_ASSERT(pndestruct);
+        LOCAL_ASSERT(pndestruct->isKind(PNK_VAR));
     } else {
         pndestruct = NULL;
     }
 
     /* Serialize the arguments and body. */
     switch (pnbody->getKind()) {
       case PNK_RETURN: /* expression closure, no destructured args */
         return functionArgs(pn, pnargs, NULL, pnbody, args) &&
@@ -3046,17 +3051,17 @@ ASTSerializer::functionArgsAndBody(Parse
       {
         ParseNode *pnstart = pnbody->pn_head->pn_next;
         LOCAL_ASSERT(pnstart && pnstart->isKind(PNK_RETURN));
 
         return functionArgs(pn, pnargs, pndestruct, pnbody, args) &&
                expression(pnstart->pn_kid, body);
       }
 
-      case PNK_LC:     /* statement closure */
+      case PNK_STATEMENTLIST:     /* statement closure */
       {
         ParseNode *pnstart = (pnbody->pn_xflags & PNX_DESTRUCT)
                                ? pnbody->pn_head->pn_next
                                : pnbody->pn_head;
 
         return functionArgs(pn, pnargs, pndestruct, pnbody, args) &&
                functionBody(pnstart, &pnbody->pn_pos, body);
       }
--- a/js/src/jsreflect.h
+++ b/js/src/jsreflect.h
@@ -76,17 +76,17 @@ enum BinaryOperator {
 
     /* eq */
     BINOP_EQ = 0, BINOP_NE, BINOP_STRICTEQ, BINOP_STRICTNE,
     /* rel */
     BINOP_LT, BINOP_LE, BINOP_GT, BINOP_GE,
     /* shift */
     BINOP_LSH, BINOP_RSH, BINOP_URSH,
     /* arithmetic */
-    BINOP_PLUS, BINOP_MINUS, BINOP_STAR, BINOP_DIV, BINOP_MOD,
+    BINOP_ADD, BINOP_SUB, BINOP_STAR, BINOP_DIV, BINOP_MOD,
     /* binary */
     BINOP_BITOR, BINOP_BITXOR, BINOP_BITAND,
     /* misc */
     BINOP_IN, BINOP_INSTANCEOF,
     /* xml */
     BINOP_DBLDOT,
 
     BINOP_LIMIT
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -151,17 +151,16 @@ static jsuword gStackBase;
  * Limit the timeout to 30 minutes to prevent an overflow on platfoms
  * that represent the time internally in microseconds using 32-bit int.
  */
 static jsdouble MAX_TIMEOUT_INTERVAL = 1800.0;
 static jsdouble gTimeoutInterval = -1.0;
 static volatile bool gCanceled = false;
 
 static bool enableMethodJit = false;
-static bool enableProfiling = false;
 static bool enableTypeInference = false;
 static bool enableDisassemblyDumps = false;
 
 static bool printTiming = false;
 
 static JSBool
 SetTimeoutValue(JSContext *cx, jsdouble t);
 
@@ -608,18 +607,16 @@ cleanup:
  * JSContext option name to flag map. The option names are in alphabetical
  * order for better reporting.
  */
 static const struct JSOption {
     const char  *name;
     uint32      flag;
 } js_options[] = {
     {"atline",          JSOPTION_ATLINE},
-    {"jitprofiling",    JSOPTION_PROFILING},
-    {"tracejit",        JSOPTION_JIT},
     {"methodjit",       JSOPTION_METHODJIT},
     {"methodjit_always",JSOPTION_METHODJIT_ALWAYS},
     {"relimit",         JSOPTION_RELIMIT},
     {"strict",          JSOPTION_STRICT},
     {"typeinfer",       JSOPTION_TYPE_INFERENCE},
     {"werror",          JSOPTION_WERROR},
     {"xml",             JSOPTION_XML},
 };
@@ -1066,43 +1063,55 @@ static JSBool
 Now(JSContext *cx, uintN argc, jsval *vp)
 {
     jsdouble now = PRMJ_Now() / double(PRMJ_USEC_PER_MSEC);
     JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(now));
     return true;
 }
 
 static JSBool
-Print(JSContext *cx, uintN argc, jsval *vp)
+PrintInternal(JSContext *cx, uintN argc, jsval *vp, FILE *file)
 {
     jsval *argv;
     uintN i;
     JSString *str;
     char *bytes;
 
     argv = JS_ARGV(cx, vp);
     for (i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         bytes = JS_EncodeString(cx, str);
         if (!bytes)
             return JS_FALSE;
-        fprintf(gOutFile, "%s%s", i ? " " : "", bytes);
+        fprintf(file, "%s%s", i ? " " : "", bytes);
         JS_free(cx, bytes);
     }
 
-    fputc('\n', gOutFile);
-    fflush(gOutFile);
+    fputc('\n', file);
+    fflush(file);
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
+Print(JSContext *cx, uintN argc, jsval *vp)
+{
+    return PrintInternal(cx, argc, vp, gOutFile);
+}
+
+static JSBool
+PrintErr(JSContext *cx, uintN argc, jsval *vp)
+{
+    return PrintInternal(cx, argc, vp, gErrFile);
+}
+
+static JSBool
 Help(JSContext *cx, uintN argc, jsval *vp);
 
 static JSBool
 Quit(JSContext *cx, uintN argc, jsval *vp)
 {
     JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/ i", &gExitCode);
 
     gQuitting = JS_TRUE;
@@ -3951,16 +3960,17 @@ static JSFunctionSpec shell_functions[] 
     JS_FN("version",        Version,        0,0),
     JS_FN("revertVersion",  RevertVersion,  0,0),
     JS_FN("options",        Options,        0,0),
     JS_FN("load",           Load,           1,0),
     JS_FN("evaluate",       Evaluate,       1,0),
     JS_FN("run",            Run,            1,0),
     JS_FN("readline",       ReadLine,       0,0),
     JS_FN("print",          Print,          0,0),
+    JS_FN("printErr",       PrintErr,       0,0),
     JS_FN("putstr",         PutStr,         0,0),
     JS_FN("dateNow",        Now,            0,0),
     JS_FN("help",           Help,           0,0),
     JS_FN("quit",           Quit,           0,0),
     JS_FN("assertEq",       AssertEq,       2,0),
     JS_FN("assertJit",      AssertJit,      0,0),
     JS_FN("gc",             ::GC,           0,0),
     JS_FN("gcparam",        GCParameter,    2,0),
@@ -4003,20 +4013,16 @@ static JSFunctionSpec shell_functions[] 
     JS_FN("clone",          Clone,          1,0),
     JS_FN("getpda",         GetPDA,         1,0),
     JS_FN("getslx",         GetSLX,         1,0),
     JS_FN("toint32",        ToInt32,        1,0),
     JS_FN("evalcx",         EvalInContext,  1,0),
     JS_FN("evalInFrame",    EvalInFrame,    2,0),
     JS_FN("shapeOf",        ShapeOf,        1,0),
     JS_FN("resolver",       Resolver,       1,0),
-#ifdef MOZ_TRACEVIS
-    JS_FN("startTraceVis",  StartTraceVisNative, 1,0),
-    JS_FN("stopTraceVis",   StopTraceVisNative,  0,0),
-#endif
 #ifdef DEBUG
     JS_FN("arrayInfo",      js_ArrayInfo,   1,0),
 #endif
 #ifdef JS_THREADSAFE
     JS_FN("sleep",          Sleep_fn,       1,0),
 #endif
     JS_FN("snarf",          Snarf,          0,0),
     JS_FN("read",           Snarf,          0,0),
@@ -4049,17 +4055,18 @@ static const char *const shell_help_mess
 "revertVersion()          Revert previously set version number",
 "options([option ...])    Get or toggle JavaScript options",
 "load(['foo.js' ...])     Load files named by string arguments",
 "evaluate(code)           Evaluate code as though it were the contents of a file",
 "run('foo.js')\n"
 "  Run the file named by the first argument, returning the number of\n"
 "  of milliseconds spent compiling and executing it",
 "readline()               Read a single line from stdin",
-"print([exp ...])         Evaluate and print expressions",
+"print([exp ...])         Evaluate and print expressions to stdout",
+"printErr([exp ...])      Evaluate and print expressions to stderr",
 "putstr([exp])            Evaluate and print expression without newline",
 "dateNow()                    Return the current time with sub-ms precision",
 "help([name ...])         Display usage and help messages",
 "quit()                   Quit the shell",
 "assertEq(actual, expected[, msg])\n"
 "  Throw if the first two arguments are not the same (both +0 or both -0,\n"
 "  both NaN, or non-zero and ===)",
 "assertJit()              Throw if the calling function failed to JIT",
@@ -4129,20 +4136,16 @@ static const char *const shell_help_mess
 "  Evaluate s in optional sandbox object o\n"
 "  if (s == '' && !o) return new o with eager standard classes\n"
 "  if (s == 'lazy' && !o) return new o with lazy standard classes",
 "evalInFrame(n,str,save)  Evaluate 'str' in the nth up frame.\n"
 "                         If 'save' (default false), save the frame chain",
 "shapeOf(obj)             Get the shape of obj (an implementation detail)",
 "resolver(src[, proto])   Create object with resolve hook that copies properties\n"
 "                         from src. If proto is omitted, use Object.prototype.",
-#ifdef MOZ_TRACEVIS
-"startTraceVis(filename)  Start TraceVis recording (stops any current recording)",
-"stopTraceVis()           Stop TraceVis recording",
-#endif
 #ifdef DEBUG
 "arrayInfo(a1, a2, ...)   Report statistics about arrays",
 #endif
 #ifdef JS_THREADSAFE
 "sleep(dt)                Sleep for dt seconds",
 #endif
 "snarf(filename)          Read filename into returned string",
 "read(filename)           Synonym for snarf",
@@ -5057,21 +5060,16 @@ ProcessArgs(JSContext *cx, JSObject *obj
         JS_ToggleOptions(cx, JSOPTION_METHODJIT);
     }
 
 #ifdef JS_GC_ZEAL
     if (const char *zeal = op->getStringOption('Z'))
         ParseZealArg(cx, zeal);
 #endif
 
-    if (op->getBoolOption('p')) {
-        enableProfiling = true;
-        JS_ToggleOptions(cx, JSOPTION_PROFILING);
-    }
-
     if (op->getBoolOption('d')) {
         JS_SetRuntimeDebugMode(JS_GetRuntime(cx), true);
         JS_SetDebugMode(cx, true);
     }
 
     if (op->getBoolOption('b'))
         printTiming = true;
 
@@ -5317,24 +5315,20 @@ main(int argc, char **argv, char **envp)
     op.setDescriptionWidth(72);
     op.setHelpWidth(80);
     op.setVersion(JS_GetImplementationVersion());
 
     if (!op.addMultiStringOption('f', "file", "PATH", "File path to run")
         || !op.addMultiStringOption('e', "execute", "CODE", "Inline code to run")
         || !op.addBoolOption('i', "shell", "Enter prompt after running code")
         || !op.addBoolOption('m', "methodjit", "Enable the JaegerMonkey method JIT")
-        || !op.addBoolOption('j', "tracejit", "Deprecated; does nothing")
-        || !op.addBoolOption('p', "profiling", "Enable runtime profiling select JIT mode")
         || !op.addBoolOption('n', "typeinfer", "Enable type inference")
         || !op.addBoolOption('d', "debugjit", "Enable runtime debug mode for method JIT code")
         || !op.addBoolOption('a', "always-mjit",
-                             "Do not try to run in the interpreter before "
-                             "method jitting. Note that this has no particular effect on the "
-                             "tracer; it still kicks in if enabled.")
+                             "Do not try to run in the interpreter before method jitting.")
         || !op.addBoolOption('D', "dump-bytecode", "Dump bytecode with exec count for all scripts")
         || !op.addBoolOption('b', "print-timing", "Print sub-ms runtime for each file that's run")
 #ifdef DEBUG
         || !op.addIntOption('A', "oom-after", "COUNT", "Trigger OOM after COUNT allocations", -1)
         || !op.addBoolOption('O', "print-alloc", "Print the number of allocations at exit")
 #endif
         || !op.addBoolOption('U', "utf8", "C strings passed to the JSAPI are UTF-8 encoded")
 #ifdef JS_GC_ZEAL
--- a/js/src/tests/browser.js
+++ b/js/src/tests/browser.js
@@ -219,17 +219,16 @@ function optionsInit() {
   // hash containing the set options.
   options.currvalues = {
     strict:     true,
     werror:     true,
     atline:     true,
     xml:        true,
     relimit:    true,
     methodjit:  true,
-    jitprofiling: true,
     methodjit_always: true
   };
 
   // record initial values to support resetting
   // options to their initial values
   options.initvalues = {};
 
   // record values in a stack to support pushing
--- a/js/src/tests/js1_5/Regress/jstests.list
+++ b/js/src/tests/js1_5/Regress/jstests.list
@@ -162,17 +162,17 @@ script regress-334807-05.js
 script regress-334807-06.js
 script regress-336100.js
 script regress-338307.js
 script regress-340369.js
 skip-if(xulRuntime.OS=="WINNT"&&isDebugBuild) slow script regress-341360.js
 script regress-343713.js
 script regress-343966.js
 script regress-344711-n.js
-skip script regress-344804.js # bug 524732
+script regress-344804.js
 script regress-344959.js
 script regress-346237.js
 script regress-346801.js
 random script regress-347306-01.js # BigO
 script regress-349482-01.js
 script regress-349482-02.js
 script regress-349592.js
 script regress-349648.js
--- a/js/src/tests/js1_5/Scope/jstests.list
+++ b/js/src/tests/js1_5/Scope/jstests.list
@@ -1,11 +1,11 @@
 url-prefix ../../jsreftest.html?test=js1_5/Scope/
 script regress-154693.js
-skip script regress-181834.js # bug 524732
+script regress-181834.js
 script regress-184107.js
 script regress-185485.js
 script regress-191276.js
 script regress-192226.js
 script regress-202678-001.js
 script regress-202678-002.js
 script regress-208496-001.js
 script regress-208496-002.js
--- a/js/src/tests/shell.js
+++ b/js/src/tests/shell.js
@@ -644,17 +644,16 @@ function optionsClear() {
   // turn off current settings
   // except jit.
   var optionNames = options().split(',');
   for (var i = 0; i < optionNames.length; i++)
   {
     var optionName = optionNames[i];
     if (optionName &&
         optionName != "methodjit" &&
-        optionName != "jitprofiling" &&
         optionName != "methodjit_always")
     {
       options(optionName);
     }
   }
 }
 
 function optionsPush()
--- a/js/src/tests/user.js
+++ b/js/src/tests/user.js
@@ -25,13 +25,11 @@ user_pref("security.warn_viewing_mixed",
 user_pref("signed.applets.codebase_principal_support", true);
 user_pref("browser.warnOnQuit", false);
 user_pref("browser.cache.check_doc_frequency", 1);
 user_pref("extensions.checkCompatibility", false);
 user_pref("extensions.checkUpdateSecurity", false);
 user_pref("browser.EULA.override", true);
 user_pref("javascript.options.methodjit.chrome", true);
 user_pref("javascript.options.methodjit.content", true);
-user_pref("javascript.options.jitprofiling.chrome", true);
-user_pref("javascript.options.jitprofiling.content", true);
 user_pref("javascript.options.methodjit_always", false);
 user_pref("javascript.options.strict", false);
 user_pref("javascript.options.werror", false);
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/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(29b63029-0868-4344-b0ca-d93256ee7c78)]
+[uuid(07661008-5505-4784-a612-89f7dc2144da)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Initializes classes on a global object that has already been created.
@@ -730,17 +730,17 @@ interface nsIXPConnect : nsISupports
      * MOZ_REPORT_ALL_JS_EXCEPTIONS environment variable will override the value
      * passed here.
      */
     void setReportAllJSExceptions(in boolean reportAllJSExceptions);
 
     /**
      * Trigger a JS garbage collection.
      */
-    void GarbageCollect();
+    void GarbageCollect(in boolean shrinkingGC);
 
     /**
      * Define quick stubs on the given object, @a proto.
      *
      * @param cx
      *     A context.  Requires request.
      * @param proto
      *     The (newly created) prototype object for a DOM class.  The JS half
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -148,17 +148,17 @@ interface nsIXPCComponents_utils_Sandbox
 interface ScheduledGCCallback : nsISupports
 {
     void callback();
 };
 
 /**
 * interface of Components.utils
 */
-[scriptable, uuid(11785c1f-346f-475c-950e-fe1bacce70f1)]
+[scriptable, uuid(d6916b9e-0947-400f-8552-81fd96312c9d)]
 interface nsIXPCComponents_Utils : nsISupports
 {
 
     /* reportError is designed to be called from JavaScript only.
      *
      * It will report a JS Error object to the JS console, and return. It
      * is meant for use in exception handler blocks which want to "eat"
      * an exception, but still want to report it to the console.
@@ -319,17 +319,16 @@ interface nsIXPCComponents_Utils : nsISu
      * cheap, but setting any of them is relatively expensive.
      */
     attribute boolean strict;
     attribute boolean werror;
     attribute boolean atline;
     attribute boolean xml;
     attribute boolean relimit;
     attribute boolean methodjit;
-    attribute boolean jitprofiling;
     attribute boolean methodjit_always;
     [implicit_jscontext]
     void setGCZeal(in long zeal);
 };
 
 /**
 * interface of JavaScript's 'Components' object
 */
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -293,20 +293,16 @@ File(JSContext *cx, uintN argc, jsval *v
 }
 
 static JSFunctionSpec gGlobalFun[] = {
     {"dump",    Dump,   1,0},
     {"debug",   Debug,  1,0},
     {"atob",    Atob,   1,0},
     {"btoa",    Btoa,   1,0},
     {"File",    File,   1,JSFUN_CONSTRUCTOR},
-#ifdef MOZ_TRACEVIS
-    {"initEthogram",     js_InitEthogram,      0,0},
-    {"shutdownEthogram", js_ShutdownEthogram,  0,0},
-#endif
     {nsnull,nsnull,0,0}
 };
 
 class JSCLContextHelper
 {
 public:
     JSCLContextHelper(mozJSComponentLoader* loader);
     ~JSCLContextHelper();
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -721,17 +721,16 @@ GetChildGlobalObject(JSContext* cx,
  * JSContext option name to flag map. The option names are in alphabetical
  * order for better reporting.
  */
 static const struct JSOption {
     const char  *name;
     uint32      flag;
 } js_options[] = {
     {"atline",          JSOPTION_ATLINE},
-    {"jit",             JSOPTION_JIT},
     {"relimit",         JSOPTION_RELIMIT},
     {"strict",          JSOPTION_STRICT},
     {"werror",          JSOPTION_WERROR},
     {"xml",             JSOPTION_XML},
 };
 
 static uint32
 MapContextOptionNameToFlag(JSContext* cx, const char* name)
@@ -1278,25 +1277,19 @@ ProcessArgs(JSContext *cx, JSObject *obj
 
             isInteractive = false;
             break;
         }
         case 'C':
             compileOnly = true;
             isInteractive = false;
             break;
-        case 'j':
-            JS_ToggleOptions(cx, JSOPTION_JIT);
-            break;
         case 'm':
             JS_ToggleOptions(cx, JSOPTION_METHODJIT);
             break;
-        case 'p':
-            JS_ToggleOptions(cx, JSOPTION_PROFILING);
-            break;
         case 'n':
             JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
             break;
         default:
             return usage();
         }
     }
 
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -51,18 +51,18 @@
 #include "XPCWrapper.h"
 #include "jsproxy.h"
 #include "WrapperFactory.h"
 #include "XrayWrapper.h"
 #include "nsNullPrincipal.h"
 #include "nsJSUtils.h"
 #include "mozJSComponentLoader.h"
 #include "nsContentUtils.h"
-#include "jsgc.h"
-
+#include "jsgc.h"
+
 using namespace js;
 /***************************************************************************/
 // stuff used by all
 
 static nsresult ThrowAndFail(uintN errNum, JSContext* cx, bool* retval)
 {
     XPCThrower::Throw(errNum, cx);
     *retval = false;
@@ -3097,23 +3097,23 @@ xpc_CreateSandboxObject(JSContext * cx, 
             return NS_ERROR_OUT_OF_MEMORY;
     }
 
     nsIPrincipal *principal = sop->GetPrincipal();
 
     JSCompartment *compartment;
     JSObject *sandbox;
 
-    nsRefPtr<Identity> identity;
-    if (!identityPtr) {
-      identity = new Identity();
-      identityPtr = identity;
-    }
-
-    rv = xpc_CreateGlobalObject(cx, &SandboxClass, principal, identityPtr,
+    nsRefPtr<Identity> identity;
+    if (!identityPtr) {
+      identity = new Identity();
+      identityPtr = identity;
+    }
+
+    rv = xpc_CreateGlobalObject(cx, &SandboxClass, principal, identityPtr,
                                 wantXrays, &sandbox, &compartment);
     NS_ENSURE_SUCCESS(rv, rv);
 
     js::AutoObjectRooter tvr(cx, sandbox);
 
     {
         JSAutoEnterCompartment ac;
         if (!ac.enter(cx, sandbox))
@@ -3319,35 +3319,35 @@ nsXPCComponents_utils_Sandbox::CallOrCon
             char *tmp = JS_EncodeString(cx, JSVAL_TO_STRING(option));
             if (!tmp) {
                 return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
             }
 
             sandboxName.Adopt(tmp, strlen(tmp));
         }
 
-        // see Bug 677294:
-        if (!JS_HasProperty(cx, optionsObject, "sameGroupAs", &found))
-            return NS_ERROR_INVALID_ARG;
-
-        if (found) {
-            if (!JS_GetProperty(cx, optionsObject, "sameGroupAs", &option) ||
-                JSVAL_IS_PRIMITIVE(option)) {
-                    return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
-            }
-
-            void* privateValue =
-                JS_GetCompartmentPrivate(cx,GetObjectCompartment(JSVAL_TO_OBJECT(option)));
-            xpc::CompartmentPrivate *compartmentPrivate =
-                static_cast<xpc::CompartmentPrivate*>(privateValue);
-
-            if (!compartmentPrivate || !compartmentPrivate->key)
-                return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
-
-            identity = compartmentPrivate->key->GetPtr();
+        // see Bug 677294:
+        if (!JS_HasProperty(cx, optionsObject, "sameGroupAs", &found))
+            return NS_ERROR_INVALID_ARG;
+
+        if (found) {
+            if (!JS_GetProperty(cx, optionsObject, "sameGroupAs", &option) ||
+                JSVAL_IS_PRIMITIVE(option)) {
+                    return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
+            }
+
+            void* privateValue =
+                JS_GetCompartmentPrivate(cx,GetObjectCompartment(JSVAL_TO_OBJECT(option)));
+            xpc::CompartmentPrivate *compartmentPrivate =
+                static_cast<xpc::CompartmentPrivate*>(privateValue);
+
+            if (!compartmentPrivate || !compartmentPrivate->key)
+                return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
+
+            identity = compartmentPrivate->key->GetPtr();
         }
     }
 
     rv = xpc_CreateSandboxObject(cx, vp, prinOrSop, proto, wantXrays, sandboxName, identity);
 
     if (NS_FAILED(rv)) {
         return ThrowAndFail(rv, cx, _retval);
     }
@@ -4065,17 +4065,16 @@ GetCurrentJSContext(JSContext** aCx)
     }
 
 GENERATE_JSOPTION_GETTER_SETTER(Strict, JSOPTION_STRICT)
 GENERATE_JSOPTION_GETTER_SETTER(Werror, JSOPTION_WERROR)
 GENERATE_JSOPTION_GETTER_SETTER(Atline, JSOPTION_ATLINE)
 GENERATE_JSOPTION_GETTER_SETTER(Xml, JSOPTION_XML)
 GENERATE_JSOPTION_GETTER_SETTER(Relimit, JSOPTION_RELIMIT)
 GENERATE_JSOPTION_GETTER_SETTER(Methodjit, JSOPTION_METHODJIT)
-GENERATE_JSOPTION_GETTER_SETTER(Jitprofiling, JSOPTION_PROFILING)
 GENERATE_JSOPTION_GETTER_SETTER(Methodjit_always, JSOPTION_METHODJIT_ALWAYS)
 
 #undef GENERATE_JSOPTION_GETTER_SETTER
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::SetGCZeal(PRInt32 aValue, JSContext* cx)
 {
 #ifdef JS_GC_ZEAL
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -338,17 +338,17 @@ nsXPConnect::GetInfoForName(const char *
 
 bool
 nsXPConnect::NeedCollect()
 {
     return !!mNeedGCBeforeCC;
 }
 
 void
-nsXPConnect::Collect()
+nsXPConnect::Collect(bool shrinkingGC)
 {
     // We're dividing JS objects into 2 categories:
     //
     // 1. "real" roots, held by the JS engine itself or rooted through the root
     //    and lock JS APIs. Roots from this category are considered black in the
     //    cycle collector, any cycle they participate in is uncollectable.
     //
     // 2. roots held by C++ objects that participate in cycle collection,
@@ -401,25 +401,28 @@ nsXPConnect::Collect()
     // cycle collection. So to compensate for JS_BeginRequest in
     // XPCCallContext::Init we disable the conservative scanner if that call
     // has started the request on this thread.
     js::ThreadData &threadData = cx->thread()->data;
     JS_ASSERT(threadData.requestDepth >= 1);
     JS_ASSERT(!threadData.conservativeGC.requestThreshold);
     if (threadData.requestDepth == 1)
         threadData.conservativeGC.requestThreshold = 1;
-    JS_GC(cx);
+    if (shrinkingGC)
+        JS_ShrinkingGC(cx);
+    else
+        JS_GC(cx);
     if (threadData.requestDepth == 1)
         threadData.conservativeGC.requestThreshold = 0;
 }
 
 NS_IMETHODIMP
-nsXPConnect::GarbageCollect()
+nsXPConnect::GarbageCollect(bool shrinkingGC)
 {
-    Collect();
+    Collect(shrinkingGC);
     return NS_OK;
 }
 
 #ifdef DEBUG_CC
 struct NoteJSRootTracer : public JSTracer
 {
     NoteJSRootTracer(PLDHashTable *aObjects,
                      nsCycleCollectionTraversalCallback& cb)
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -561,17 +561,17 @@ public:
     virtual void NotifyLeaveCycleCollectionThread();
     virtual void NotifyEnterMainThread();
     virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
                                           bool explainExpectedLiveGarbage);
     virtual nsresult FinishTraverse();
     virtual nsresult FinishCycleCollection();
     virtual nsCycleCollectionParticipant *ToParticipant(void *p);
     virtual bool NeedCollect();
-    virtual void Collect();
+    virtual void Collect(bool shrinkingGC=false);
 #ifdef DEBUG_CC
     virtual void PrintAllReferencesTo(void *p);
 #endif
 
     XPCCallContext *GetCycleCollectionContext()
     {
         return mCycleCollectionContext;
     }
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -95,17 +95,17 @@ nsRefreshDriver::GetRefreshTimerInterval
 }
 
 PRInt32
 nsRefreshDriver::GetRefreshTimerType() const
 {
   if (mThrottled) {
     return nsITimer::TYPE_ONE_SHOT;
   }
-  if (HaveAnimationFrameListeners() || sPrecisePref) {
+  if (HaveFrameRequestCallbacks() || sPrecisePref) {
     return nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP;
   }
   return nsITimer::TYPE_REPEATING_SLACK;
 }
 
 nsRefreshDriver::nsRefreshDriver(nsPresContext *aPresContext)
   : mPresContext(aPresContext),
     mFrozen(false),
@@ -264,18 +264,17 @@ nsRefreshDriver::ObserverCount() const
   }
 
   // Even while throttled, we need to process layout and style changes.  Style
   // changes can trigger transitions which fire events when they complete, and
   // layout changes can affect media queries on child documents, triggering
   // style changes, etc.
   sum += mStyleFlushObservers.Length();
   sum += mLayoutFlushObservers.Length();
-  sum += mBeforePaintTargets.Length();
-  sum += mAnimationFrameListenerDocs.Length();
+  sum += mFrameRequestCallbackDocs.Length();
   return sum;
 }
 
 PRUint32
 nsRefreshDriver::ImageRequestCount() const
 {
   return mRequests.Count();
 }
@@ -360,44 +359,29 @@ nsRefreshDriver::Notify(nsITimer *aTimer
       
       if (!mPresContext || !mPresContext->GetPresShell()) {
         StopTimer();
         return NS_OK;
       }
     }
 
     if (i == 0) {
-      // Don't just loop while we have things in mBeforePaintTargets,
-      // the whole point is that event handlers should readd the
-      // target as needed.
-      nsTArray< nsCOMPtr<nsIDocument> > targets;
-      targets.SwapElements(mBeforePaintTargets);
-      for (PRUint32 i = 0; i < targets.Length(); ++i) {
-        targets[i]->BeforePaintEventFiring();
+      // Grab all of our frame request callbacks up front.
+      nsIDocument::FrameRequestCallbackList frameRequestCallbacks;
+      for (PRUint32 i = 0; i < mFrameRequestCallbackDocs.Length(); ++i) {
+        mFrameRequestCallbackDocs[i]->
+          TakeFrameRequestCallbacks(frameRequestCallbacks);
       }
-
-      // Also grab all of our animation frame listeners up front.
-      nsIDocument::AnimationListenerList animationListeners;
-      for (PRUint32 i = 0; i < mAnimationFrameListenerDocs.Length(); ++i) {
-        mAnimationFrameListenerDocs[i]->
-          TakeAnimationFrameListeners(animationListeners);
-      }
-      // OK, now reset mAnimationFrameListenerDocs so they can be
+      // OK, now reset mFrameRequestCallbackDocs so they can be
       // readded as needed.
-      mAnimationFrameListenerDocs.Clear();
+      mFrameRequestCallbackDocs.Clear();
 
       PRInt64 eventTime = mMostRecentRefreshEpochTime / PR_USEC_PER_MSEC;
-      for (PRUint32 i = 0; i < targets.Length(); ++i) {
-        nsEvent ev(true, NS_BEFOREPAINT);
-        ev.time = eventTime;
-        nsEventDispatcher::Dispatch(targets[i], nsnull, &ev);
-      }
-
-      for (PRUint32 i = 0; i < animationListeners.Length(); ++i) {
-        animationListeners[i]->OnBeforePaint(eventTime);
+      for (PRUint32 i = 0; i < frameRequestCallbacks.Length(); ++i) {
+        frameRequestCallbacks[i]->Sample(eventTime);
       }
 
       // This is the Flush_Style case.
       if (mPresContext && mPresContext->GetPresShell()) {
         nsAutoTArray<nsIPresShell*, 16> observers;
         observers.AppendElements(mStyleFlushObservers);
         for (PRUint32 j = observers.Length();
              j && mPresContext && mPresContext->GetPresShell(); --j) {
@@ -536,44 +520,27 @@ bool
 nsRefreshDriver::IsRefreshObserver(nsARefreshObserver *aObserver,
                                    mozFlushType aFlushType)
 {
   ObserverArray& array = ArrayFor(aFlushType);
   return array.Contains(aObserver);
 }
 #endif
 
-bool
-nsRefreshDriver::ScheduleBeforePaintEvent(nsIDocument* aDocument)
+void
+nsRefreshDriver::ScheduleFrameRequestCallbacks(nsIDocument* aDocument)
 {
-  NS_ASSERTION(mBeforePaintTargets.IndexOf(aDocument) ==
-               mBeforePaintTargets.NoIndex,
-               "Shouldn't have a paint event posted for this document");
-  bool appended = mBeforePaintTargets.AppendElement(aDocument) != nsnull;
-  EnsureTimerStarted(false);
-  return appended;
-}
-
-void
-nsRefreshDriver::ScheduleAnimationFrameListeners(nsIDocument* aDocument)
-{
-  NS_ASSERTION(mAnimationFrameListenerDocs.IndexOf(aDocument) ==
-               mAnimationFrameListenerDocs.NoIndex,
+  NS_ASSERTION(mFrameRequestCallbackDocs.IndexOf(aDocument) ==
+               mFrameRequestCallbackDocs.NoIndex,
                "Don't schedule the same document multiple times");
-  mAnimationFrameListenerDocs.AppendElement(aDocument);
+  mFrameRequestCallbackDocs.AppendElement(aDocument);
   // No need to worry about restarting our timer in precise mode if it's
   // already running; that will happen automatically when it fires.
   EnsureTimerStarted(false);
 }
 
 void
-nsRefreshDriver::RevokeBeforePaintEvent(nsIDocument* aDocument)
+nsRefreshDriver::RevokeFrameRequestCallbacks(nsIDocument* aDocument)
 {
-  mBeforePaintTargets.RemoveElement(aDocument);
-}
-
-void
-nsRefreshDriver::RevokeAnimationFrameListeners(nsIDocument* aDocument)
-{
-  mAnimationFrameListenerDocs.RemoveElement(aDocument);
+  mFrameRequestCallbackDocs.RemoveElement(aDocument);
   // No need to worry about restarting our timer in slack mode if it's already
   // running; that will happen automatically when it fires.
 }
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -172,34 +172,24 @@ public:
   void RemoveLayoutFlushObserver(nsIPresShell* aShell) {
     mLayoutFlushObservers.RemoveElement(aShell);
   }
   bool IsLayoutFlushObserver(nsIPresShell* aShell) {
     return mLayoutFlushObservers.Contains(aShell);
   }
 
   /**
-   * Add a document for which we should fire a MozBeforePaint event.
+   * Add a document for which we have nsIFrameRequestCallbacks
    */
-  bool ScheduleBeforePaintEvent(nsIDocument* aDocument);
+  void ScheduleFrameRequestCallbacks(nsIDocument* aDocument);
 
   /**
-   * Add a document for which we have nsIAnimationFrameListeners
-   */
-  void ScheduleAnimationFrameListeners(nsIDocument* aDocument);
-
-  /**
-   * Remove a document for which we should fire a MozBeforePaint event.
+   * Remove a document for which we have nsIFrameRequestCallbacks
    */
-  void RevokeBeforePaintEvent(nsIDocument* aDocument);
-
-  /**
-   * Remove a document for which we have nsIAnimationFrameListeners
-   */
-  void RevokeAnimationFrameListeners(nsIDocument* aDocument);
+  void RevokeFrameRequestCallbacks(nsIDocument* aDocument);
 
   /**
    * Tell the refresh driver that it is done driving refreshes and
    * should stop its timer and forget about its pres context.  This may
    * be called from within a refresh.
    */
   void Disconnect() {
     StopTimer();
@@ -251,18 +241,18 @@ private:
   void UpdateMostRecentRefresh();
   ObserverArray& ArrayFor(mozFlushType aFlushType);
   // Trigger a refresh immediately, if haven't been disconnected or frozen.
   void DoRefresh();
 
   PRInt32 GetRefreshTimerInterval() const;
   PRInt32 GetRefreshTimerType() const;
 
-  bool HaveAnimationFrameListeners() const {
-    return mAnimationFrameListenerDocs.Length() != 0;
+  bool HaveFrameRequestCallbacks() const {
+    return mFrameRequestCallbackDocs.Length() != 0;
   }
 
   nsCOMPtr<nsITimer> mTimer;
   mozilla::TimeStamp mMostRecentRefresh; // only valid when mTimer non-null
   PRInt64 mMostRecentRefreshEpochTime;   // same thing as mMostRecentRefresh,
                                          // but in microseconds since the epoch.
 
   nsPresContext *mPresContext; // weak; pres context passed in constructor
@@ -278,19 +268,17 @@ private:
 
   // separate arrays for each flush type we support
   ObserverArray mObservers[3];
   RequestTable mRequests;
 
   nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
   nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
   // nsTArray on purpose, because we want to be able to swap.
-  nsTArray< nsCOMPtr<nsIDocument> > mBeforePaintTargets;
-  // nsTArray on purpose, because we want to be able to swap.
-  nsTArray<nsIDocument*> mAnimationFrameListenerDocs;
+  nsTArray<nsIDocument*> mFrameRequestCallbackDocs;
 
   // This is the last interval we used for our timer.  May be 0 if we
   // haven't computed a timer interval yet.
   mutable PRInt32 mLastTimerInterval;
 
   // Helper struct for processing image requests
   struct ImageRequestParameters {
       mozilla::TimeStamp ts;
--- a/layout/base/tests/file_bug607529.html
+++ b/layout/base/tests/file_bug607529.html
@@ -2,25 +2,16 @@
 <script>
   window.onerror = function(msg, url, line) {
     var myMsg = JSON.stringify({msg: msg, url: url, line: line, error: true});
     opener.postMessage(myMsg, "*");
   }
   
   var report = false;
   
-  function f() {
-    if (report) {
-      opener.postMessage("eventHappened", "*");
-    }
-    window.mozRequestAnimationFrame();
-  }
-  document.addEventListener("MozBeforePaint", f, false);
-  f();
-
   function g() {
     if (report) {
       opener.postMessage("callbackHappened", "*");
     }
     window.mozRequestAnimationFrame(g);
   }
   g();
 
--- a/layout/base/tests/test_bug569520.html
+++ b/layout/base/tests/test_bug569520.html
@@ -20,42 +20,38 @@ https://bugzilla.mozilla.org/show_bug.cg
 /** Test for Bug 569520 **/
 SimpleTest.waitForExplicitFinish();
 
 var startNow = Date.now();
 var start = window.mozAnimationStartTime;
 var firstListenerTime;
 var secondListenerTime;
 
-function secondListener(ev) {
-  secondListenerTime = ev.timeStamp;
-  window.removeEventListener("MozBeforePaint", secondListener, false);
+function secondListener(t) {
+  secondListenerTime = t;
 
   // They really shouldn't be more than 100ms apart, but we can get weird
   // effects on slow machines.  5 minutes is our test timeout, though.
   ok(Math.abs(startNow - start) <= 5 * 60 * 1000, "Bogus animation start time");
   ok(firstListenerTime >= start, "First listener should fire after start");
   // FIXME: The timer filtering code makes the refresh driver call back in 0ms
   // sometimes!
   ok(secondListenerTime >= firstListenerTime,
      "Second listener should fire after first listener");
   SimpleTest.finish();
 }
                             
-function firstListener(ev) {
-  firstListenerTime = ev.timeStamp;
-  window.removeEventListener("MozBeforePaint", firstListener, false);
-  window.addEventListener("MozBeforePaint", secondListener, false);
-  mozRequestAnimationFrame();
+function firstListener(t) {
+  firstListenerTime = t;
+  mozRequestAnimationFrame(secondListener);
 }
                             
 addLoadEvent(function() {
     setTimeout(function() {
-      window.addEventListener("MozBeforePaint", firstListener, false);
-      mozRequestAnimationFrame();
+      mozRequestAnimationFrame(firstListener);
     }, 100);
   });
 
 
 
 
 </script>
 </pre>
--- a/layout/base/tests/test_bug607529.html
+++ b/layout/base/tests/test_bug607529.html
@@ -19,47 +19,33 @@ https://bugzilla.mozilla.org/show_bug.cg
   SimpleTest.waitForExplicitFinish();
 
   /* General idea: Open a new window (needed because we don't bfcache
      subframes) that uses mozRequestAnimationFrame, navigate it, navigate it
      back, and verify that the animations are still running.  */
 
   var doneOneLoad = false;
 
-  var eventsHappening = false;
-  var callbacksHappening = false;
-
-  function tryFinishTest() {
-    if (eventsHappening && callbacksHappening) {
-      w.close();
-      SimpleTest.finish();
-    }
-  }
-
   /** Test for Bug 607529 **/
   window.onmessage = function(e) {
     isnot(e.data, "notcached", "Should never end up not being cached");
   
     if (e.data == "loaded" && !doneOneLoad) {
       doneOneLoad = true;
       w.location = "data:text/html,<script>window.onload = function() { opener.postMessage('goback', '*'); }</" + "script>";
     }
     else if (e.data == "goback") {
       w.history.back();
     }
     else if (e.data == "revived") {
       w.postMessage("report", "*");
     }
-    else if (e.data == "eventHappened") {
-      eventsHappening = true;
-      tryFinishTest();
-    }
     else if (e.data == "callbackHappened") {
-      callbacksHappening = true;
-      tryFinishTest();
+      w.close();
+      SimpleTest.finish();
     } else {
       var msg = JSON.parse(e.data);
       if (msg.error) {
         window.onerror(msg.msg, msg.url, msg.line);
       }
     }
   };
 
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -132,42 +132,35 @@ nsFileControlFrame::Init(nsIContent* aCo
 }
 
 void
 nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   ENSURE_TRUE(mContent);
 
   // Remove the drag events
-  nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
-  if (dragTarget) {
-    dragTarget->RemoveEventListener(NS_LITERAL_STRING("drop"),
-                                    mMouseListener, false);
-    dragTarget->RemoveEventListener(NS_LITERAL_STRING("dragover"),
-                                    mMouseListener, false);
+  if (mContent) {
+    mContent->RemoveSystemEventListener(NS_LITERAL_STRING("drop"),
+                                        mMouseListener, false);
+    mContent->RemoveSystemEventListener(NS_LITERAL_STRING("dragover"),
+                                        mMouseListener, false);
   }
 
   // remove mMouseListener as a mouse event listener (bug 40533, bug 355931)
-  NS_NAMED_LITERAL_STRING(click, "click");
-
   nsContentUtils::DestroyAnonymousContent(&mCapture);
 
-  nsEventListenerManager* elm = mBrowse->GetListenerManager(false);
-  if (elm) {
-    elm->RemoveEventListenerByType(mMouseListener, click,
-                                   NS_EVENT_FLAG_BUBBLE |
-                                   NS_EVENT_FLAG_SYSTEM_EVENT);
+  if (mBrowse) {
+    mBrowse->RemoveSystemEventListener(NS_LITERAL_STRING("click"),
+                                       mMouseListener, false);
   }
   nsContentUtils::DestroyAnonymousContent(&mBrowse);
 
-  elm = mTextContent->GetListenerManager(false);
-  if (elm) {
-    elm->RemoveEventListenerByType(mMouseListener, click,
-                                   NS_EVENT_FLAG_BUBBLE |
-                                   NS_EVENT_FLAG_SYSTEM_EVENT);
+  if (mTextContent) {
+    mTextContent->RemoveSystemEventListener(NS_LITERAL_STRING("click"),
+                                            mMouseListener, false);
   }
   nsContentUtils::DestroyAnonymousContent(&mTextContent);
 
   mCaptureMouseListener->ForgetFrame();
   mMouseListener->ForgetFrame();
   nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
@@ -260,31 +253,25 @@ nsFileControlFrame::CreateAnonymousConte
 
   textControl->SetTabIndex(-1);
   textControl->SetReadOnly(true);
 
   if (!aElements.AppendElement(mTextContent))
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Register the whole frame as an event listener of drag events
-  nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
-  NS_ENSURE_STATE(dragTarget);
-  dragTarget->AddEventListener(NS_LITERAL_STRING("drop"),
-                               mMouseListener, false);
-  dragTarget->AddEventListener(NS_LITERAL_STRING("dragover"),
-                               mMouseListener, false);
+  mContent->AddSystemEventListener(NS_LITERAL_STRING("drop"),
+                                   mMouseListener, false);
+  mContent->AddSystemEventListener(NS_LITERAL_STRING("dragover"),
+                                   mMouseListener, false);
 
-  NS_NAMED_LITERAL_STRING(click, "click");
-  nsEventListenerManager* manager = mTextContent->GetListenerManager(true);
-  NS_ENSURE_STATE(manager);
   // Register as an event listener of the textbox
   // to open file dialog on mouse click
-  manager->AddEventListenerByType(mMouseListener, click,
-                                  NS_EVENT_FLAG_BUBBLE |
-                                  NS_EVENT_FLAG_SYSTEM_EVENT);
+  mTextContent->AddSystemEventListener(NS_LITERAL_STRING("click"),
+                                       mMouseListener, false);
 
   // Create the browse button
   nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::input, nsnull,
                                                  kNameSpaceID_XHTML,
                                                  nsIDOMNode::ELEMENT_NODE);
   NS_NewHTMLElement(getter_AddRefs(mBrowse), nodeInfo.forget(),
                     dom::NOT_FROM_PARSER);
   if (!mBrowse)
@@ -321,19 +308,18 @@ nsFileControlFrame::CreateAnonymousConte
       mCapture->SetNativeAnonymous();
 
       mCapture->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                         NS_LITERAL_STRING("button"), false);
 
       mCapture->SetAttr(kNameSpaceID_None, nsGkAtoms::value,
                         NS_LITERAL_STRING("capture"), false);
 
-      nsCOMPtr<nsIDOMEventTarget> captureEventTarget =
-        do_QueryInterface(mCapture);
-      captureEventTarget->AddEventListener(click, mCaptureMouseListener, false);
+      mCapture->AddSystemEventListener(NS_LITERAL_STRING("click"),
+                                       mCaptureMouseListener, false);
     }
   }
   nsCOMPtr<nsIDOMHTMLInputElement> fileContent = do_QueryInterface(mContent);
   nsCOMPtr<nsIDOMHTMLInputElement> browseControl = do_QueryInterface(mBrowse);
   if (fileContent && browseControl) {
     PRInt32 tabIndex;
     nsAutoString accessKey;
 
@@ -344,25 +330,20 @@ nsFileControlFrame::CreateAnonymousConte
   }
 
   if (!aElements.AppendElement(mBrowse))
     return NS_ERROR_OUT_OF_MEMORY;
 
   if (mCapture && !aElements.AppendElement(mCapture))
     return NS_ERROR_OUT_OF_MEMORY;
 
-  nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mBrowse);
-  NS_ENSURE_STATE(target);
-  manager = target->GetListenerManager(true);
-  NS_ENSURE_STATE(manager);
   // Register as an event listener of the button
   // to open file dialog on mouse click
-  manager->AddEventListenerByType(mMouseListener, click,
-                                  NS_EVENT_FLAG_BUBBLE |
-                                  NS_EVENT_FLAG_SYSTEM_EVENT);
+  mBrowse->AddSystemEventListener(NS_LITERAL_STRING("click"),
+                                  mMouseListener, false);
 
   SyncAttr(kNameSpaceID_None, nsGkAtoms::size,     SYNC_TEXT);
   SyncDisabledState();
 
   return NS_OK;
 }
 
 void
--- a/layout/ipc/test-ipcbrowser-chrome.js
+++ b/layout/ipc/test-ipcbrowser-chrome.js
@@ -83,16 +83,20 @@ function startAnimatedScrollBy(dx, dy) {
     var start = mozAnimationStartTime;
     var end = start + kDurationMs;
     // |- k| so that we do something in first invocation of nudge()
     var prevNow = start - 20;
     var accumDx = 0, accumDy = 0;
 
     var sentScrollBy = false;
     function nudgeScroll(now) {
+	if (!scrolling) {
+	    // we've been canceled
+	    return;
+	}
         var ddx = dx * (now - prevNow) / kDurationMs;
         var ddy = dy * (now - prevNow) / kDurationMs;
 
         ddx = Math.min(dx - accumDx, ddx);
         ddy = Math.min(dy - accumDy, ddy);
         accumDx += ddx;
         accumDy += ddy;
 
@@ -105,23 +109,19 @@ function startAnimatedScrollBy(dx, dy) {
         }
 
         if (now >= end || (accumDx >= dx && accumDy >= dy)) {
             var fixupDx = Math.max(dx - accumDx, 0);
             var fixupDy = Math.max(dy - accumDy, 0);
             rootView().scrollBy(fixupDx, fixupDy);
 
             scrolling = false;
-            removeEventListener("MozBeforePaint", nudgeScroll, false);
         }
         else {
-            mozRequestAnimationFrame();
+            mozRequestAnimationFrame(nudgeScroll);
         }
 
         prevNow = now;
     }
 
     nudgeScroll(start);
-    addEventListener("MozBeforePaint",
-                     function (e) { nudgeScroll(e.timeStamp); },
-                     false);
-    mozRequestAnimationFrame();
+    mozRequestAnimationFrame(nudgeScroll);
 }
--- a/layout/printing/nsPrintData.cpp
+++ b/layout/printing/nsPrintData.cpp
@@ -129,35 +129,34 @@ nsPrintData::~nsPrintData()
   if (mBrandName) {
     NS_Free(mBrandName);
   }
 }
 
 void nsPrintData::OnStartPrinting()
 {
   if (!mOnStartSent) {
-    DoOnProgressChange(0, 0, true, nsIWebProgressListener::STATE_START|nsIWebProgressListener::STATE_IS_DOCUMENT);
+    DoOnProgressChange(0, 0, true, nsIWebProgressListener::STATE_START|nsIWebProgressListener::STATE_IS_DOCUMENT|nsIWebProgressListener::STATE_IS_NETWORK);
     mOnStartSent = true;
   }
 }
 
 void nsPrintData::OnEndPrinting()
 {
   DoOnProgressChange(100, 100, true, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT);
+  DoOnProgressChange(100, 100, true, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_NETWORK);
 }
 
 void
-nsPrintData::DoOnProgressChange(PRInt32      aProgess,
+nsPrintData::DoOnProgressChange(PRInt32      aProgress,
                                 PRInt32      aMaxProgress,
                                 bool         aDoStartStop,
                                 PRInt32      aFlag)
 {
-  if (aProgess == 0) return;
-
   for (PRInt32 i=0;i<mPrintProgressListeners.Count();i++) {
     nsIWebProgressListener* wpl = mPrintProgressListeners.ObjectAt(i);
-    wpl->OnProgressChange(nsnull, nsnull, aProgess, aMaxProgress, aProgess, aMaxProgress);
+    wpl->OnProgressChange(nsnull, nsnull, aProgress, aMaxProgress, aProgress, aMaxProgress);
     if (aDoStartStop) {
       wpl->OnStateChange(nsnull, nsnull, aFlag, 0);
     }
   }
 }
 
--- a/layout/printing/nsPrintData.h
+++ b/layout/printing/nsPrintData.h
@@ -80,17 +80,17 @@ public:
 
 
   nsPrintData(ePrintDataType aType);
   ~nsPrintData(); // non-virtual
 
   // Listener Helper Methods
   void OnEndPrinting();
   void OnStartPrinting();
-  void DoOnProgressChange(PRInt32      aProgess,
+  void DoOnProgressChange(PRInt32      aProgress,
                           PRInt32      aMaxProgress,
                           bool         aDoStartStop,
                           PRInt32      aFlag);
 
 
   ePrintDataType               mType;            // the type of data this is (Printing or Print Preview)
   nsRefPtr<nsDeviceContext>   mPrintDC;
   FILE                        *mDebugFilePtr;    // a file where information can go to when printing
--- a/layout/reftests/svg/smil/transform/scale-1-ref.svg
+++ b/layout/reftests/svg/smil/transform/scale-1-ref.svg
@@ -1,38 +1,43 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink">
   <defs>
-    <linearGradient id="grad">
-      <stop offset="5%" stop-color="#F66"/>
-      <stop offset="95%" stop-color="#FF6"/>
-    </linearGradient>
-    <circle fill="url(#grad)" stroke="black" stroke-width="1" cx="0" cy="0"
-      r="20" id="circle"/>
+    <g id="smiley">
+      <circle fill="yellow" stroke="black" stroke-width="1" cx="0" cy="0"
+        r="20"/>
+      <circle fill="white" stroke="black" stroke-width="1" cx="-7" cy="-7"
+        r="7"/>
+      <circle fill="white" stroke="black" stroke-width="1" cx="7" cy="-7"
+        r="7"/>
+      <circle cx="-5" cy="-7" r="2"/>
+      <circle cx="5" cy="-7" r="2"/>
+      <path d="m-11 7a13,13 0 0,0 22,0" fill="none" stroke="black"/>
+    </g>
   </defs>
   <g transform="translate(50 50)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(150 50)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(250 50)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(50 150)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(150 150)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(250 150)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(50 250)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(150 250)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
   <g transform="translate(250 250)">
-    <use xlink:href="#circle" transform="scale(2)"/>
+    <use xlink:href="#smiley" transform="scale(2)"/>
   </g>
 </svg>
--- a/layout/reftests/svg/smil/transform/scale-1.svg
+++ b/layout/reftests/svg/smil/transform/scale-1.svg
@@ -1,46 +1,51 @@
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      class="reftest-wait"
      onload="setTimeAndSnapshot(1, true)">
   <script xlink:href="../smil-util.js" type="text/javascript"/>
   <defs>
-    <linearGradient id="grad">
-      <stop offset="5%" stop-color="#F66"/>
-      <stop offset="95%" stop-color="#FF6"/>
-    </linearGradient>
-    <circle fill="url(#grad)" stroke="black" stroke-width="1" cx="0" cy="0"
-      r="20" id="circle"/>
+    <g id="smiley">
+      <circle fill="yellow" stroke="black" stroke-width="1" cx="0" cy="0"
+        r="20"/>
+      <circle fill="white" stroke="black" stroke-width="1" cx="-7" cy="-7"
+        r="7"/>
+      <circle fill="white" stroke="black" stroke-width="1" cx="7" cy="-7"
+        r="7"/>
+      <circle cx="-5" cy="-7" r="2"/>
+      <circle cx="5" cy="-7" r="2"/>
+      <path d="m-11 7a13,13 0 0,0 22,0" fill="none" stroke="black"/>
+    </g>
   </defs>
   <!-- to animation 
 
        This should interpolate from 0 (not 1) to 4 to match the behaviour
        required by the SVGT1.2 test suite and Opera's behaviour.
   -->
   <g transform="translate(50 50)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform"
         type="scale" to="4" dur="2s" fill="freeze"/>
     </use>
   </g>
   <!-- from-to animation -->
   <g transform="translate(150 50)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform"
         type="scale" from="-5" to="9" dur="2s" fill="freeze"/>
     </use>
   </g>
   <!-- negative to-animation
 
        Should go from 0 to -4 over 2s, therefore at t=1s, the scale factor
        should be -2, so we add a rotation animation to correct the gradient
    -->
   <g transform="translate(250 50)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform"
         type="scale" to="-4" dur="2s" fill="freeze"/>
       <animateTransform attributeName="transform"
         type="rotate" from="0" to="360" dur="2s" fill="freeze" additive="sum"/>
     </use>
   </g>
   <!-- by animation
 
@@ -58,51 +63,51 @@
        it's 0. This is inconsistent with the definition of addition for
        animateTransform (post-multiplication of matrices) but it is the
        behaviour required by SVGT1.2 test suite and used by Opera.
 
        The following animation should go from 0 to 4, over 2s so at t=1s, the
        scale factor should be 2.
    -->
   <g transform="translate(50 150)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform"
         type="scale" by="4" dur="2s" fill="freeze"/>
     </use>
   </g>
   <!-- by animation #2 -->
   <g transform="translate(150 150)">
-    <use xlink:href="#circle" transform="scale(4)">
+    <use xlink:href="#smiley" transform="scale(4)">
       <animateTransform attributeName="transform"
         type="scale" by="1" dur="2s" fill="freeze" additive="sum"/>
     </use>
   </g>
   <!-- from-by animation -->
   <g transform="translate(250 150)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform"
         type="scale" from="2" by="0" dur="2s" fill="freeze"/>
     </use>
   </g>
   <!-- values animation -->
   <g transform="translate(50 250)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform"
         type="scale" values="0; 10; 2; 5; -1" dur="2s" fill="freeze"/>
     </use>
   </g>
   <!-- repetition -->
   <g transform="translate(150 250)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform" type="scale" from="0"
       to="0.6" dur="0.3s" repeatCount="4" accumulate="sum"
       fill="freeze"/>
     </use>
   </g>
   <!-- repeated to-animation (should NOT accumulate) -->
   <g transform="translate(250 250)">
-    <use xlink:href="#circle">
+    <use xlink:href="#smiley">
       <animateTransform attributeName="transform" type="scale"
       to="6" dur="0.75" repeatCount="2" accumulate="sum"
       fill="freeze"/>
     </use>
   </g>
 </svg>
--- a/layout/style/test/test_value_cloning.html
+++ b/layout/style/test/test_value_cloning.html
@@ -150,19 +150,27 @@ function iframe_loaded(event)
     var end_ser =
       ifdoc.styleSheets[0].cssRules[3*idx+3].style.getPropertyValue(current_item.prop);
     is(end_ser, start_ser[idx],
        "serialization should match when cloning " +
        current_item.prop + ": " + current_item.value);
 
     if (!("backend_only" in info)) {
       var end_compute = get_computed_value(test_cs[idx], current_item.prop);
-      is(end_compute, start_compute[idx],
-	 "computed values should match when cloning " +
-	 current_item.prop + ": " + current_item.value);
+      // Output computed values only when the test failed.
+      // Computed values may be very long.
+      if (end_compute == start_compute[idx]) {
+        ok(true,
+           "computed values should match when cloning " +
+           current_item.prop + ": " + current_item.value);
+      } else {
+        is(end_compute, start_compute[idx],
+           "computed values should match when cloning " +
+           current_item.prop + ": " + current_item.value);
+      }
     }
   }
 
   SimpleTest.finish();
 }
 
 </script>
 </pre>
--- a/layout/xul/base/src/nsXULTooltipListener.cpp
+++ b/layout/xul/base/src/nsXULTooltipListener.cpp
@@ -300,34 +300,35 @@ bool nsXULTooltipListener::sShowTooltips
 PRUint32 nsXULTooltipListener::sTooltipListenerCount = 0;
 
 nsresult
 nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode)
 {
   if (!aNode)
     return NS_ERROR_NULL_POINTER;
 
-  nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
-  evtTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false);
-  evtTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this, false);
-  evtTarget->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true);
-  
+  aNode->AddSystemEventListener(NS_LITERAL_STRING("mouseout"), this,
+                                false, false);
+  aNode->AddSystemEventListener(NS_LITERAL_STRING("mousemove"), this,
+                                false, false);
+  aNode->AddSystemEventListener(NS_LITERAL_STRING("dragstart"), this,
+                                true, false);
+
   return NS_OK;
 }
 
 nsresult
 nsXULTooltipListener::RemoveTooltipSupport(nsIContent* aNode)
 {
   if (!aNode)
     return NS_ERROR_NULL_POINTER;
 
-  nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
-  evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false);
-  evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, false);
-  evtTarget->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, true);
+  aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mouseout"), this, false);
+  aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"), this, false);
+  aNode->RemoveSystemEventListener(NS_LITERAL_STRING("dragstart"), this, true);
 
   return NS_OK;
 }
 
 #ifdef MOZ_XUL
 void
 nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent)
 {
@@ -412,31 +413,34 @@ nsXULTooltipListener::ShowTooltip()
       mTargetNode = nsnull;
 
       nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
       if (!currentTooltip)
         return NS_OK;
 
       // listen for popuphidden on the tooltip node, so that we can
       // be sure DestroyPopup is called even if someone else closes the tooltip
-      nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(currentTooltip));
-      evtTarget->AddEventListener(NS_LITERAL_STRING("popuphiding"), 
-                                  this, false);
+      currentTooltip->AddSystemEventListener(NS_LITERAL_STRING("popuphiding"), 
+                                             this, false, false);
 
       // listen for mousedown, mouseup, keydown, and DOMMouseScroll events at document level
       nsIDocument* doc = sourceNode->GetDocument();
       if (doc) {
-        evtTarget = do_QueryInterface(doc);
-        evtTarget->AddEventListener(NS_LITERAL_STRING("DOMMouseScroll"), 
+        // Probably, we should listen to untrusted events for hiding tooltips
+        // on content since tooltips might disturb something of web
+        // applications.  If we don't specify the aWantsUntrusted of
+        // AddSystemEventListener(), the event target sets it to TRUE if the
+        // target is in content.
+        doc->AddSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"),
                                     this, true);
-        evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), 
+        doc->AddSystemEventListener(NS_LITERAL_STRING("mousedown"),
                                     this, true);
-        evtTarget->AddEventListener(NS_LITERAL_STRING("mouseup"), 
-                                    this, true);                                    
-        evtTarget->AddEventListener(NS_LITERAL_STRING("keydown"), 
+        doc->AddSystemEventListener(NS_LITERAL_STRING("mouseup"),
+                                    this, true);
+        doc->AddSystemEventListener(NS_LITERAL_STRING("keydown"),
                                     this, true);
       }
       mSourceNode = nsnull;
     }
   }
 
   return NS_OK;
 }
@@ -655,21 +659,22 @@ nsXULTooltipListener::DestroyTooltip()
 {
   nsCOMPtr<nsIDOMEventListener> kungFuDeathGrip(this);
   nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip);
   if (currentTooltip) {
     // clear out the tooltip node on the document
     nsCOMPtr<nsIDocument> doc = currentTooltip->GetDocument();
     if (doc) {
       // remove the mousedown and keydown listener from document
-      nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(doc));
-      evtTarget->RemoveEventListener(NS_LITERAL_STRING("DOMMouseScroll"), this, true);
-      evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true);
-      evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, true);
-      evtTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
+      doc->RemoveSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"), this,
+                                     true);
+      doc->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), this,
+                                     true);
+      doc->RemoveSystemEventListener(NS_LITERAL_STRING("mouseup"), this, true);
+      doc->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), this, true);
     }
 
     // remove the popuphidden listener from tooltip
     nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(currentTooltip));
 
     // release tooltip before removing listener to prevent our destructor from
     // being called recursively (bug 120863)
     mCurrentTooltip = nsnull;
deleted file mode 100644
--- a/layout/xul/base/src/tree/src/nsITreeImageListener.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* ***** 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 mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dave Hyatt <hyatt@mozilla.org> (Original Author)
- *   Jan Varga <varga@ku.sk>
- *   Scott Johnson <sjohnson@mozilla.com>, Mozilla Corporation
- *
- * 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 ***** */
-
-#ifndef nsITreeImageListener_h__
-#define nsITreeImageListener_h__
-
-// The interface for our image listener.
-// {90586540-2D50-403e-8DCE-981CAA778444}
-#define NS_ITREEIMAGELISTENER_IID \
-{ 0x90586540, 0x2d50, 0x403e, { 0x8d, 0xce, 0x98, 0x1c, 0xaa, 0x77, 0x84, 0x44 } }
-
-class nsITreeImageListener : public nsISupports
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITREEIMAGELISTENER_IID)
-
-  NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol) = 0;
-
-  /**
-   * Clear the internal frame pointer to prevent dereferencing an object
-   * that no longer exists.
-   */
-  NS_IMETHOD ClearFrame() = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsITreeImageListener, NS_ITREEIMAGELISTENER_IID)
-
-#endif
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -2152,19 +2152,21 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIn
     // We can only call GetAnimated if we're decoded
     if (*aResult && (status & imgIRequest::STATUS_DECODE_COMPLETE))
       (*aResult)->GetAnimated(&animated);
 
     if ((!(status & imgIRequest::STATUS_LOAD_COMPLETE)) || animated) {
       // We either aren't done loading, or we're animating. Add our row as a listener for invalidations.
       nsCOMPtr<imgIDecoderObserver> obs;
       imgReq->GetDecoderObserver(getter_AddRefs(obs));
-      nsCOMPtr<nsITreeImageListener> listener(do_QueryInterface(obs));
-      if (listener)
-        listener->AddCell(aRowIndex, aCol);
+
+      if (obs) {
+        static_cast<nsTreeImageListener*> (obs.get())->AddCell(aRowIndex, aCol);
+      }
+
       return NS_OK;
     }
   }
 
   if (!*aResult) {
     // Create a new nsTreeImageListener object and pass it our row and column
     // information.
     nsTreeImageListener* listener = new nsTreeImageListener(this);
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
@@ -58,17 +58,16 @@
 #include "nsTreeColumns.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "imgIRequest.h"
 #include "imgIDecoderObserver.h"
 #include "nsScrollbarFrame.h"
 #include "nsThreadUtils.h"
 #include "mozilla/LookAndFeel.h"
-#include "nsITreeImageListener.h"
 
 class nsOverflowChecker;
 class nsTreeImageListener;
 
 // An entry in the tree's image cache
 struct nsTreeImageCacheEntry
 {
   nsTreeImageCacheEntry() {}
--- a/layout/xul/base/src/tree/src/nsTreeImageListener.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeImageListener.cpp
@@ -37,17 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsTreeImageListener.h"
 #include "nsITreeBoxObject.h"
 #include "imgIRequest.h"
 #include "imgIContainer.h"
 
-NS_IMPL_ISUPPORTS3(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver, nsITreeImageListener)
+NS_IMPL_ISUPPORTS2(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver)
 
 nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame)
   : mTreeFrame(aTreeFrame),
     mInvalidationSuppressed(true),
     mInvalidationArea(nsnull)
 {
 }
 
@@ -87,17 +87,17 @@ NS_IMETHODIMP nsTreeImageListener::OnDat
 NS_IMETHODIMP nsTreeImageListener::FrameChanged(imgIContainer *aContainer,
                                                 const nsIntRect *aDirtyRect)
 {
   Invalidate();
   return NS_OK;
 }
 
 
-NS_IMETHODIMP
+void
 nsTreeImageListener::AddCell(PRInt32 aIndex, nsITreeColumn* aCol)
 {
   if (!mInvalidationArea) {
     mInvalidationArea = new InvalidationArea(aCol);
     mInvalidationArea->AddRow(aIndex);
   }
   else {
     InvalidationArea* currArea;
@@ -109,18 +109,16 @@ nsTreeImageListener::AddCell(PRInt32 aIn
     }
     if (!currArea) {
       currArea = new InvalidationArea(aCol);
       currArea->SetNext(mInvalidationArea);
       mInvalidationArea = currArea;
       mInvalidationArea->AddRow(aIndex);
     }
   }
-
-  return NS_OK;
 }
 
 
 void
 nsTreeImageListener::Invalidate()
 {
   if (!mInvalidationSuppressed) {
     for (InvalidationArea* currArea = mInvalidationArea; currArea;
--- a/layout/xul/base/src/tree/src/nsTreeImageListener.h
+++ b/layout/xul/base/src/tree/src/nsTreeImageListener.h
@@ -40,43 +40,42 @@
 #ifndef nsTreeImageListener_h__
 #define nsTreeImageListener_h__
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsITreeColumns.h"
 #include "nsStubImageDecoderObserver.h"
 #include "nsTreeBodyFrame.h"
-#include "nsITreeImageListener.h"
 
 // This class handles image load observation.
-class nsTreeImageListener : public nsStubImageDecoderObserver, public nsITreeImageListener
+class nsTreeImageListener : public nsStubImageDecoderObserver
 {
 public:
   nsTreeImageListener(nsTreeBodyFrame *aTreeFrame);
   ~nsTreeImageListener();
 
   NS_DECL_ISUPPORTS
   // imgIDecoderObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
   NS_IMETHOD OnImageIsAnimated(imgIRequest* aRequest);
   NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame,
                              const nsIntRect *aRect);
   // imgIContainerObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *aDirtyRect);
 
-  NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol);
   NS_IMETHOD ClearFrame();
 
   friend class nsTreeBodyFrame;
 
 protected:
   void UnsuppressInvalidation() { mInvalidationSuppressed = false; }
   void Invalidate();
+  void AddCell(PRInt32 aIndex, nsITreeColumn* aCol);
 
 private:
   nsTreeBodyFrame* mTreeFrame;
 
   // A guard that prevents us from recursive painting.
   bool mInvalidationSuppressed;
 
   class InvalidationArea {
--- a/mobile/xul/chrome/content/AnimatedZoom.js
+++ b/mobile/xul/chrome/content/AnimatedZoom.js
@@ -127,17 +127,17 @@ const AnimatedZoom = {
     window.dispatchEvent(event);
     browser._updateCSSViewport();
   },
 
   isZooming: function isZooming() {
     return this.beginTime != null;
   },
 
-  onBeforePaint: function(aTimeStamp) {
+  sample: function(aTimeStamp) {
     try {
       let tdiff = aTimeStamp - this.beginTime;
       let counter = tdiff / this.animationDuration;
       if (counter < 1) {
         // update browser to interpolated rectangle
         let rect = this.zoomFrom.blend(this.zoomTo, counter);
         this.updateTo(rect);
         mozRequestAnimationFrame(this);
--- a/mobile/xul/chrome/content/Util.js
+++ b/mobile/xul/chrome/content/Util.js
@@ -171,16 +171,28 @@ let Util = {
 
     // Act according to user prefs if tablet mode has been
     // explicitly disabled or enabled.
     if (tabletPref == 0)
       return this._isTablet = false;
     else if (tabletPref == 1)
       return this._isTablet = true;
 
+#ifdef ANDROID
+    // Disable tablet mode on non-honeycomb devices because of theme bugs (bug 705026)
+    let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
+    let shellVersion = sysInfo.get("shellVersion") || "";
+    let matches = shellVersion.match(/\((\d+)\)$/);
+    if (matches) {
+      let sdkVersion = parseInt(matches[1]);
+      if (sdkVersion < 11 || sdkVersion > 13)
+        return this._isTablet = false;
+    }
+#endif
+
     let dpi = this.displayDPI;
     if (dpi <= 96)
       return this._isTablet = (window.innerWidth > 1024);
 
     // See the tablet_panel_minwidth from mobile/themes/core/defines.inc
     let tablet_panel_minwidth = 124;
     let dpmm = 25.4 * window.innerWidth / dpi;
     return this._isTablet = (dpmm >= tablet_panel_minwidth);
--- a/mobile/xul/chrome/content/input.js
+++ b/mobile/xul/chrome/content/input.js
@@ -170,17 +170,17 @@ MouseModule.prototype = {
             aEvent.preventDefault();
             aEvent.target.removeEventListener("click", this, true);
             break;
         }
       }
     }
   },
 
-  onBeforePaint: function onBeforePaint(aTimeStamp) {
+  sample: function sample(aTimeStamp) {
     this._waitingForPaint = false;
   },
 
   /**
    * This gets invoked by the input handler if another module grabs.  We should
    * reset our state or something here.  This is probably doing the wrong thing
    * in its current form.
    */
@@ -884,17 +884,17 @@ KineticController.prototype = {
       return v0 * Math.exp(-t / c) * -c + a * t * t + v0 * c;
     }
 
     this._calcV = function(v0, a, t) {
       return v0 * Math.exp(-t / c) + 2 * a * t;
     }
 
     let callback = {
-      onBeforePaint: function kineticHandleEvent(timeStamp) {
+      sample: function kineticHandleEvent(timeStamp) {
         // Someone called end() on us between timer intervals
         // or we are paused.
         if (!self.isActive() || self._paused)
           return;
 
         // To make animation end fast enough but to keep smoothness, average the ideal
         // time frame (smooth animation) with the actual time lapse (end fast enough).
         // Animation will never take longer than 2 times the ideal length of time.
--- a/mobile/xul/themes/core/jar.mn
+++ b/mobile/xul/themes/core/jar.mn
@@ -141,17 +141,17 @@ chrome.jar:
   skin/images/handle-end.png                (images/handle-end.png)
   skin/images/homescreen-blank-hdpi.png     (images/homescreen-blank-hdpi.png)
   skin/images/homescreen-default-hdpi.png   (images/homescreen-default-hdpi.png)
   skin/images/aurora-lightbox-bg.jpg        (images/aurora-lightbox-bg.jpg)
   skin/images/aurora-lightbox-logo.png      (images/aurora-lightbox-logo.png)
   skin/images/aurora-lightbox-close.png     (images/aurora-lightbox-close.png)
 
 chrome.jar:
-% skin browser classic/1.0 %skin/gingerbread/ os=Android osversion=2.3 osversion=2.3.3 osversion=2.3.4 osversion=2.3.5 osversion=2.3.6 osversion=2.3.7
+% skin browser classic/1.0 %skin/gingerbread/ os=Android osversion=2.3 osversion=2.3.3 osversion=2.3.4 osversion=2.3.5 osversion=2.3.6 osversion=2.3.7 osversion=2.3.8 osversion>=4.0
 % skin browser gingerbread/1.0 %skin/gingerbread/
   skin/gingerbread/aboutPage.css                        (aboutPage.css)
   skin/gingerbread/about.css                            (about.css)
   skin/gingerbread/aboutHome.css                        (aboutHome.css)
 * skin/gingerbread/browser.css                          (gingerbread/browser.css)
 * skin/gingerbread/content.css                          (gingerbread/content.css)
   skin/gingerbread/config.css                           (config.css)
 * skin/gingerbread/forms.css                            (gingerbread/forms.css)
@@ -280,17 +280,17 @@ chrome.jar:
   skin/gingerbread/images/errorpage-larry-black.png     (images/errorpage-larry-black.png)
   skin/gingerbread/images/homescreen-blank-hdpi.png     (images/homescreen-blank-hdpi.png)
   skin/gingerbread/images/homescreen-default-hdpi.png   (images/homescreen-default-hdpi.png)
   skin/gingerbread/images/aurora-lightbox-bg.jpg        (images/aurora-lightbox-bg.jpg)
   skin/gingerbread/images/aurora-lightbox-logo.png      (images/aurora-lightbox-logo.png)
   skin/gingerbread/images/aurora-lightbox-close.png     (images/aurora-lightbox-close.png)
 
 chrome.jar:
-% skin browser classic/1.0 %skin/honeycomb/ os=Android osversion>=3.0
+% skin browser classic/1.0 %skin/honeycomb/ os=Android osversion=3.0 osversion=3.1 osversion=3.2 osversion=3.2.1 osversion=3.2.2 osversion=3.2.3 osversion=3.2.4 osversion=3.2.5 osversion=3.2.6 osversion=3.2.7 osversion=3.2.8 osversion=3.2.9
 % skin browser honeycomb/1.0 %skin/honeycomb/
   skin/honeycomb/aboutPage.css                        (aboutPage.css)
   skin/honeycomb/about.css                            (about.css)
   skin/honeycomb/aboutHome.css                        (aboutHome.css)
 * skin/honeycomb/browser.css                          (honeycomb/browser.css)
 * skin/honeycomb/content.css                          (content.css)
   skin/honeycomb/config.css                           (config.css)
 * skin/honeycomb/forms.css                            (honeycomb/forms.css)
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -623,18 +623,16 @@ pref("dom.event.contextmenu.enabled",   
 pref("javascript.enabled",                  true);
 pref("javascript.options.strict",           false);
 #ifdef DEBUG
 pref("javascript.options.strict.debug",     true);
 #endif
 pref("javascript.options.relimit",          true);
 pref("javascript.options.methodjit.content", true);
 pref("javascript.options.methodjit.chrome",  true);
-pref("javascript.options.jitprofiling.content", true);
-pref("javascript.options.jitprofiling.chrome",  true);
 pref("javascript.options.pccounts.content", false);
 pref("javascript.options.pccounts.chrome",  false);
 pref("javascript.options.methodjit_always", false);
 pref("javascript.options.jit_hardening", true);
 pref("javascript.options.typeinference", true);
 // This preference limits the memory usage of javascript.
 // If you want to change these values for your device,
 // please find Bug 417052 comment 17 and Bug 456721
--- a/parser/html/nsHtml5Highlighter.cpp
+++ b/parser/html/nsHtml5Highlighter.cpp
@@ -329,16 +329,17 @@ nsHtml5Highlighter::Transition(PRInt32 a
           break;
         default:
           FinishTag();
           break;
       }
       break;
       // most comment states are omitted, because they don't matter to
       // highlighting
+    case NS_HTML5TOKENIZER_COMMENT_START:
     case NS_HTML5TOKENIZER_COMMENT_END:
     case NS_HTML5TOKENIZER_COMMENT_END_BANG:
     case NS_HTML5TOKENIZER_COMMENT_START_DASH:
     case NS_HTML5TOKENIZER_BOGUS_COMMENT:
     case NS_HTML5TOKENIZER_BOGUS_COMMENT_HYPHEN:
       if (aState == NS_HTML5TOKENIZER_DATA) {
         AddClass(sComment);
         FinishTag();
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug704667-1-ref.html
@@ -0,0 +1,1 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://gre-resources/viewsource.css"></head><body id="viewsource" class="wrap"><span class="error comment">&lt;!--&gt;</span> <span class="error comment">&lt;!X&gt;</span>
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug704667-1.html
@@ -0,0 +1,1 @@
+<!--> <!X>
--- a/parser/htmlparser/tests/reftest/reftest.list
+++ b/parser/htmlparser/tests/reftest/reftest.list
@@ -11,8 +11,9 @@ fails-if(/^Windows\x20NT\x206\.1/.test(h
 == bug659763-3.html bug659763-3-ref.html
 == bug659763-4.html bug659763-4-ref.html
 == bug659763-5.html bug659763-5-ref.html
 == bug659763-6.html bug659763-6-ref.html
 == view-source:bug673094-1.html view-source:bug673094-1-ref.html
 == bug696651-1.html bug696651-1-ref.html
 == bug696651-2.html bug696651-2-ref.html
 == view-source:bug700260-1.html view-source:bug700260-1-ref.html
+== view-source:bug704667-1.html bug704667-1-ref.html
--- a/services/sync/modules/engines/bookmarks.js
+++ b/services/sync/modules/engines/bookmarks.js
@@ -1045,21 +1045,16 @@ BookmarksStore.prototype = {
     case PlacesUtils.bookmarks.TYPE_SEPARATOR:
       record = new BookmarkSeparator(collection, id);
       if (parent > 0)
         record.parentName = PlacesUtils.bookmarks.getItemTitle(parent);
       // Create a positioning identifier for the separator, used by _mapDupe
       record.pos = PlacesUtils.bookmarks.getItemIndex(placeId);
       break;
 
-    case PlacesUtils.bookmarks.TYPE_DYNAMIC_CONTAINER:
-      record = new PlacesItem(collection, id);
-      this._log.warn("Don't know how to serialize dynamic containers yet");
-      break;
-
     default:
       record = new PlacesItem(collection, id);
       this._log.warn("Unknown item type, cannot serialize: " +
                      PlacesUtils.bookmarks.getItemType(placeId));
     }
 
     record.parentid = this.GUIDForId(parent);
     record.sortindex = this._calculateIndex(record);
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -214,17 +214,17 @@ class XPCShellTests(object):
     """
       Load the root head.js file as the first file in our test path, before other head, test, and tail files.
       On a remote system, we overload this to add additional command line arguments, so this gets overloaded.
     """
     # - NOTE: if you rename/add any of the constants set here, update
     #   do_load_child_test_harness() in head.js
     if not self.appPath:
         self.appPath = self.xrePath
-    self.xpcsCmd = [self.xpcshell, '-g', self.xrePath, '-a', self.appPath, '-r', self.httpdManifest, '-j', '-s'] + \
+    self.xpcsCmd = [self.xpcshell, '-g', self.xrePath, '-a', self.appPath, '-r', self.httpdManifest, '-m', '-n', '-s'] + \
         ['-e', 'const _HTTPD_JS_PATH = "%s";' % self.httpdJSPath,
          '-e', 'const _HEAD_JS_PATH = "%s";' % self.headJSPath,
          '-f', os.path.join(self.testharnessdir, 'head.js')]
 
     if self.debuggerInfo:
       self.xpcsCmd = [self.debuggerInfo["path"]] + self.debuggerInfo["args"] + self.xpcsCmd
 
   def buildTestPath(self):
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -627,16 +627,22 @@ Database::InitSchema(bool* aDatabaseMigr
         rv = MigrateV11Up();
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       // Firefox 4 uses schema version 11.
 
       // Firefox 8 uses schema version 12.
 
+      if (currentSchemaVersion < 13) {
+        rv = MigrateV13Up();
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+      // Firefox 11 uses schema version 13.
+
       // Schema Upgrades must add migration code here.
     }
   }
   else {
     // This is a new database, so we have to create all the tables and indices.
 
     // moz_places.
     rv = mMainConn->ExecuteSimpleSQL(CREATE_MOZ_PLACES);
@@ -1252,16 +1258,40 @@ Database::MigrateV11Up()
 
   // We need to update our guids before we do any real database work.
   rv = CheckAndUpdateGUIDs();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
+nsresult
+Database::MigrateV13Up()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // Dynamic containers are no more supported.
+
+  // For existing profiles, we may not have a moz_bookmarks.guid column
+  nsCOMPtr<mozIStorageAsyncStatement> deleteDynContainersStmt;
+  nsresult rv = mMainConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
+      "DELETE FROM moz_bookmarks WHERE type = :item_type"),
+    getter_AddRefs(deleteDynContainersStmt));
+  rv = deleteDynContainersStmt->BindInt32ByName(
+    NS_LITERAL_CSTRING("item_type"),
+    nsINavBookmarksService::TYPE_DYNAMIC_CONTAINER
+  );
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<mozIStoragePendingStatement> ps;
+  rv = deleteDynContainersStmt->ExecuteAsync(nsnull, getter_AddRefs(ps));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
 void
 Database::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mShuttingDown);
 
   mMainThreadStatements.FinalizeStatements();
   mMainThreadAsyncStatements.FinalizeStatements();
--- a/toolkit/components/places/Database.h
+++ b/toolkit/components/places/Database.h
@@ -42,17 +42,17 @@
 #include "nsWeakReference.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObserver.h"
 #include "mozilla/storage.h"
 #include "mozilla/storage/StatementCache.h"
 
 // This is the schema version, update it at any schema change and add a
 // corresponding migrateVxx method below.
-#define DATABASE_SCHEMA_VERSION 12
+#define DATABASE_SCHEMA_VERSION 13
 
 // Fired after Places inited.
 #define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
 // Fired when initialization fails due to a locked database.
 #define TOPIC_DATABASE_LOCKED "places-database-locked"
 // This topic is received when the profile is about to be lost.  Places does
 // initial shutdown work and notifies TOPIC_PLACES_SHUTDOWN to all listeners.
 // Any shutdown work that requires the Places APIs should happen here.
@@ -284,16 +284,17 @@ protected:
    * Helpers used by schema upgrades.
    */
   nsresult MigrateV7Up();
   nsresult MigrateV8Up();
   nsresult MigrateV9Up();
   nsresult MigrateV10Up();
   nsresult MigrateV11Up();
   nsresult CheckAndUpdateGUIDs();
+  nsresult MigrateV13Up();
 
 private:
   ~Database();
 
   /**
    * Singleton getter, invoked by class instantiation.
    *
    * Note: does AddRef.
--- a/toolkit/components/places/Makefile.in
+++ b/toolkit/components/places/Makefile.in
@@ -57,17 +57,16 @@ MODULE_NAME = nsPlacesModule
 IS_COMPONENT = 1
 
 XPIDLSRCS += \
   mozIAsyncHistory.idl \
   mozIAsyncFavicons.idl \
   mozIPlacesAutoComplete.idl \
   nsIAnnotationService.idl \
   nsIBrowserHistory.idl \
-  nsIDynamicContainer.idl \
   nsIFaviconService.idl \
   nsILivemarkService.idl \
   nsINavBookmarksService.idl \
   nsIPlacesImportExportService.idl \
   nsITaggingService.idl  \
   nsPIPlacesDatabase.idl \
   nsPIPlacesHistoryListenersNotifier.idl \
   $(NULL)
--- a/toolkit/components/places/PlacesDBUtils.jsm
+++ b/toolkit/components/places/PlacesDBUtils.jsm
@@ -482,31 +482,30 @@ let PlacesDBUtils = {
         "SELECT id FROM moz_bookmarks b " +
         "WHERE keyword_id NOT NULL " +
           "AND NOT EXISTS " +
             "(SELECT id FROM moz_keywords WHERE id = b.keyword_id LIMIT 1) " +
       ")");
     cleanupStatements.push(fixInvalidKeywords);
 
     // D.6 fix wrong item types
-    //     Folders, separators and dynamic containers should not have an fk.
+    //     Folders and separators should not have an fk.
     //     If they have a valid fk convert them to bookmarks. Later in D.9 we
     //     will move eventual children to unsorted bookmarks.
     let fixBookmarksAsFolders = DBConn.createAsyncStatement(
       "UPDATE moz_bookmarks SET type = :bookmark_type WHERE id NOT IN ( " +
         "SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
       ") AND id IN ( " +
         "SELECT id FROM moz_bookmarks b " +
-        "WHERE type IN (:folder_type, :separator_type, :dynamic_type) " +
+        "WHERE type IN (:folder_type, :separator_type) " +
           "AND fk NOTNULL " +
       ")");
     fixBookmarksAsFolders.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
     fixBookmarksAsFolders.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
     fixBookmarksAsFolders.params["separator_type"] = PlacesUtils.bookmarks.TYPE_SEPARATOR;
-    fixBookmarksAsFolders.params["dynamic_type"] = PlacesUtils.bookmarks.TYPE_DYNAMIC_CONTAINER;
     cleanupStatements.push(fixBookmarksAsFolders);
 
     // D.7 fix wrong item types
     //     Bookmarks should have an fk, if they don't have any, convert them to
     //     folders.
     let fixFoldersAsBookmarks = DBConn.createAsyncStatement(
       "UPDATE moz_bookmarks SET type = :folder_type WHERE id NOT IN ( " +
         "SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
@@ -514,48 +513,32 @@ let PlacesDBUtils = {
         "SELECT id FROM moz_bookmarks b " +
         "WHERE type = :bookmark_type " +
           "AND fk IS NULL " +
       ")");
     fixFoldersAsBookmarks.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
     fixFoldersAsBookmarks.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
     cleanupStatements.push(fixFoldersAsBookmarks);
 
-    // D.8 fix wrong item types
-    //     Dynamic containers should have a folder_type, if they don't have any
-    //     convert them to folders.
-    let fixFoldersAsDynamic = DBConn.createAsyncStatement(
-      "UPDATE moz_bookmarks SET type = :folder_type WHERE id NOT IN ( " +
-        "SELECT folder_id FROM moz_bookmarks_roots " + // skip roots
-      ") AND id IN ( " +
-        "SELECT id FROM moz_bookmarks b " +
-        "WHERE type = :dynamic_type " +
-          "AND folder_type IS NULL " +
-      ")");
-    fixFoldersAsDynamic.params["dynamic_type"] = PlacesUtils.bookmarks.TYPE_DYNAMIC_CONTAINER;
-    fixFoldersAsDynamic.params["folder_type"] = PlacesUtils.bookmarks.TYPE_FOLDER;
-    cleanupStatements.push(fixFoldersAsDynamic);
-
     // D.9 fix wrong parents
-    //     Items cannot have dynamic containers, separators or other bookmarks
+    //     Items cannot have separators or other bookmarks
     //     as parent, if they have bad parent move them to unsorted bookmarks.
     let fixInvalidParents = DBConn.createAsyncStatement(
       "UPDATE moz_bookmarks SET parent = :unsorted_folder WHERE id NOT IN ( " +
         "SELECT folder_id FROM moz_bookmarks_roots " +  // skip roots
       ") AND id IN ( " +
         "SELECT id FROM moz_bookmarks b " +
         "WHERE EXISTS " +
           "(SELECT id FROM moz_bookmarks WHERE id = b.parent " +
-            "AND type IN (:bookmark_type, :separator_type, :dynamic_type) " +
+            "AND type IN (:bookmark_type, :separator_type) " +
             "LIMIT 1) " +
       ")");
     fixInvalidParents.params["unsorted_folder"] = PlacesUtils.unfiledBookmarksFolderId;
     fixInvalidParents.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
     fixInvalidParents.params["separator_type"] = PlacesUtils.bookmarks.TYPE_SEPARATOR;
-    fixInvalidParents.params["dynamic_type"] = PlacesUtils.bookmarks.TYPE_DYNAMIC_CONTAINER;
     cleanupStatements.push(fixInvalidParents);
 
     // D.10 recalculate positions
     //      This requires multiple related statements.
     //      We can detect a folder with bad position values comparing the sum of
     //      all distinct position values (+1 since position is 0-based) with the
     //      triangular numbers obtained by the number of children (n).
     //      SUM(DISTINCT position + 1) == (n * (n + 1) / 2).
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -405,17 +405,17 @@ var PlacesUtils = {
   /**
    * Determines if a node is read only (children cannot be inserted, sometimes
    * they cannot be removed depending on the circumstance)
    * @param   aNode
    *          A result node
    * @returns true if the node is readonly, false otherwise
    */
   nodeIsReadOnly: function PU_nodeIsReadOnly(aNode) {
-    if (this.nodeIsFolder(aNode) || this.nodeIsDynamicContainer(aNode)) {
+    if (this.nodeIsFolder(aNode)) {
       if (this._readOnly.indexOf(aNode.itemId) != -1)
         return true;
     }
     else if (this.nodeIsQuery(aNode) &&
              asQuery(aNode).queryOptions.resultType !=
              Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_CONTENTS)
       return aNode.childrenReadOnly;
     return false;
@@ -464,18 +464,17 @@ var PlacesUtils = {
   /**
    * Determines whether or not a ResultNode is a container.
    * @param   aNode
    *          A result node
    * @returns true if the node is a container item, false otherwise
    */
   containerTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER,
                    Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT,
-                   Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY,
-                   Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER],
+                   Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY],
   nodeIsContainer: function PU_nodeIsContainer(aNode) {
     return this.containerTypes.indexOf(aNode.type) != -1;
   },
 
   /**
    * Determines whether or not a ResultNode is an history related container.
    * @param   node
    *          A result node
@@ -488,31 +487,16 @@ var PlacesUtils = {
               Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY ||
             resultType == Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY ||
             resultType == Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY ||
             this.nodeIsDay(aNode) ||
             this.nodeIsHost(aNode));
   },
 
   /**
-   * Determines whether or not a result-node is a dynamic-container item.
-   * The dynamic container result node type is for dynamically created
-   * containers (e.g. for the file browser service where you get your folders
-   * in bookmark menus).
-   * @param   aNode
-   *          A result node
-   * @returns true if the node is a dynamic container item, false otherwise
-   */
-  nodeIsDynamicContainer: function PU_nodeIsDynamicContainer(aNode) {
-    if (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER)
-      return true;
-    return false;
-  },
-
-  /**
    * Determines if a container item id is a livemark.
    * @param aItemId
    *        The id of the potential livemark.
    * @returns true if the item is a livemark.
    */
   itemIsLivemark: function PU_itemIsLivemark(aItemId) {
     // If the Livemark service hasn't yet been initialized then
     // use the annotations service directly to avoid instanciating
deleted file mode 100644
--- a/toolkit/components/places/nsIDynamicContainer.idl
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*- Mode: IDL; 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 Places.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Annie Sullivan <annie.sullivan@gmail.com> (original author)
- *   Asaf Romano <mano@mozilla.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
- * 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 ***** */
-
-#include "nsISupports.idl"
-
-interface nsIURI;
-interface nsINavHistoryContainerResultNode;
-interface nsINavHistoryQueryOptions;
-
-/**
- * The dynamic container interface provides a base class for services that want
- * to provide containers for temporary contents.
- *
- * The service can fill result nodes directly into the container when it is
- * being opened. It can use the property bag on every result node to store data
- * associated with each item, such as full path on disk. It would create
- * additional containers for each container, registered to its service.
- *
- * See also createDynamicContainer in nsINavBookmarksService.
- */
-
-[scriptable, uuid(7e85d97b-4109-4ea7-afd8-bc2cd3840d70)]
-interface nsIDynamicContainer : nsISupports
-{
-  /**
-   * Called when the given container node is about to be populated so that the
-   * service can populate the container if necessary.
-   *
-   * @param aContainer
-   *        The container node for the container being opened. Note that all
-   *        result nodes implement a property bag if you need to store state.
-   * @param aOptions
-   *        The options used to generate this query. Containers should follow
-   *        these when possible, for example, whether to expand queries, etc.
-   *        Implementations should use this when possible if adding query and
-   *        folder nodes to the container. DO NOT MODIFY THIS VALUE.
-   */
-  void onContainerNodeOpening(in nsINavHistoryContainerResultNode aContainer,
-                              in nsINavHistoryQueryOptions aOptions);
-
-  /**
-   * Called when the given container has just been collapsed so that the
-   * service can do any necessary cleanup. This is NOT guaranteed to get
-   * called. In particular, if the query just goes away, you will not get this
-   * call. This only happens when the container itself goes from the open state
-   * to the closed state. A service with large numbers of dynamically populated
-   * items might use this to do some cleanup so those items don't hang around
-   *
-   * @param aContainer
-   *        The container node of the container being closed. The service need
-   *        not worry about removing any created nodes, they will be
-   *        automatically removed when this call completes.
-   */
-  void onContainerNodeClosed(in nsINavHistoryContainerResultNode aContainer);
-
-  /**
-   * Called when the given container is about to be deleted from the bookmarks
-   * table, so that the service can do any necessary cleanup.
-   * Called BEFORE the container is deleted, so that the service
-   * can still reference it.
-   * @param aItemId
-   *        The item-id of the container item.
-   */
-  void onContainerRemoving(in long long aItemId);
-
-  /**
-   * Called when the given container has just been moved, in case
-   * the service needs to do any bookkeeping.
-   * Called AFTER the container has been moved.
-   * @param aItemId
-   *        The item-id of the container item.
-   * @param aNewParent
-   *        The item of the new parent folder for the container.
-   * @param aNewIndex
-   *        The index the container will be inserted at, or -1 for append.
-   */
-  void onContainerMoved(in long long aItemId,
-                        in long long aNewParent, in long aNewIndex);
-};
--- a/toolkit/components/places/nsINavBookmarksService.idl
+++ b/toolkit/components/places/nsINavBookmarksService.idl
@@ -276,17 +276,17 @@ interface nsINavBookmarkObserver : nsISu
 };
 
 /**
  * The BookmarksService interface provides methods for managing bookmarked
  * history items.  Bookmarks consist of a set of user-customizable
  * folders.  A URI in history can be contained in one or more such folders.
  */
 
-[scriptable, uuid(573f99bd-988c-4253-836f-4ce009d33ac6)]
+[scriptable, uuid(5398fdee-72d8-4100-9863-6bb7f88274e0)]
 interface nsINavBookmarksService : nsISupports
 {
   /**
    * The item ID of the Places root.
    */
   readonly attribute long long placesRoot;
 
   /**
@@ -314,16 +314,18 @@ interface nsINavBookmarksService : nsISu
    * where an index is not known, or not required to be specified.
    * e.g.: When appending an item to a folder.
    */
   const short DEFAULT_INDEX = -1;
 
   const unsigned short TYPE_BOOKMARK = 1;
   const unsigned short TYPE_FOLDER = 2;
   const unsigned short TYPE_SEPARATOR = 3;
+  // Dynamic containers are deprecated and unsupported.
+  // This const exists just to avoid reusing the value.
   const unsigned short TYPE_DYNAMIC_CONTAINER = 4;
 
   /**
    * Inserts a child bookmark into the given folder.
    *
    *  @param aParentId
    *         The id of the parent folder
    *  @param aURI
@@ -356,34 +358,16 @@ interface nsINavBookmarksService : nsISu
    *  @param aIndex
    *         The index to insert at, or DEFAULT_INDEX to append
    *  @return The ID of the newly-inserted folder.
    */
   long long createFolder(in long long aParentFolder, in AUTF8String name,
                          in long index);
 
   /**
-   * Creates a dynamic container under the given parent folder.
-   *
-   *  @param aParentFolder
-   *         The id of the parent folder
-   *  @param aName
-   *         The name of the new folder
-   *  @param aContractId
-   *         The contract id of the service which is to manipulate this
-   *         container.
-   *  @param aIndex
-   *         The index to insert at, or DEFAULT_INDEX to append
-   *         
-   *  @return The ID of the newly-inserted folder.
-   */
-  long long createDynamicContainer(in long long aParentFolder, in AUTF8String aName,
-                                   in AString aContractId, in long aIndex);
-
-  /**
    * Gets an undo-able transaction for removing a folder from the bookmarks
    * tree. 
    *  @param aItemId
    *         The id of the folder to remove.
    *  @return An object implementing nsITransaction that can be used to undo 
    *          or redo the action. 
    *
    * This method exists because complex delete->undo operations rely on 
--- a/toolkit/components/places/nsINavHistoryService.idl
+++ b/toolkit/components/places/nsINavHistoryService.idl
@@ -85,16 +85,18 @@ interface nsINavHistoryResultNode : nsIS
 
   /**
    * Identifies the type of this node. This node can then be QI-ed to the
    * corresponding specialized result node interface.
    */
   const unsigned long RESULT_TYPE_URI = 0;               // nsINavHistoryResultNode
   const unsigned long RESULT_TYPE_VISIT = 1;             // nsINavHistoryVisitResultNode
   const unsigned long RESULT_TYPE_FULL_VISIT = 2;        // nsINavHistoryFullVisitResultNode
+  // Dynamic containers are deprecated and unsupported.
+  // This const exists just to avoid reusing the value.
   const unsigned long RESULT_TYPE_DYNAMIC_CONTAINER = 4; // nsINavHistoryContainerResultNode
   const unsigned long RESULT_TYPE_QUERY = 5;             // nsINavHistoryQueryResultNode
   const unsigned long RESULT_TYPE_FOLDER = 6;            // nsINavHistoryQueryResultNode
   const unsigned long RESULT_TYPE_SEPARATOR = 7;         // nsINavHistoryResultNode
   const unsigned long RESULT_TYPE_FOLDER_SHORTCUT = 9;   // nsINavHistoryQueryResultNode
   readonly attribute unsigned long type;
 
   /**
@@ -228,17 +230,17 @@ interface nsINavHistoryFullVisitResultNo
 };
 
 
 /**
  * Base class for container results. This includes all types of groupings.
  * Bookmark folders and places queries will be QueryResultNodes which extends
  * these items.
  */
-[scriptable, uuid(55829318-0f6c-4503-8739-84231f3a6793)]
+[scriptable, uuid(62534d3c-1b3f-401e-b3ba-b911f57f8a29)]
 interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
 {
 
   /**
    * Set this to allow descent into the container. When closed, attempting
    * to call getChildren or childCount will result in an error. You should
    * set this to false when you are done reading.
    *
@@ -318,115 +320,16 @@ interface nsINavHistoryContainerResultNo
   /**
    * Returns false if this node's list of children can be modified
    * (adding or removing children, or reordering children), or true if
    * the UI should not allow the list of children to be modified.
    * This is false for bookmark folder nodes unless setFolderReadOnly() has
    * been called to override it, and true for non-folder nodes.
    */
   readonly attribute boolean childrenReadOnly;
-
-  // --------------------------------------------------------------------------
-  // Dynamic container
-
-  /**
-   * This is a string representing the dynamic container API service that is
-   * responsible for this container. This throws if if the node is not a dynamic
-   * container.
-   */
-  readonly attribute AUTF8String dynamicContainerType;
-
-  /**
-   * Appends a full visit node to this container and returns it. For the dynamic
-   * container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
-   * ONLY, and only for non-bookmark-folder containers.
-   *
-   * @see nsINavHistoryURIResultNode for parameters.
-   */
-  nsINavHistoryResultNode appendURINode(
-      in AUTF8String aURI, in AUTF8String aTitle, in PRUint32 aAccessCount,
-      in PRTime aTime, in AUTF8String aIconURI);
-
-  /**
-   * Appends a full visit node to this container and returns it. For the dynamic
-   * container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
-   * ONLY, and only for non-bookmark-folder containers.
-   *
-   * @see nsINavHistoryVisitResultNode for parameters.
-   *
-   * UNTESTED: Container API functions are commented out until we can test
-   */
-  /*nsINavHistoryVisitResultNode appendVisitNode(
-      in AUTF8String aURI, in AUTF8String aTitle, in PRUint32 aAccessCount,
-      in PRTime aTime, in AUTF8String aIconURI, in PRInt64 aSession);*/
-
-  /**
-   * Appends a full visit node to this container and returns it. For the dynamic
-   * container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
-   * ONLY, and only for non-bookmark-folder containers.
-   *
-   * @see nsINavHistoryFullVisitResultNode for parameters.
-   *
-   * UNTESTED: Container API functions are commented out until we can test
-   */
-  /*nsINavHistoryFullVisitResultNode appendFullVisitNode(
-      in AUTF8String aURI, in AUTF8String aTitle, in PRUint32 aAccessCount,
-      in PRTime aTime, in AUTF8String aIconURI, in PRInt64 aSession,
-      in PRInt64 aVisitId, in PRInt64 aReferringVisitId,
-      in PRInt32 aTransitionType);*/
-
-  /**
-   * Appends a container node to this container and returns it. For the dynamic
-   * container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
-   * ONLY, and only for non-bookmark-folder containers.
-   *
-   * aContainerType should be RESULT_TYPE_DYNAMIC_CONTAINER.
-   * When type is dynamic container you must
-   * specify a dynamic container type, otherwise, the dynamic container type must
-   * be null. Use appendQueryNode and appendFolderNode for the other container
-   * types.
-   *
-   * UNTESTED: Container API functions are commented out until we can test
-   */
-  /*nsINavHistoryContainerResultNode appendContainerNode(
-      in AUTF8String aTitle, in AUTF8String aIconURI, in PRUint32 aContainerType,
-      in AUTF8String aDynamicContainerType);*/
-
-  /**
-   * Appends a query node to this container and returns it. For the dynamic
-   * container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
-   * ONLY, and only for non-bookmark-folder containers.
-   *
-   * Normally you should supply an empty string for IconURI and it will take
-   * the default query icon for the current theme.
-   *
-   * UNTESTED: Container API functions are commented out until we can test
-   */
-  /*nsINavHistoryQueryResultNode appendQueryNode(
-      in AUTF8String aQueryURI, in AUTF8String aTitle, in AUTF8String aIconURI);*/
-
-  /**
-   * Appends a bookmark folder node to this container and returns it. For the
-   * dynamic container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
-   * ONLY, and only for non-bookmark-folder containers.
-   *
-   * All container attributes will come from the boomkarks service for this
-   * folder.
-   */
-  nsINavHistoryContainerResultNode appendFolderNode(in PRInt64 aFolderId);
-
-  /**
-   * Clears all children of this container. For the dynamic container API.
-   * TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening and
-   * nsIDynamicContainer::OnContainerClosed ONLY, and valid only for
-   * non-bookmark-folder containers.
-   *
-   * UNTESTED: Container API functions are commented out until we can test
-   */
-  /*void clearContents();*/
 };
 
 
 /**
  * Used for places queries and as a base for bookmark folders.
  *
  * Note that if you request places to *not* be expanded in the options that
  * generated this node, this item will report it has no children and never try
--- a/toolkit/components/places/nsNavBookmarks.cpp
+++ b/toolkit/components/places/nsNavBookmarks.cpp
@@ -44,17 +44,16 @@
 #include "nsNavHistory.h"
 #include "nsAnnotationService.h"
 #include "nsILivemarkService.h"
 #include "nsPlacesMacros.h"
 #include "Helpers.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsNetUtil.h"
-#include "nsIDynamicContainer.h"
 #include "nsUnicharUtils.h"
 #include "nsPrintfCString.h"
 #include "nsIUUIDGenerator.h"
 #include "prprf.h"
 #include "mozilla/storage.h"
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Util.h"
 
@@ -72,18 +71,17 @@
 #define TOPIC_PLACES_MAINTENANCE "places-maintenance-finished"
 
 using namespace mozilla;
 
 // These columns sit to the right of the kGetInfoIndex_* columns.
 const PRInt32 nsNavBookmarks::kGetChildrenIndex_Position = 14;
 const PRInt32 nsNavBookmarks::kGetChildrenIndex_Type = 15;
 const PRInt32 nsNavBookmarks::kGetChildrenIndex_PlaceID = 16;
-const PRInt32 nsNavBookmarks::kGetChildrenIndex_ServiceContractId = 17;
-const PRInt32 nsNavBookmarks::kGetChildrenIndex_Guid = 18;
+const PRInt32 nsNavBookmarks::kGetChildrenIndex_Guid = 17;
 
 using namespace mozilla::places;
 
 PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsNavBookmarks, gBookmarksService)
 
 #define BOOKMARKS_ANNO_PREFIX "bookmarks/"
 #define BOOKMARKS_TOOLBAR_FOLDER_ANNO NS_LITERAL_CSTRING(BOOKMARKS_ANNO_PREFIX "toolbarFolder")
 #define GUID_ANNO NS_LITERAL_CSTRING("placesInternal/GUID")
@@ -520,31 +518,30 @@ nsNavBookmarks::GetUnfiledBookmarksFolde
 nsresult
 nsNavBookmarks::InsertBookmarkInDB(PRInt64 aPlaceId,
                                    enum ItemType aItemType,
                                    PRInt64 aParentId,
                                    PRInt32 aIndex,
                                    const nsACString& aTitle,
                                    PRTime aDateAdded,
                                    PRTime aLastModified,
-                                   const nsAString& aServiceContractId,
                                    PRInt64* _itemId,
                                    nsACString& _guid)
 {
   // Check for a valid itemId.
   MOZ_ASSERT(_itemId && (*_itemId == -1 || *_itemId > 0));
   // Check for a valid placeId.
   MOZ_ASSERT(aPlaceId && (aPlaceId == -1 || aPlaceId > 0));
 
   nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
     "INSERT INTO moz_bookmarks "
-      "(id, fk, type, parent, position, title, folder_type, "
+      "(id, fk, type, parent, position, title, "
        "dateAdded, lastModified, guid) "
     "VALUES (:item_id, :page_id, :item_type, :parent, :item_index, "
-            ":item_title, :folder_type, :date_added, :last_modified, "
+            ":item_title, :date_added, :last_modified, "
             "GENERATE_GUID())"
   );
   NS_ENSURE_STATE(stmt);
   mozStorageStatementScoper scoper(stmt);
 
   nsresult rv;
   if (*_itemId != -1)
     rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), *_itemId);
@@ -567,25 +564,16 @@ nsNavBookmarks::InsertBookmarkInDB(PRInt
 
   // Support NULL titles.
   if (aTitle.IsVoid())
     rv = stmt->BindNullByName(NS_LITERAL_CSTRING("item_title"));
   else
     rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("item_title"), aTitle);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (aServiceContractId.IsEmpty()) {
-    rv = stmt->BindNullByName(NS_LITERAL_CSTRING("folder_type"));
-  }
-  else {
-    rv = stmt->BindStringByName(NS_LITERAL_CSTRING("folder_type"),
-                                aServiceContractId);
-  }
-  NS_ENSURE_SUCCESS(rv, rv);
-
   rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("date_added"), aDateAdded);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aLastModified) {
     rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("last_modified"),
                                aLastModified);
   }
   else {
@@ -667,19 +655,18 @@ nsNavBookmarks::InsertBookmark(PRInt64 a
   }
 
   *aNewBookmarkId = -1;
   PRTime dateAdded = PR_Now();
   nsCAutoString guid;
   nsCString title;
   TruncateTitle(aTitle, title);
 
-  rv = InsertBookmarkInDB(placeId, BOOKMARK, aFolder, index,
-                          title, dateAdded, nsnull, EmptyString(),
-                          aNewBookmarkId, guid);
+  rv = InsertBookmarkInDB(placeId, BOOKMARK, aFolder, index, title, dateAdded,
+                          nsnull, aNewBookmarkId, guid);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Recalculate frecency for this entry, since it changed.
   rv = history->UpdateFrecency(placeId);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = transaction.Commit();
   NS_ENSURE_SUCCESS(rv, rv);
@@ -745,25 +732,16 @@ nsNavBookmarks::RemoveItem(PRInt64 aItem
 
   // First, remove item annotations
   nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
   NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
   rv = annosvc->RemoveItemAnnotations(bookmark.id);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (bookmark.type == TYPE_FOLDER) {
-    // If this is a dynamic container, try to notify its service.
-    if (!bookmark.serviceCID.IsEmpty()) {
-      nsCOMPtr<nsIDynamicContainer> svc =
-        do_GetService(bookmark.serviceCID.get());
-      if (svc) {
-        (void)svc->OnContainerRemoving(bookmark.id);
-      }
-    }
-
     // Remove all of the folder's children.
     rv = RemoveFolderChildren(bookmark.id);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   BEGIN_CRITICAL_BOOKMARK_CACHE_SECTION(bookmark.id);
 
   nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
@@ -857,39 +835,22 @@ nsNavBookmarks::CreateFolder(PRInt64 aPa
   // NOTE: aParent can be null for root creation, so not checked
   NS_ENSURE_ARG_POINTER(aNewFolder);
 
   // CreateContainerWithID returns the index of the new folder, but that's not
   // used here.  To avoid any risk of corrupting data should this function
   // be changed, we'll use a local variable to hold it.  The true argument
   // will cause notifications to be sent to bookmark observers.
   PRInt32 localIndex = aIndex;
-  nsresult rv = CreateContainerWithID(-1, aParent, aName, EmptyString(),
-                                      true, &localIndex, aNewFolder);
+  nsresult rv = CreateContainerWithID(-1, aParent, aName, true, &localIndex,
+                                      aNewFolder);
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
-
-NS_IMETHODIMP
-nsNavBookmarks::CreateDynamicContainer(PRInt64 aParent,
-                                       const nsACString& aName,
-                                       const nsAString& aContractId,
-                                       PRInt32 aIndex,
-                                       PRInt64* aNewFolder)
-{
-  NS_ENSURE_FALSE(aContractId.IsEmpty(), NS_ERROR_INVALID_ARG);
-
-  nsresult rv = CreateContainerWithID(-1, aParent, aName, aContractId,
-                                      false, &aIndex, aNewFolder);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return NS_OK;
-}
-
-
 NS_IMETHODIMP
 nsNavBookmarks::GetFolderReadonly(PRInt64 aFolder, bool* aResult)
 {
   NS_ENSURE_ARG_MIN(aFolder, 1);
   NS_ENSURE_ARG_POINTER(aResult);
 
   nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
   NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
@@ -924,17 +885,16 @@ nsNavBookmarks::SetFolderReadonly(PRInt6
   return NS_OK;
 }
 
 
 nsresult
 nsNavBookmarks::CreateContainerWithID(PRInt64 aItemId,
                                       PRInt64 aParent,
                                       const nsACString& aTitle,
-                                      const nsAString& aContractId,
                                       bool aIsBookmarkFolder,
                                       PRInt32* aIndex,
                                       PRInt64* aNewFolder)
 {
   NS_ENSURE_ARG_MIN(*aIndex, nsINavBookmarksService::DEFAULT_INDEX);
 
   // Get the correct index for insertion.  This also ensures the parent exists.
   PRInt32 index, folderCount;
@@ -953,36 +913,34 @@ nsNavBookmarks::CreateContainerWithID(PR
     // Create space for the insertion.
     rv = AdjustIndices(aParent, index, PR_INT32_MAX, 1);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   *aNewFolder = aItemId;
   PRTime dateAdded = PR_Now();
   nsCAutoString guid;
-  ItemType containerType = aIsBookmarkFolder ? FOLDER
-                                             : DYNAMIC_CONTAINER;
   nsCString title;
   TruncateTitle(aTitle, title);
 
-  rv = InsertBookmarkInDB(-1, containerType, aParent, index,
-                          title, dateAdded, nsnull, aContractId, aNewFolder,
+  rv = InsertBookmarkInDB(-1, FOLDER, aParent, index,
+                          title, dateAdded, nsnull, aNewFolder,
                           guid);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = transaction.Commit();
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!mBatching) {
     ForceWALCheckpoint();
   }
 
   NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
                    nsINavBookmarkObserver,
-                   OnItemAdded(*aNewFolder, aParent, index, containerType,
+                   OnItemAdded(*aNewFolder, aParent, index, FOLDER,
                                nsnull, title, dateAdded, guid, folderGuid));
 
   *aIndex = index;
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
@@ -1016,17 +974,17 @@ nsNavBookmarks::InsertSeparator(PRInt64 
 
   *aNewItemId = -1;
   // Set a NULL title rather than an empty string.
   nsCString voidString;
   voidString.SetIsVoid(true);
   nsCAutoString guid;
   PRTime dateAdded = PR_Now();
   rv = InsertBookmarkInDB(-1, SEPARATOR, aParent, index, voidString, dateAdded,
-                          nsnull, EmptyString(), aNewItemId, guid);
+                          nsnull, aNewItemId, guid);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = transaction.Commit();
   NS_ENSURE_SUCCESS(rv, rv);
 
   NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
                    nsINavBookmarkObserver,
                    OnItemAdded(*aNewItemId, aParent, index, TYPE_SEPARATOR,
@@ -1138,18 +1096,17 @@ nsNavBookmarks::GetDescendantChildren(PR
     // Select all children of a given folder, sorted by position.
     // This is a LEFT JOIN because not all bookmarks types have a place.
     // We construct a result where the first columns exactly match
     // kGetInfoIndex_* order, and additionally contains columns for position,
     // item_child, and folder_child from moz_bookmarks.
     nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
       "SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, "
              "h.last_visit_date, f.url, null, b.id, b.dateAdded, b.lastModified, "
-             "b.parent, null, h.frecency, b.position, b.type, b.fk, "
-             "b.folder_type, b.guid "
+             "b.parent, null, h.frecency, b.position, b.type, b.fk, b.guid "
       "FROM moz_bookmarks b "
       "LEFT JOIN moz_places h ON b.fk = h.id "
       "LEFT JOIN moz_favicons f ON h.favicon_id = f.id "
       "WHERE b.parent = :parent "
       "ORDER BY b.position ASC"
     );
     NS_ENSURE_STATE(stmt);
     mozStorageStatementScoper scoper(stmt);
@@ -1173,26 +1130,17 @@ nsNavBookmarks::GetDescendantChildren(PR
       NS_ENSURE_SUCCESS(rv, rv);
       rv = stmt->GetUTF8String(kGetChildrenIndex_Guid, child.guid);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (child.type == TYPE_BOOKMARK) {
         rv = stmt->GetUTF8String(nsNavHistory::kGetInfoIndex_URL, child.url);
         NS_ENSURE_SUCCESS(rv, rv);
       }
-      else if (child.type == TYPE_FOLDER) {
-        bool isNull;
-        rv = stmt->GetIsNull(kGetChildrenIndex_ServiceContractId, &isNull);
-        NS_ENSURE_SUCCESS(rv, rv);
-        if (!isNull) {
-          rv = stmt->GetUTF8String(kGetChildrenIndex_ServiceContractId,
-                                   child.serviceCID);
-          NS_ENSURE_SUCCESS(rv, rv);
-        }
-      }
+
       // Append item to children's array.
       aFolderChildrenArray.AppendElement(child);
     }
   }
 
   // Recursively call GetDescendantChildren for added folders.
   // We start at startIndex since previous folders are checked
   // by previous calls to this method.
@@ -1243,27 +1191,16 @@ nsNavBookmarks::RemoveFolderChildren(PRI
                                          child.type,
                                          child.parentId,
                                          child.guid,
                                          child.parentGuid));
 
     if (child.type == TYPE_FOLDER) {
       foldersToRemove.AppendLiteral(",");
       foldersToRemove.AppendInt(child.id);
-
-      // If this is a dynamic container, try to notify its service that we
-      // are going to remove it.
-      // XXX (bug 484094) this should use a bookmark observer!
-      if (!child.serviceCID.IsEmpty()) {
-        nsCOMPtr<nsIDynamicContainer> svc =
-          do_GetService(child.serviceCID.get());
-        if (svc) {
-          (void)svc->OnContainerRemoving(child.id);
-        }
-      }
     }
 
     BEGIN_CRITICAL_BOOKMARK_CACHE_SECTION(child.id);
   }
 
   // Delete items from the database now.
   mozStorageTransaction transaction(mDB->MainConn(), false);
 
@@ -1496,25 +1433,16 @@ nsNavBookmarks::MoveItem(PRInt64 aItemId
                                bookmark.parentId,
                                bookmark.position,
                                aNewParent,
                                newIndex,
                                bookmark.type,
                                bookmark.guid,
                                bookmark.parentGuid,
                                newParentGuid));
-
-  // notify dynamic container provider if there is one
-  if (!bookmark.serviceCID.IsEmpty()) {
-    nsCOMPtr<nsIDynamicContainer> svc =
-      do_GetService(bookmark.serviceCID.get());
-    if (svc) {
-      (void)svc->OnContainerMoved(bookmark.id, aNewParent, newIndex);
-    }
-  }
   return NS_OK;
 }
 
 nsresult
 nsNavBookmarks::FetchItemInfo(PRInt64 aItemId,
                               BookmarkData& _bookmark)
 {
   // Check if the requested id is in the recent cache and avoid the database
@@ -1523,18 +1451,17 @@ nsNavBookmarks::FetchItemInfo(PRInt64 aI
   if (key) {
     _bookmark = key->bookmark;
     return NS_OK;
   }
 
   // LEFT JOIN since not all bookmarks have an associated place.
   nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
     "SELECT b.id, h.url, b.title, b.position, b.fk, b.parent, b.type, "
-           "b.folder_type, b.dateAdded, b.lastModified, b.guid, "
-           "t.guid, t.parent "
+           "b.dateAdded, b.lastModified, b.guid, t.guid, t.parent "
     "FROM moz_bookmarks b "
     "LEFT JOIN moz_bookmarks t ON t.id = b.parent "
     "LEFT JOIN moz_places h ON h.id = b.fk "
     "WHERE b.id = :item_id"
   );
   NS_ENSURE_STATE(stmt);
   mozStorageStatementScoper scoper(stmt);
 
@@ -1564,38 +1491,29 @@ nsNavBookmarks::FetchItemInfo(PRInt64 aI
   rv = stmt->GetInt32(3, &_bookmark.position);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = stmt->GetInt64(4, &_bookmark.placeId);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = stmt->GetInt64(5, &_bookmark.parentId);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = stmt->GetInt32(6, &_bookmark.type);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = stmt->GetIsNull(7, &isNull);
+  rv = stmt->GetInt64(7, &_bookmark.dateAdded);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (isNull) {
-    _bookmark.serviceCID.SetIsVoid(true);
-  }
-  else {
-    rv = stmt->GetUTF8String(7, _bookmark.serviceCID);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  rv = stmt->GetInt64(8, &_bookmark.dateAdded);
+  rv = stmt->GetInt64(8, &_bookmark.lastModified);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = stmt->GetInt64(9, &_bookmark.lastModified);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = stmt->GetUTF8String(10, _bookmark.guid);
+  rv = stmt->GetUTF8String(9, _bookmark.guid);
   NS_ENSURE_SUCCESS(rv, rv);
   // Getting properties of the root would show no parent.
-  rv = stmt->GetIsNull(11, &isNull);
+  rv = stmt->GetIsNull(10, &isNull);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!isNull) {
-    rv = stmt->GetUTF8String(11, _bookmark.parentGuid);
+    rv = stmt->GetUTF8String(10, _bookmark.parentGuid);
     NS_ENSURE_SUCCESS(rv, rv);
-    rv = stmt->GetInt64(12, &_bookmark.grandParentId);
+    rv = stmt->GetInt64(11, &_bookmark.grandParentId);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   else {
     _bookmark.grandParentId = -1;
   }
 
   // Make space for the new entry.
   ExpireNonrecentBookmarks(&mRecentBookmarksCache);
@@ -1938,54 +1856,28 @@ nsNavBookmarks::GetItemType(PRInt64 aIte
   NS_ENSURE_SUCCESS(rv, rv);
 
   *_type = static_cast<PRUint16>(bookmark.type);
   return NS_OK;
 }
 
 
 nsresult
-nsNavBookmarks::GetFolderType(PRInt64 aItemId,
-                              nsACString& _type)
-{
-  NS_ENSURE_ARG_MIN(aItemId, 1);
-
-  BookmarkData bookmark;
-  nsresult rv = FetchItemInfo(aItemId, bookmark);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  _type = bookmark.serviceCID;
-  return NS_OK;
-}
-
-
-nsresult
 nsNavBookmarks::ResultNodeForContainer(PRInt64 aItemId,
                                        nsNavHistoryQueryOptions* aOptions,
                                        nsNavHistoryResultNode** aNode)
 {
   BookmarkData bookmark;
   nsresult rv = FetchItemInfo(aItemId, bookmark);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (bookmark.type == TYPE_DYNAMIC_CONTAINER) {
-    *aNode = new nsNavHistoryContainerResultNode(EmptyCString(),
-                                                 bookmark.title,
-                                                 EmptyCString(),
-                                                 nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER,
-                                                 true,
-                                                 bookmark.serviceCID,
-                                                 aOptions);
-    (*aNode)->mItemId = bookmark.id;
-  }
-  else if (bookmark.type == TYPE_FOLDER) { // TYPE_FOLDER
+  if (bookmark.type == TYPE_FOLDER) { // TYPE_FOLDER
     *aNode = new nsNavHistoryFolderResultNode(bookmark.title,
                                               aOptions,
-                                              bookmark.id,
-                                              EmptyCString());
+                                              bookmark.id);
   }
   else {
     return NS_ERROR_INVALID_ARG;
   }
 
   (*aNode)->mDateAdded = bookmark.dateAdded;
   (*aNode)->mLastModified = bookmark.lastModified;
 
@@ -2007,17 +1899,17 @@ nsNavBookmarks::QueryFolderChildren(
   // This is a LEFT JOIN because not all bookmarks types have a place.
   // We construct a result where the first columns exactly match those returned
   // by mDBGetURLPageInfo, and additionally contains columns for position,
   // item_child, and folder_child from moz_bookmarks.
   nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
     "SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, "
            "h.last_visit_date, f.url, null, b.id, b.dateAdded, b.lastModified, "
            "b.parent, null, h.frecency, b.position, b.type, b.fk, "
-           "b.folder_type, b.guid "
+           "b.guid "
     "FROM moz_bookmarks b "
     "LEFT JOIN moz_places h ON b.fk = h.id "
     "LEFT JOIN moz_favicons f ON h.favicon_id = f.id "
     "WHERE b.parent = :parent "
     "ORDER BY b.position ASC"
   );
   NS_ENSURE_STATE(stmt);
   mozStorageStatementScoper scoper(stmt);
@@ -2073,27 +1965,21 @@ nsNavBookmarks::ProcessFolderNodeRow(
     if ((nodeType == nsINavHistoryResultNode::RESULT_TYPE_QUERY &&
          aOptions->ExcludeQueries()) ||
         (nodeType != nsINavHistoryResultNode::RESULT_TYPE_QUERY &&
          nodeType != nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT &&
          aOptions->ExcludeItems())) {
       return NS_OK;
     }
   }
-  else if (itemType == TYPE_FOLDER || itemType == TYPE_DYNAMIC_CONTAINER) {
+  else if (itemType == TYPE_FOLDER) {
     if (aOptions->ExcludeReadOnlyFolders()) {
       // If the folder is read-only, skip it.
-      bool readOnly;
-      if (itemType == TYPE_DYNAMIC_CONTAINER) {
-        readOnly = true;
-      }
-      else {
-        readOnly = false;
-        GetFolderReadonly(id, &readOnly);
-      }
+      bool readOnly = false;
+      GetFolderReadonly(id, &readOnly);
       if (readOnly)
         return NS_OK;
     }
     rv = ResultNodeForContainer(id, aOptions, getter_AddRefs(node));
     NS_ENSURE_SUCCESS(rv, rv);
   }
   else {
     // This is a separator.
@@ -2136,17 +2022,17 @@ nsNavBookmarks::QueryFolderChildrenAsync
   // This is a LEFT JOIN because not all bookmarks types have a place.
   // We construct a result where the first columns exactly match those returned
   // by mDBGetURLPageInfo, and additionally contains columns for position,
   // item_child, and folder_child from moz_bookmarks.
   nsCOMPtr<mozIStorageAsyncStatement> stmt = mDB->GetAsyncStatement(
     "SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, "
            "h.last_visit_date, f.url, null, b.id, b.dateAdded, b.lastModified, "
            "b.parent, null, h.frecency, b.position, b.type, b.fk, "
-           "b.folder_type, b.guid "
+           "b.guid "
     "FROM moz_bookmarks b "
     "LEFT JOIN moz_places h ON b.fk = h.id "
     "LEFT JOIN moz_favicons f ON h.favicon_id = f.id "
     "WHERE b.parent = :parent "
     "ORDER BY b.position ASC"
   );
   NS_ENSURE_STATE(stmt);
 
--- a/toolkit/components/places/nsNavBookmarks.h
+++ b/toolkit/components/places/nsNavBookmarks.h
@@ -215,17 +215,16 @@ public:
    * @return index of the new folder in aIndex, whether it was passed in or
    *         generated by autoincrement.
    *
    * @note If aFolder is -1, uses the autoincrement id for folder index.
    * @note aTitle will be truncated to TITLE_LENGTH_MAX
    */
   nsresult CreateContainerWithID(PRInt64 aId, PRInt64 aParent,
                                  const nsACString& aTitle,
-                                 const nsAString& aContractId,
                                  bool aIsBookmarkFolder,
                                  PRInt32* aIndex,
                                  PRInt64* aNewFolder);
 
   /**
    * Fetches information about the specified id from the database.
    *
    * @param aItemId
@@ -313,18 +312,16 @@ private:
    *
    * @throws If folder does not exist.
    */
   nsresult FetchFolderInfo(PRInt64 aFolderId,
                            PRInt32* _folderCount,
                            nsACString& _guid,
                            PRInt64* _parentId);
 
-  nsresult GetFolderType(PRInt64 aFolder, nsACString& aType);
-
   nsresult GetLastChildId(PRInt64 aFolder, PRInt64* aItemId);
 
   /**
    * This is an handle to the Places database.
    */
   nsRefPtr<mozilla::places::Database> mDB;
 
   nsString mGUIDBase;
@@ -351,17 +348,16 @@ private:
                                  const nsACString& aFolderGuid,
                                  PRInt64 aGrandParentId,
                                  nsTArray<BookmarkData>& aFolderChildrenArray);
 
   enum ItemType {
     BOOKMARK = TYPE_BOOKMARK,
     FOLDER = TYPE_FOLDER,
     SEPARATOR = TYPE_SEPARATOR,
-    DYNAMIC_CONTAINER = TYPE_DYNAMIC_CONTAINER
   };
 
   /**
    * Helper to insert a bookmark in the database.
    *
    *  @param aItemId
    *         The itemId to insert, pass -1 to generate a new one.
    *  @param aPlaceId
@@ -376,32 +372,28 @@ private:
    *  @param aTitle
    *         The title for the new bookmark.
    *         Pass a void string to set a NULL title.
    *  @param aDateAdded
    *         The date for the insertion.
    *  @param [optional] aLastModified
    *         The last modified date for the insertion.
    *         It defaults to aDateAdded.
-   *  @param [optional] aServiceContractId
-   *         The contract id for a dynamic container.
-   *         Pass EmptyCString() for other type of containers.
    *
    *  @return The new item id that has been inserted.
    *
    *  @note This will also update last modified date of the parent folder.
    */
   nsresult InsertBookmarkInDB(PRInt64 aPlaceId,
                               enum ItemType aItemType,
                               PRInt64 aParentId,
                               PRInt32 aIndex,
                               const nsACString& aTitle,
                               PRTime aDateAdded,
                               PRTime aLastModified,
-                              const nsAString& aServiceContractId,
                               PRInt64* _itemId,
                               nsACString& _guid);
 
   /**
    * TArray version of getBookmarksIdForURI for ease of use in C++ code.
    * Pass in a reference to a TArray; it will get filled with the
    * resulting list of bookmark IDs.
    *
@@ -420,17 +412,16 @@ private:
                               nsTArray<BookmarkData>& _bookmarks);
 
   PRInt64 RecursiveFindRedirectedBookmark(PRInt64 aPlaceId);
 
   static const PRInt32 kGetChildrenIndex_Position;
   static const PRInt32 kGetChildrenIndex_Type;
   static const PRInt32 kGetChildrenIndex_PlaceID;
   static const PRInt32 kGetChildrenIndex_FolderTitle;
-  static const PRInt32 kGetChildrenIndex_ServiceContractId;
   static const PRInt32 kGetChildrenIndex_Guid;
 
   class RemoveFolderTransaction : public nsITransaction {
   public:
     RemoveFolderTransaction(PRInt64 aID) : mID(aID) {}
 
     NS_DECL_ISUPPORTS
 
@@ -441,29 +432,24 @@ private:
       nsresult rv = bookmarks->FetchItemInfo(mID, folder);
       // TODO (Bug 656935): store the BookmarkData struct instead.
       mParent = folder.parentId;
       mIndex = folder.position;
 
       rv = bookmarks->GetItemTitle(mID, mTitle);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      nsCAutoString type;
-      rv = bookmarks->GetFolderType(mID, type);
-      NS_ENSURE_SUCCESS(rv, rv);
-      CopyUTF8toUTF16(type, mType);
-
       return bookmarks->RemoveItem(mID);
     }
 
     NS_IMETHOD UndoTransaction() {
       nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
       NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
       PRInt64 newFolder;
-      return bookmarks->CreateContainerWithID(mID, mParent, mTitle, mType, true,
+      return bookmarks->CreateContainerWithID(mID, mParent, mTitle, true,
                                               &mIndex, &newFolder); 
     }
 
     NS_IMETHOD RedoTransaction() {
       return DoTransaction();
     }
 
     NS_IMETHOD GetIsTransient(bool* aResult) {
@@ -475,17 +461,16 @@ private:
       *aResult = false;
       return NS_OK;
     }
 
   private:
     PRInt64 mID;
     PRInt64 mParent;
     nsCString mTitle;
-    nsString mType;
     PRInt32 mIndex;
   };
 
   // Used to enable and disable the observer notifications.
   bool mCanNotify;
   nsCategoryCache<nsINavBookmarkObserver> mCacheObservers;
 
   // Tracks whether we are in batch mode.
--- a/toolkit/components/places/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -51,17 +51,16 @@
 #include "nsDebug.h"
 #include "nsNetUtil.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "prtime.h"
 #include "prprf.h"
 
-#include "nsIDynamicContainer.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIClassInfo.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsIXPCScriptable.h"
 
 #define TO_ICONTAINER(_node)                                                  \
     static_cast<nsINavHistoryContainerResultNode*>(_node)                      
 
@@ -493,41 +492,38 @@ NS_IMPL_RELEASE_INHERITED(nsNavHistoryCo
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsNavHistoryContainerResultNode)
   NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsNavHistoryContainerResultNode)
   NS_INTERFACE_MAP_ENTRY(nsINavHistoryContainerResultNode)
 NS_INTERFACE_MAP_END_INHERITING(nsNavHistoryResultNode)
 
 nsNavHistoryContainerResultNode::nsNavHistoryContainerResultNode(
     const nsACString& aURI, const nsACString& aTitle,
     const nsACString& aIconURI, PRUint32 aContainerType, bool aReadOnly,
-    const nsACString& aDynamicContainerType, nsNavHistoryQueryOptions* aOptions) :
+    nsNavHistoryQueryOptions* aOptions) :
   nsNavHistoryResultNode(aURI, aTitle, 0, 0, aIconURI),
   mResult(nsnull),
   mContainerType(aContainerType),
   mExpanded(false),
   mChildrenReadOnly(aReadOnly),
   mOptions(aOptions),
-  mDynamicContainerType(aDynamicContainerType),
   mAsyncCanceledState(NOT_CANCELED)
 {
 }
 
 nsNavHistoryContainerResultNode::nsNavHistoryContainerResultNode(
     const nsACString& aURI, const nsACString& aTitle,
     PRTime aTime,
     const nsACString& aIconURI, PRUint32 aContainerType, bool aReadOnly,
-    const nsACString& aDynamicContainerType, 
     nsNavHistoryQueryOptions* aOptions) :
   nsNavHistoryResultNode(aURI, aTitle, 0, aTime, aIconURI),
   mResult(nsnull),
   mContainerType(aContainerType),
   mExpanded(false),
   mChildrenReadOnly(aReadOnly),
   mOptions(aOptions),
-  mDynamicContainerType(aDynamicContainerType),
   mAsyncCanceledState(NOT_CANCELED)
 {
 }
 
 
 nsNavHistoryContainerResultNode::~nsNavHistoryContainerResultNode()
 {
   // Explicitly clean up array of children of this container.  We must ensure
@@ -650,34 +646,17 @@ nsNavHistoryContainerResultNode::GetStat
  * override this to do their own handling.
  */
 nsresult
 nsNavHistoryContainerResultNode::OpenContainer()
 {
   NS_ASSERTION(!mExpanded, "Container must not be expanded to open it");
   mExpanded = true;
 
-  nsresult rv;
-
-  if (IsDynamicContainer()) {
-    // dynamic container API may want to fill us
-    nsCOMPtr<nsIDynamicContainer> svc = do_GetService(mDynamicContainerType.get(), &rv);
-    if (NS_SUCCEEDED(rv)) {
-      svc->OnContainerNodeOpening(this, GetGeneratingOptions());
-    } else {
-      NS_WARNING("Unable to get dynamic container for ");
-      NS_WARNING(mDynamicContainerType.get());
-    }
-    PRInt32 oldAccessCount = mAccessCount;
-    FillStats();
-    rv = ReverseUpdateStats(mAccessCount - oldAccessCount);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  rv = NotifyOnStateChange(STATE_CLOSED);
+  nsresult rv = NotifyOnStateChange(STATE_CLOSED);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 
 /**
  * Unset aSuppressNotifications to notify observers on this change.  That is
@@ -701,24 +680,16 @@ nsNavHistoryContainerResultNode::CloseCo
     // Recursively close all child containers.
     for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
       if (mChildren[i]->IsContainer() &&
           mChildren[i]->GetAsContainer()->mExpanded)
         mChildren[i]->GetAsContainer()->CloseContainer(true);
     }
 
     mExpanded = false;
-
-    if (IsDynamicContainer()) {
-      // Notify dynamic containers that we are closing.
-      nsCOMPtr<nsIDynamicContainer> svc =
-        do_GetService(mDynamicContainerType.get());
-      if (svc)
-        svc->OnContainerNodeClosed(this);
-    }
   }
 
   // Be sure to set this to null before notifying observers.  It signifies that
   // the container is no longer loading (if it was in the first place).
   mAsyncPendingStmt = nsnull;
 
   if (!aSuppressNotifications) {
     rv = NotifyOnStateChange(oldState);
@@ -2077,207 +2048,16 @@ nsNavHistoryContainerResultNode::FindNod
  */
 NS_IMETHODIMP
 nsNavHistoryContainerResultNode::GetChildrenReadOnly(bool *aChildrenReadOnly)
 {
   *aChildrenReadOnly = mChildrenReadOnly;
   return NS_OK;
 }
 
-
-NS_IMETHODIMP
-nsNavHistoryContainerResultNode::GetDynamicContainerType(
-    nsACString& aDynamicContainerType)
-{
-  aDynamicContainerType = mDynamicContainerType;
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsNavHistoryContainerResultNode::AppendURINode(
-    const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount,
-    PRTime aTime, const nsACString& aIconURI, nsINavHistoryResultNode** _retval)
-{
-  *_retval = nsnull;
-  if (!IsDynamicContainer())
-    return NS_ERROR_INVALID_ARG; // we must be a dynamic container
-
-  // If we are child of an ExcludeItems parent or root, we should not append
-  // URI Nodes.
-  if ((mResult && mResult->mRootNode->mOptions->ExcludeItems()) ||
-      (mParent && mParent->mOptions->ExcludeItems()))
-    return NS_OK;
-
-  nsRefPtr<nsNavHistoryResultNode> result =
-      new nsNavHistoryResultNode(aURI, aTitle, aAccessCount, aTime, aIconURI);
-  NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
-
-  // append to our list
-  nsresult rv = InsertChildAt(result, mChildren.Count());
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ADDREF(*_retval = result);
-  return NS_OK;
-}
-
-
-#if 0 // UNTESTED, commented out until it can be tested
-NS_IMETHODIMP
-nsNavHistoryContainerResultNode::AppendVisitNode(
-    const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount,
-    PRTime aTime, const nsACString& aIconURI, PRInt64 aSession,
-    nsINavHistoryVisitResultNode** _retval)
-{
-  *_retval = nsnull;
-  if (!IsDynamicContainer())
-    return NS_ERROR_INVALID_ARG; // we must be a dynamic container
-
-  nsRefPtr<nsNavHistoryVisitResultNode> result =
-      new nsNavHistoryVisitResultNode(aURI, aTitle, aAccessCount, aTime,
-                                      aIconURI, aSession);
-  NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
-
-  // append to our list
-  if (! mChildren.AppendObject(result))
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*_retval = result);
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsNavHistoryContainerResultNode::AppendFullVisitNode(
-    const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount,
-    PRTime aTime, const nsACString& aIconURI, PRInt64 aSession,
-    PRInt64 aVisitId, PRInt64 aReferringVisitId, PRInt32 aTransitionType,
-    nsINavHistoryFullVisitResultNode** _retval)
-{
-  *_retval = nsnull;
-  if (!IsDynamicContainer())
-    return NS_ERROR_INVALID_ARG; // we must be a dynamic container
-
-  nsRefPtr<nsNavHistoryFullVisitResultNode> result =
-      new nsNavHistoryFullVisitResultNode(aURI, aTitle, aAccessCount, aTime,
-                                          aIconURI, aSession, aVisitId,
-                                          aReferringVisitId, aTransitionType);
-  NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
-
-  // append to our list
-  if (! mChildren.AppendObject(result))
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*_retval = result);
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsNavHistoryContainerResultNode::AppendContainerNode(
-    const nsACString& aTitle, const nsACString& aIconURI,
-    PRUint32 aContainerType, const nsACString& aDynamicContainerType,
-    nsINavHistoryContainerResultNode** _retval)
-{
-  *_retval = nsnull;
-  if (!IsDynamicContainer())
-    return NS_ERROR_INVALID_ARG; // we must be a dynamic container
-  if (! IsTypeContainer(aContainerType) || IsTypeFolder(aContainerType) ||
-      IsTypeQuery(aContainerType))
-    return NS_ERROR_INVALID_ARG; // not proper container type
-  if (aContainerType == nsNavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER &&
-      aRemoteContainerType.IsEmpty())
-    return NS_ERROR_INVALID_ARG; // dynamic containers must have d.c. type
-  if (aContainerType != nsNavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER &&
-      ! aDynamicContainerType.IsEmpty())
-    return NS_ERROR_INVALID_ARG; // non-dynamic containers must NOT have d.c. type
-
-  nsRefPtr<nsNavHistoryContainerResultNode> result =
-      new nsNavHistoryContainerResultNode(EmptyCString(), aTitle, aIconURI,
-                                          aContainerType, true,
-                                          aDynamicContainerType);
-  NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
-
-  // append to our list
-  if (! mChildren.AppendObject(result))
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*_retval = result);
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsNavHistoryContainerResultNode::AppendQueryNode(
-    const nsACString& aQueryURI, const nsACString& aTitle,
-    const nsACString& aIconURI, nsINavHistoryQueryResultNode** _retval)
-{
-  *_retval = nsnull;
-  if (!IsDynamicContainer())
-    return NS_ERROR_INVALID_ARG; // we must be a dynamic container
-
-  nsRefPtr<nsNavHistoryQueryResultNode> result =
-      new nsNavHistoryQueryResu