Merge.
authorRobert Sayre <sayrer@gmail.com>
Wed, 31 Dec 2008 01:53:26 -0500
changeset 23233 69ae130bce9e8fbab5818cfa28d125a67f05ca7d
parent 23232 1fea65b442c89f8e5fc34b57caae85fbcc5430c9 (current diff)
parent 23205 219526c76f59e01a423952fcfab2a8a4003c76f1 (diff)
child 23235 3cddecabdffb08e6ec3879214aa5f1c74055719a
push id4405
push userrsayre@mozilla.com
push dateThu, 01 Jan 2009 22:27:02 +0000
treeherdermozilla-central@5a1e6eac685c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
Merge.
browser/themes/pinstripe/browser/tabbrowser/alltabs-box-bkgnd.png
browser/themes/pinstripe/browser/tabbrowser/tab-arrow-end-bkgnd.png
browser/themes/pinstripe/browser/tabbrowser/tab-arrow-start-bkgnd.png
editor/README.html
intl/chardet/tools/genucs2be.pl
intl/chardet/tools/genucs2le.pl
js/src/editline/Makefile.in
js/src/shell/Makefile.in
js/src/shell/js.cpp
layout/generic/nsAreaFrame.cpp
layout/generic/nsAreaFrame.h
widget/src/windows/nsWindowAPI.h
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -231,17 +231,17 @@ var StarUI = {
   },
 
   panelShown:
   function SU_panelShown(aEvent) {
     if (aEvent.target == this.panel) {
       if (!this._element("editBookmarkPanelContent").hidden) {
         var namePicker = this._element("editBMPanel_namePicker");
         namePicker.focus();
-        namePicker.editor.selectAll();
+        namePicker.select();
       }
       else
         this.panel.focus();
     }
   },
 
   showPageBookmarkedNotification:
   function PCH_showPageBookmarkedNotification(aItemId, aAnchorElement, aPosition) {
@@ -946,17 +946,21 @@ var PlacesMenuDNDController = {
   _dragSupported: false
 #else
   _dragSupported: true
 #endif
 };
 
 var PlacesStarButton = {
   init: function PSB_init() {
-    PlacesUtils.bookmarks.addObserver(this, false);
+    try {
+      PlacesUtils.bookmarks.addObserver(this, false);
+    } catch(ex) {
+      Components.utils.reportError("PlacesStarButton.init(): error adding bookmark observer: " + ex);
+    }
   },
 
   uninit: function PSB_uninit() {
     PlacesUtils.bookmarks.removeObserver(this);
   },
 
   QueryInterface: function PSB_QueryInterface(aIID) {
     if (aIID.equals(Ci.nsINavBookmarkObserver) ||
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1139,17 +1139,21 @@ function prepareForStartup() {
   var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
   os.addObserver(gBrowser.browsers[0], "browser:purge-session-history", false);
 
   // remove the disablehistory attribute so the browser cleans up, as
   // though it had done this work itself
   gBrowser.browsers[0].removeAttribute("disablehistory");
 
   // enable global history
-  gBrowser.docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).useGlobalHistory = true;
+  try {
+    gBrowser.docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).useGlobalHistory = true;
+  } catch(ex) {
+    Components.utils.reportError("Places database may be locked: " + ex);
+  }
 
   // hook up UI through progress listener
   gBrowser.addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
   gBrowser.addTabsProgressListener(window.TabsProgressListener);
 
   // setup our common DOMLinkAdded listener
   gBrowser.addEventListener("DOMLinkAdded", DOMLinkHandler, false);
 
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -623,18 +623,19 @@
             browser.mIconURL = aURI;
 
             if (aURI) {
               if (!(aURI instanceof Components.interfaces.nsIURI)) {
                 var ios = Components.classes["@mozilla.org/network/io-service;1"]
                                     .getService(Components.interfaces.nsIIOService);
                 aURI = ios.newURI(aURI, null, null);
               }
-              this.mFaviconService.setAndLoadFaviconForPage(browser.currentURI,
-                                                            aURI, false);
+              if (this.mFaviconService)
+                this.mFaviconService.setAndLoadFaviconForPage(browser.currentURI,
+                                                              aURI, false);
             }
 
             this.updateIcon(aTab);
 
             if (browser == this.mCurrentBrowser) {
               for (var i = 0; i < this.mProgressListeners.length; i++) {
                 var p = this.mProgressListeners[i];
                 if ('onLinkIconAvailable' in p)
@@ -723,17 +724,19 @@
         <body>
           <![CDATA[
             if (!(aURI instanceof Components.interfaces.nsIURI)) {
               var ios = Components.classes["@mozilla.org/network/io-service;1"]
                                   .getService(Components.interfaces.nsIIOService);
               aURI = ios.newURI(aURI, null, null);
             }
 
-            return this.mFaviconService.isFailedFavicon(aURI);
+            if (this.mFaviconService)
+              return this.mFaviconService.isFailedFavicon(aURI);
+            return null;
           ]]>
         </body>
       </method>
 
       <method name="updateTitlebar">
         <body>
           <![CDATA[
             var newTitle = "";
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -18,16 +18,17 @@
 # Portions created by the Initial Developer are Copyright (C) 2005
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Giorgio Maone <g.maone@informaction.com>
 #   Seth Spitzer <sspitzer@mozilla.com>
 #   Asaf Romano <mano@mozilla.com>
 #   Marco Bonardo <mak77@bonardo.net>
+#   Dietrich Ayala <dietrich@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
@@ -65,28 +66,46 @@ const BrowserGlueServiceFactory = {
     return this._instance == null ?
       this._instance = new BrowserGlue() : this._instance;
   }
 };
 
 // Constructor
 
 function BrowserGlue() {
+
+  this.__defineGetter__("_prefs", function() {
+    delete this._prefs;
+    return this._prefs = Cc["@mozilla.org/preferences-service;1"].
+                         getService(Ci.nsIPrefBranch);
+  });
+
+  this.__defineGetter__("_bundleService", function() {
+    delete this._bundleService;
+    return this._bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
+                                 getService(Ci.nsIStringBundleService);
+  });
+
+  this.__defineGetter__("_idleService", function() {
+    delete this._idleService;
+    return this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
+                           getService(Ci.nsIIdleService);
+  });
+
+  this.__defineGetter__("_observerService", function() {
+    delete this._observerService;
+    return this._observerService = Cc['@mozilla.org/observer-service;1'].
+                                   getService(Ci.nsIObserverService);
+  });
+
   this._init();
 }
 
 BrowserGlue.prototype = {
-  __prefs: null,
-  get _prefs() {
-    if (!this.__prefs)
-      this.__prefs = Cc["@mozilla.org/preferences-service;1"].
-                     getService(Ci.nsIPrefBranch);
-    return this.__prefs;
-  },
-
+  
   _saveSession: false,
 
   _setPrefToSaveSession: function()
   {
     this._prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
   },
 
   // nsIObserver implementation 
@@ -125,60 +144,67 @@ BrowserGlue.prototype = {
         break;
       case "session-save":
         this._setPrefToSaveSession();
         subject.QueryInterface(Ci.nsISupportsPRBool);
         subject.data = true;
         break;
       case "places-init-complete":
         this._initPlaces();
+        this._observerService.removeObserver(this, "places-init-complete");
+        // no longer needed, since history was initialized completely.
+        this._observerService.removeObserver(this, "places-database-locked");
+        break;
+      case "places-database-locked":
+        this._isPlacesDatabaseLocked = true;
+        // stop observing, so further attempts to load history service
+        // do not show the prompt.
+        this._observerService.removeObserver(this, "places-database-locked");
         break;
       case "idle":
-        if (this.idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
+        if (this._idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
           // Back up bookmarks.
           this._archiveBookmarks();
         }
         break;
     }
   }, 
 
   // initialization (called on application startup) 
   _init: function() 
   {
     // observer registration
-    const osvr = Cc['@mozilla.org/observer-service;1'].
-                 getService(Ci.nsIObserverService);
+    const osvr = this._observerService;
     osvr.addObserver(this, "quit-application", false);
     osvr.addObserver(this, "xpcom-shutdown", false);
     osvr.addObserver(this, "prefservice:after-app-defaults", false);
     osvr.addObserver(this, "final-ui-startup", false);
     osvr.addObserver(this, "sessionstore-windows-restored", false);
     osvr.addObserver(this, "browser:purge-session-history", false);
     osvr.addObserver(this, "quit-application-requested", false);
     osvr.addObserver(this, "quit-application-granted", false);
     osvr.addObserver(this, "session-save", false);
     osvr.addObserver(this, "places-init-complete", false);
+    osvr.addObserver(this, "places-database-locked", false);
   },
 
   // cleanup (called on application shutdown)
   _dispose: function() 
   {
     // observer removal 
-    const osvr = Cc['@mozilla.org/observer-service;1'].
-                 getService(Ci.nsIObserverService);
+    const osvr = this._observerService;
     osvr.removeObserver(this, "quit-application");
     osvr.removeObserver(this, "xpcom-shutdown");
     osvr.removeObserver(this, "prefservice:after-app-defaults");
     osvr.removeObserver(this, "final-ui-startup");
     osvr.removeObserver(this, "sessionstore-windows-restored");
     osvr.removeObserver(this, "browser:purge-session-history");
     osvr.removeObserver(this, "quit-application-requested");
     osvr.removeObserver(this, "quit-application-granted");
     osvr.removeObserver(this, "session-save");
-    osvr.removeObserver(this, "places-init-complete");
   },
 
   _onAppDefaults: function()
   {
     // apply distribution customizations (prefs)
     // other customizations are applied in _onProfileStartup()
     var distro = new DistributionCustomizer();
     distro.applyPrefDefaults();
@@ -201,26 +227,24 @@ BrowserGlue.prototype = {
     // apply distribution customizations
     // prefs are applied in _onAppDefaults()
     var distro = new DistributionCustomizer();
     distro.applyCustomizations();
 
     // handle any UI migration
     this._migrateUI();
 
-    const osvr = Cc['@mozilla.org/observer-service;1'].
-                 getService(Ci.nsIObserverService);
-    osvr.notifyObservers(null, "browser-ui-startup-complete", "");
+    this._observerService.notifyObservers(null, "browser-ui-startup-complete", "");
   },
 
   // profile shutdown handler (contains profile cleanup routines)
   _onProfileShutdown: function() 
   {
     this._shutdownPlaces();
-    this.idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
+    this._idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
     this.Sanitizer.onShutdown();
   },
 
   // Browser startup complete. All initial windows have opened.
   _onBrowserStartup: function()
   {
     // Show about:rights notification, if needed.
     if (this._shouldShowRights())
@@ -240,16 +264,25 @@ BrowserGlue.prototype = {
       args.AppendElement(str);
       const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
       const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
                getService(Ci.nsIWindowWatcher);
       ww.openWindow(null, EMURL, "_blank", EMFEATURES, args);
       this._prefs.clearUserPref(PREF_EM_NEW_ADDONS_LIST);
     }
+
+    // Load the "more info" page for a locked places.sqlite
+    // This property is set earlier in the startup process:
+    // nsPlacesDBFlush loads after profile-after-change and initializes
+    // the history service, which sends out places-database-locked
+    // which sets this property.
+    if (this._isPlacesDatabaseLocked) {
+      this._showPlacesLockedNotificationBox();
+    }
   },
 
   _onQuitRequest: function(aCancelQuit, aQuitType)
   {
     // If user has already dismissed quit request, then do nothing
     if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
       return;
 
@@ -290,24 +323,22 @@ BrowserGlue.prototype = {
       else
         showPrompt = this._prefs.getBoolPref("browser.tabs.warnOnClose");
     } catch (ex) {}
 
     if (!showPrompt)
       return false;
 
     var buttonChoice = 0;
-    var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
-                        getService(Ci.nsIStringBundleService);
-    var quitBundle = bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
-    var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
+    var quitBundle = this._bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
+    var brandBundle = this._bundleService.createBundle("chrome://branding/locale/brand.properties");
 
     var appName = brandBundle.GetStringFromName("brandShortName");
     var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle",
-                                                            [appName], 1);
+                                                          [appName], 1);
 
     var message;
     if (aQuitType == "restart")
       message = quitBundle.formatStringFromName("messageRestart",
                                                 [appName], 1);
     else if (windowcount == 1)
       message = quitBundle.formatStringFromName("messageNoWindows",
                                                 [appName], 1);
@@ -403,20 +434,18 @@ BrowserGlue.prototype = {
   },
 
   _showRightsNotification : function () {
     // Stick the notification onto the selected tab of the active browser window.
     var win = this.getMostRecentBrowserWindow();
     var browser = win.gBrowser; // for closure in notification bar callback
     var notifyBox = browser.getNotificationBox();
 
-    var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
-                        getService(Ci.nsIStringBundleService);
-    var brandBundle  = bundleService.createBundle("chrome://branding/locale/brand.properties");
-    var rightsBundle = bundleService.createBundle("chrome://browser/locale/aboutRights.properties");
+    var brandBundle  = this._bundleService.createBundle("chrome://branding/locale/brand.properties");
+    var rightsBundle = this._bundleService.createBundle("chrome://browser/locale/aboutRights.properties");
 
     var buttonLabel     = rightsBundle.GetStringFromName("buttonLabel");
     var buttonAccessKey = rightsBundle.GetStringFromName("buttonAccessKey");
     var productName     = brandBundle.GetStringFromName("brandFullName");
     var notifyText      = rightsBundle.formatStringFromName("notifyText", [productName], 1);
     
     var buttons = [
                     {
@@ -443,24 +472,16 @@ BrowserGlue.prototype = {
     if(typeof(Sanitizer) != "function") { // we should dynamically load the script
       Cc["@mozilla.org/moz/jssubscript-loader;1"].
       getService(Ci.mozIJSSubScriptLoader).
       loadSubScript("chrome://browser/content/sanitize.js", null);
     }
     return Sanitizer;
   },
 
-  _idleService: null,
-  get idleService() {
-    if (!this._idleService)
-      this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
-                          getService(Ci.nsIIdleService);
-    return this._idleService;
-  },
-
   /**
    * Initialize Places
    * - imports the bookmarks html file if bookmarks database is empty, try to
    *   restore bookmarks from a JSON backup if the backend indicates that the
    *   database was corrupt.
    *
    * These prefs can be set up by the frontend:
    *
@@ -477,21 +498,22 @@ BrowserGlue.prototype = {
    *   bookmarks.
    */
   _initPlaces: function bg__initPlaces() {
     // We must instantiate the history service since it will tell us if we
     // need to import or restore bookmarks due to first-run, corruption or
     // forced migration (due to a major schema change).
     var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
                   getService(Ci.nsINavHistoryService);
-    var databaseStatus = histsvc.databaseStatus;
 
     // If the database is corrupt or has been newly created we should
     // import bookmarks.
-    var importBookmarks = databaseStatus != histsvc.DATABASE_STATUS_OK;
+    var databaseStatus = histsvc.databaseStatus;
+    var importBookmarks = databaseStatus == histsvc.DATABASE_STATUS_CREATE ||
+                          databaseStatus == histsvc.DATABASE_STATUS_CORRUPT;
 
     // Check if user or an extension has required to import bookmarks.html
     var importBookmarksHTML = false;
     try {
       importBookmarksHTML =
         this._prefs.getBoolPref("browser.places.importBookmarksHTML");
       if (importBookmarksHTML)
         importBookmarks = true;
@@ -579,17 +601,17 @@ BrowserGlue.prototype = {
         this._prefs.setBoolPref("browser.places.importBookmarksHTML", false);
       if (restoreDefaultBookmarks)
         this._prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
                                 false);
     }
 
     // Initialize bookmark archiving on idle.
     // Once a day, either on idle or shutdown, bookmarks are backed up.
-    this.idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
+    this._idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
   },
 
   /**
    * Places shut-down tasks
    * - back up and archive bookmarks
    * - export bookmarks as HTML, if so configured
    *
    * Note: quit-application-granted notification is received twice
@@ -631,16 +653,54 @@ BrowserGlue.prototype = {
       try {
         maxBackups = this._prefs.getIntPref("browser.bookmarks.max_backups");
       } catch(ex) {}
 
       PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
     }
   },
 
+  /**
+   * Show the notificationBox for a locked places database.
+   */
+  _showPlacesLockedNotificationBox: function nsBrowserGlue__showPlacesLockedNotificationBox() {
+    var brandBundle  = this._bundleService.createBundle("chrome://branding/locale/brand.properties");
+    var applicationName = brandBundle.GetStringFromName("brandShortName");
+    var placesBundle = this._bundleService.createBundle("chrome://browser/locale/places/places.properties");
+    var title = placesBundle.GetStringFromName("lockPrompt.title");
+    var text = placesBundle.formatStringFromName("lockPrompt.text", [applicationName], 1);
+    var buttonText = placesBundle.GetStringFromName("lockPromptInfoButton.label");
+    var accessKey = placesBundle.GetStringFromName("lockPromptInfoButton.accessKey");
+
+    var helpTopic = "places-locked";
+    var url = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
+              getService(Components.interfaces.nsIURLFormatter).
+              formatURLPref("app.support.baseURL");
+    url += helpTopic;
+
+    var browser = this.getMostRecentBrowserWindow().gBrowser;
+
+    var buttons = [
+                    {
+                      label:     buttonText,
+                      accessKey: accessKey,
+                      popup:     null,
+                      callback:  function(aNotificationBar, aButton) {
+                        browser.selectedTab = browser.addTab(url);
+                      }
+                    }
+                  ];
+
+    var notifyBox = browser.getNotificationBox();
+    var box = notifyBox.appendNotification(text, title, null,
+                                           notifyBox.PRIORITY_CRITICAL_MEDIUM,
+                                           buttons);
+    box.persistence = -1; // Until user closes it
+  },
+
   _migrateUI: function bg__migrateUI() {
     var migration = 0;
     try {
       migration = this._prefs.getIntPref("browser.migration.version");
     } catch(ex) {}
 
     if (migration == 0) {
       // this code should always migrate pre-FF3 profiles to the current UI state
@@ -741,48 +801,48 @@ BrowserGlue.prototype = {
       return;
 
     var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
                 getService(Ci.nsINavBookmarksService);
     var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
                   getService(Ci.nsIAnnotationService);
 
     var callback = {
-      _placesBundle: Cc["@mozilla.org/intl/stringbundle;1"].
-                     getService(Ci.nsIStringBundleService).
-                     createBundle("chrome://browser/locale/places/places.properties"),
-
       _uri: function(aSpec) {
         return Cc["@mozilla.org/network/io-service;1"].
                getService(Ci.nsIIOService).
                newURI(aSpec, null, null);
       },
 
       runBatched: function() {
         var smartBookmarks = [];
         var bookmarksMenuIndex = 0;
         var bookmarksToolbarIndex = 0;
 
+        var placesBundle = Cc["@mozilla.org/intl/stringbundle;1"].
+                           getService(Ci.nsIStringBundleService).
+                           createBundle("chrome://browser/locale/places/places.properties");
+
         // MOST VISITED
         var smart = {queryId: "MostVisited", // don't change this
                      itemId: null,
-                     title: this._placesBundle.GetStringFromName("mostVisitedTitle"),
+                     title: placesBundle.GetStringFromName("mostVisitedTitle"),
                      uri: this._uri("place:queryType=" +
                                     Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
                                     "&sort=" +
                                     Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
                                     "&maxResults=" + MAX_RESULTS),
                      parent: bmsvc.toolbarFolder,
                      position: bookmarksToolbarIndex++};
         smartBookmarks.push(smart);
 
         // RECENTLY BOOKMARKED
         smart = {queryId: "RecentlyBookmarked", // don't change this
                  itemId: null,
-                 title: this._placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
+                 title: placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
                  uri: this._uri("place:folder=BOOKMARKS_MENU" +
                                 "&folder=UNFILED_BOOKMARKS" +
                                 "&folder=TOOLBAR" +
                                 "&queryType=" +
                                 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
                                 "&sort=" +
                                 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
                                 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
@@ -790,17 +850,17 @@ BrowserGlue.prototype = {
                                 "&excludeQueries=1"),
                  parent: bmsvc.bookmarksMenuFolder,
                  position: bookmarksMenuIndex++};
         smartBookmarks.push(smart);
 
         // RECENT TAGS
         smart = {queryId: "RecentTags", // don't change this
                  itemId: null,
-                 title: this._placesBundle.GetStringFromName("recentTagsTitle"),
+                 title: placesBundle.GetStringFromName("recentTagsTitle"),
                  uri: this._uri("place:"+
                     "type=" +
                     Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
                     "&sort=" +
                     Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
                     "&maxResults=" + MAX_RESULTS),
                  parent: bmsvc.bookmarksMenuFolder,
                  position: bookmarksMenuIndex++};
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -1164,28 +1164,34 @@
         if (parent.localName == "toolbarbutton" &&
             !PlacesControllerDragHelper.getSession())
           this._openedMenuButton = parent;
       ]]></handler>
 
       <handler event="popuphidden"><![CDATA[
         var popup = event.originalTarget;
 
-        // Avoid handling popupshowing of inner views
+        // Avoid handling popuphidden of inner views
         if (popup._resultNode && PlacesUIUtils.getViewForNode(popup) == this) {
           // UI performance: folder queries are cheap, keep the resultnode open
           // so we don't rebuild its contents whenever the popup is reopened.
           if (!PlacesUtils.nodeIsFolder(popup._resultNode))
             popup._resultNode.containerOpen = false;
         }
 
         var parent = popup.parentNode;
-        if (parent.localName == "toolbarbutton" &&
-            !PlacesControllerDragHelper.getSession())
-          this._openedMenuButton = null;
+        if (parent.localName == "toolbarbutton") {
+          if (!PlacesControllerDragHelper.getSession())
+            this._openedMenuButton = null;
+          // Clear the dragover attribute if present, if we are dragging into a
+          // folder in the hierachy of current opened popup we don't clear
+          // this attribute on clearOverFolder.  See Notify for closeTimer.
+          if (parent.hasAttribute("dragover"))
+            parent.removeAttribute("dragover");
+        }
       ]]></handler>
 
       <handler event="mousedown"><![CDATA[
         // Allow drag and drop of folders in Linux.
         // We must prevent popupshowing event from firing when shift is pressed.
         var target = event.originalTarget;
         if (event.button == 0 && event.shiftKey &&
             target.localName == "toolbarbutton" && target.type == "menu")
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -113,8 +113,15 @@ OrganizerQueryAllBookmarks=All Bookmarks
 # for url bar autocomplete results of type "tag"
 # See createResultLabel() in urlbarBindings.xml 
 tagResultLabel=Tag
 # LOCALIZATION NOTE (bookmarkResultLabel) :
 # This is what we use to form the label (for screen readers)
 # for url bar autocomplete results of type "bookmark"
 # See createResultLabel() in urlbarBindings.xml 
 bookmarkResultLabel=Bookmark
+
+# LOCALIZATION NOTE (lockPrompt.text)
+# %S will be replaced with the application name.
+lockPrompt.title=Browser Startup Error
+lockPrompt.text=The bookmarks and history system will not be functional because one of %S's files is in use by another application. Some security software can cause this problem.
+lockPromptInfoButton.label=Learn More
+lockPromptInfoButton.accessKey=L
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -116,24 +116,21 @@ classic.jar:
   skin/classic/browser/preferences/alwaysAsk.png            (preferences/alwaysAsk.png)
   skin/classic/browser/preferences/application.png          (preferences/application.png)
   skin/classic/browser/preferences/Options.png              (preferences/Options.png)
   skin/classic/browser/preferences/saveFile.png             (preferences/saveFile.png)
   skin/classic/browser/preferences/preferences.css          (preferences/preferences.css)
   skin/classic/browser/preferences/panebutton-active.png    (preferences/panebutton-active.png)
   skin/classic/browser/preferences/panebutton-inactive.png  (preferences/panebutton-inactive.png)
   skin/classic/browser/preferences/applications.css         (preferences/applications.css)
-  skin/classic/browser/tabbrowser/alltabs-box-bkgnd.png                  (tabbrowser/alltabs-box-bkgnd.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png             (tabbrowser/alltabs-box-bkgnd-icon.png)
   skin/classic/browser/tabbrowser/alltabs-box-overflow-bkgnd-animate.png (tabbrowser/alltabs-box-overflow-bkgnd-animate.png)
   skin/classic/browser/tabbrowser/newtab.png                             (tabbrowser/newtab.png)
   skin/classic/browser/tabbrowser/tab-arrow-start.png                    (tabbrowser/tab-arrow-start.png)
-  skin/classic/browser/tabbrowser/tab-arrow-start-bkgnd.png              (tabbrowser/tab-arrow-start-bkgnd.png)
   skin/classic/browser/tabbrowser/tab-arrow-end.png                      (tabbrowser/tab-arrow-end.png)
-  skin/classic/browser/tabbrowser/tab-arrow-end-bkgnd.png                (tabbrowser/tab-arrow-end-bkgnd.png)
   skin/classic/browser/tabbrowser/tabbrowser-tabs-bkgnd.png              (tabbrowser/tabbrowser-tabs-bkgnd.png)
   skin/classic/browser/tabbrowser/tabDragIndicator.png                   (tabbrowser/tabDragIndicator.png)
   skin/classic/browser/tabbrowser/tab-bkgnd.png                          (tabbrowser/tab-bkgnd.png)
   skin/classic/browser/urlbar/endcap.png                                 (urlbar/endcap.png)
   skin/classic/browser/urlbar/endcap-rtl.png                             (urlbar/endcap-rtl.png)
   skin/classic/browser/urlbar/endcap-focused.png                         (urlbar/endcap-focused.png)
   skin/classic/browser/urlbar/endcap-focused-rtl.png                     (urlbar/endcap-focused-rtl.png)
   skin/classic/browser/urlbar/startcap.png                               (urlbar/startcap.png)
deleted file mode 100644
index d0b203cc6ee4adff49ce4b1312789de53d1d2b11..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 0856361c10d12d2af966a7f3d94b1413c2371324..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 4bedf7dba3c5a7aa802f8e0ebb2be7ed259e7add..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -127,16 +127,17 @@ MOZ_UNIVERSALCHARDET = @MOZ_UNIVERSALCHA
 ACCESSIBILITY = @ACCESSIBILITY@
 MOZ_VIEW_SOURCE = @MOZ_VIEW_SOURCE@
 MOZ_XPINSTALL = @MOZ_XPINSTALL@
 MOZ_JSLOADER  = @MOZ_JSLOADER@
 MOZ_USE_NATIVE_UCONV = @MOZ_USE_NATIVE_UCONV@
 MOZ_BRANDING_DIRECTORY = @MOZ_BRANDING_DIRECTORY@
 XPCOM_USE_LEA = @XPCOM_USE_LEA@
 JS_ULTRASPARC_OPTS = @JS_ULTRASPARC_OPTS@
+JS_STATIC_BUILD = @JS_STATIC_BUILD@
 MOZ_ENABLE_POSTSCRIPT = @MOZ_ENABLE_POSTSCRIPT@
 MOZ_INSTALLER	= @MOZ_INSTALLER@
 MOZ_UPDATER	= @MOZ_UPDATER@
 MOZ_UPDATE_PACKAGING	= @MOZ_UPDATE_PACKAGING@
 MOZ_NO_ACTIVEX_SUPPORT = @MOZ_NO_ACTIVEX_SUPPORT@
 MOZ_ACTIVEX_SCRIPTING_SUPPORT = @MOZ_ACTIVEX_SCRIPTING_SUPPORT@
 MOZ_DISABLE_VISTA_SDK_REQUIREMENTS = @MOZ_DISABLE_VISTA_SDK_REQUIREMENTS@
 MOZ_DISABLE_PARENTAL_CONTROLS = @MOZ_DISABLE_PARENTAL_CONTROLS@
--- a/config/config.mk
+++ b/config/config.mk
@@ -68,18 +68,16 @@ COMMA = ,
 CHECK_VARS := \
  XPI_NAME \
  LIBRARY_NAME \
  MODULE \
  DEPTH \
  SHORT_LIBNAME \
  XPI_PKGNAME \
  INSTALL_EXTENSION_ID \
- SHARED_LIBRARY_NAME \
- STATIC_LIBRARY_NAME \
  $(NULL)
 
 # checks for internal spaces or trailing spaces in the variable
 # named by $x
 check-variable = $(if $(filter-out 0 1,$(words $($(x))z)),$(error Spaces are not allowed in $(x)))
 
 $(foreach x,$(CHECK_VARS),$(check-variable))
 
@@ -356,28 +354,16 @@ ifndef _ENABLE_PIC
 DSO_CFLAGS=
 ifeq ($(OS_ARCH)_$(HAVE_GCC3_ABI),Darwin_1)
 DSO_PIC_CFLAGS=-mdynamic-no-pic
 else
 DSO_PIC_CFLAGS=
 endif
 endif
 
-ifndef SHARED_LIBRARY_NAME
-ifdef LIBRARY_NAME
-SHARED_LIBRARY_NAME=$(LIBRARY_NAME)
-endif
-endif
-
-ifndef STATIC_LIBRARY_NAME
-ifdef LIBRARY_NAME
-STATIC_LIBRARY_NAME=$(LIBRARY_NAME)
-endif
-endif
-
 # This comes from configure
 ifdef MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 endif
 
 # Enable profile-based feedback
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
 ifdef MOZ_PROFILE_GENERATE
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -214,52 +214,52 @@ endif # ENABLE_TESTS
 #
 # Library rules
 #
 # If BUILD_STATIC_LIBS or FORCE_STATIC_LIB is set, build a static library.
 # Otherwise, build a shared library.
 #
 
 ifndef LIBRARY
-ifdef STATIC_LIBRARY_NAME
+ifdef LIBRARY_NAME
 ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
 ifdef SHORT_LIBNAME
-STATIC_LIBRARY_NAME	:= $(SHORT_LIBNAME)
+LIBRARY_NAME		:= $(SHORT_LIBNAME)
 endif
 endif
-LIBRARY			:= $(LIB_PREFIX)$(STATIC_LIBRARY_NAME).$(LIB_SUFFIX)
-endif # STATIC_LIBRARY_NAME
-endif # LIBRARY
+LIBRARY			:= $(LIB_PREFIX)$(LIBRARY_NAME).$(LIB_SUFFIX)
+endif
+endif
 
 ifndef HOST_LIBRARY
 ifdef HOST_LIBRARY_NAME
 HOST_LIBRARY		:= $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX)
 endif
 endif
 
 ifdef LIBRARY
 ifneq (_1,$(FORCE_SHARED_LIB)_$(BUILD_STATIC_LIBS))
 ifdef MKSHLIB
 
 ifdef LIB_IS_C_ONLY
 MKSHLIB			= $(MKCSHLIB)
 endif
 
 ifdef MAKE_FRAMEWORK
-SHARED_LIBRARY		:= $(SHARED_LIBRARY_NAME)
+SHARED_LIBRARY		:= $(LIBRARY_NAME)
 else
-SHARED_LIBRARY		:= $(DLL_PREFIX)$(SHARED_LIBRARY_NAME)$(DLL_SUFFIX)
+SHARED_LIBRARY		:= $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
 endif
 
 ifeq ($(OS_ARCH),OS2)
 DEF_FILE		:= $(SHARED_LIBRARY:.dll=.def)
 endif
 
 ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
-IMPORT_LIBRARY		:= $(LIB_PREFIX)$(SHARED_LIBRARY_NAME).$(IMPORT_LIB_SUFFIX)
+IMPORT_LIBRARY		:= $(LIB_PREFIX)$(LIBRARY_NAME).$(IMPORT_LIB_SUFFIX)
 endif
 
 ifdef MOZ_ENABLE_LIBXUL
 EMBED_MANIFEST_AT=2
 endif
 
 endif # MKSHLIB
 endif # FORCE_SHARED_LIB && !BUILD_STATIC_LIBS
@@ -314,32 +314,39 @@ COMPILE_PDBFILE = generated.pdb
 endif
 
 LINK_PDBFILE = $(basename $(@F)).pdb
 ifdef MOZ_DEBUG
 CODFILE=$(basename $(@F)).cod
 endif
 
 ifdef MOZ_MAPINFO
-ifdef SHARED_LIBRARY_NAME
-MAPFILE=$(SHARED_LIBRARY_NAME).map
+ifdef LIBRARY_NAME
+MAPFILE=$(LIBRARY_NAME).map
 else
 MAPFILE=$(basename $(@F)).map
 endif # LIBRARY_NAME
 endif # MOZ_MAPINFO
 
 ifdef DEFFILE
 OS_LDFLAGS += -DEF:$(DEFFILE)
 EXTRA_DEPS += $(DEFFILE)
 endif
 
 ifdef MAPFILE
 OS_LDFLAGS += -MAP:$(MAPFILE)
+#CFLAGS += -Fm$(MAPFILE)
+#CXXFLAGS += -Fm$(MAPFILE)
 endif
 
+#ifdef CODFILE
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#endif
+
 endif # !GNU_CC
 
 ifdef ENABLE_CXX_EXCEPTIONS
 ifdef GNU_CC
 CXXFLAGS		+= -fexceptions
 else
 ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
 CXXFLAGS		+= -GX
@@ -829,23 +836,23 @@ endif
 #
 # Rule to create list of libraries for final link
 #
 export::
 ifdef LIBRARY_NAME
 ifdef EXPORT_LIBRARY
 ifdef IS_COMPONENT
 ifdef BUILD_STATIC_LIBS
-	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMPS) $(STATIC_LIBRARY_NAME)
+	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMPS) $(LIBRARY_NAME)
 ifdef MODULE_NAME
 	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMP_NAMES) $(MODULE_NAME)
 endif
-endif # BUILD_STATIC_LIBS
-else  # !IS_COMPONENT
-	$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME)
+endif
+else
+	$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_LIBS) $(LIBRARY_NAME)
 endif # IS_COMPONENT
 endif # EXPORT_LIBRARY
 endif # LIBRARY_NAME
 
 # Create dependencies on static (and shared EXTRA_DSO_LIBS) libraries
 LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(LIBS))
 HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(HOST_LIBS))
 DSO_LDOPTS_DEPS = $(EXTRA_DSO_LIBS) $(filter %.$(LIB_SUFFIX), $(EXTRA_DSO_LDOPTS))
@@ -1171,17 +1178,17 @@ endif
 
 ifeq (,$(filter-out WINNT WINCE, $(OS_ARCH)))
 $(IMPORT_LIBRARY): $(SHARED_LIBRARY)
 endif
 
 ifeq ($(OS_ARCH),OS2)
 $(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS)
 	rm -f $@
-	echo LIBRARY $(SHARED_LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@
+	echo LIBRARY $(LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@
 	echo PROTMODE >> $@
 	echo CODE    LOADONCALL MOVEABLE DISCARDABLE >> $@
 	echo DATA    PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
 	echo EXPORTS >> $@
 ifeq ($(IS_COMPONENT),1)
 ifeq ($(HAS_EXTRAEXPORTS),1)
 ifndef MOZ_OS2_USE_DECLSPEC
 	$(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
--- a/configure.in
+++ b/configure.in
@@ -4374,16 +4374,17 @@ MOZ_XTF=1
 MOZ_XUL=1
 MOZ_XUL_APP=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
 NECKO_COOKIES=1
 NECKO_DISK_CACHE=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp gopher http res viewsource"
 NECKO_SMALL_BUFFERS=
+JS_STATIC_BUILD=
 XPC_IDISPATCH_SUPPORT=
 
 
 case "$target_os" in
 darwin*)
     ACCESSIBILITY=
     ;;
 *)
@@ -4466,16 +4467,17 @@ basic)
   MOZ_XPINSTALL=
   MOZ_XTF=
   MOZ_ZIPWRITER=
   NECKO_DISK_CACHE=
   NECKO_PROTOCOLS_DEFAULT="about data http file res"
   NECKO_SMALL_BUFFERS=1
   NS_DISABLE_LOGGING=1
   NS_PRINTING=
+  JS_STATIC_BUILD=1
   ;;
 
 minimal)
   MOZ_EMBEDDING_LEVEL_DEFAULT=
   MOZ_EMBEDDING_LEVEL_BASIC=
   MOZ_EMBEDDING_LEVEL_MINIMAL=1
   AC_DEFINE(MOZ_EMBEDDING_LEVEL_MINIMAL)
   ENABLE_TESTS=
@@ -4513,16 +4515,17 @@ minimal)
   MOZ_XUL=
   MOZ_ZIPWRITER=
   MOZ_RDF=
   NECKO_DISK_CACHE=
   NECKO_PROTOCOLS_DEFAULT="about data http file res"
   NECKO_SMALL_BUFFERS=1
   NS_DISABLE_LOGGING=1
   NS_PRINTING=
+  JS_STATIC_BUILD=1
   ;;
 
 *)
   AC_MSG_ERROR([Unrecognized value: --with-embedding-profile=$MOZ_EMBEDDING_PROFILE])
   ;;
 esac
 
 AC_SUBST(MOZ_EMBEDDING_LEVEL_DEFAULT)
@@ -7180,16 +7183,35 @@ if test -n "$MOZ_ENABLE_LIBXUL"; then
 else
     if test -n "$BUILD_STATIC_LIBS"; then
         AC_DEFINE(MOZ_STATIC_BUILD)
     fi
     XPCOM_LIBS="$DYNAMIC_XPCOM_LIBS"
 fi
 
 dnl ========================================================
+dnl = Force JS to be a static lib
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(js-static-build,
+[  --enable-js-static-build  Force js to be a static lib],
+    JS_STATIC_BUILD=1,
+    JS_STATIC_BUILD= )
+
+AC_SUBST(JS_STATIC_BUILD)
+        
+if test -n "$JS_STATIC_BUILD"; then
+    AC_DEFINE(EXPORT_JS_API)
+
+if test -z "$BUILD_STATIC_LIBS"; then
+    AC_MSG_ERROR([--enable-js-static-build is only compatible with --enable-static])
+fi
+
+fi
+
+dnl ========================================================
 dnl =
 dnl = Standalone module options
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Standalone module options (Not for building Mozilla))
 
 dnl Check for GLib and libIDL.
 dnl ========================================================
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -92,18 +92,18 @@ class nsIDocumentObserver;
 class nsBindingManager;
 class nsIDOMNodeList;
 class mozAutoSubtreeModified;
 struct JSObject;
 class nsFrameLoader;
 
 // IID for the nsIDocument interface
 #define NS_IDOCUMENT_IID      \
-{ 0x92b19d1c, 0x8f37, 0x4d4b, \
-  { 0xa3, 0x42, 0xb5, 0xc6, 0x8b, 0x54, 0xde, 0x6c } }
+{ 0x29f7a5d7, 0xb217, 0x4ea2, \
+  {0x95, 0x40, 0x46, 0x41, 0xb9, 0xf5, 0x99, 0xd9 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 //----------------------------------------------------------------------
 
 // Document interface.  This is implemented by all document objects in
 // Gecko.
@@ -1092,17 +1092,24 @@ public:
 
   /**
    * Enumerate the external resource documents associated with this document.
    * The enumerator callback should return PR_TRUE to continue enumerating, or
    * PR_FALSE to stop.  This callback will never get passed a null aDocument.
    */
   virtual void EnumerateExternalResources(nsSubDocEnumFunc aCallback,
                                           void* aData) = 0;
-  
+
+  /**
+   * Return whether the document is currently showing (in the sense of
+   * OnPageShow() having been called already and OnPageHide() not having been
+   * called yet.
+   */
+  PRBool IsShowing() { return mIsShowing; }
+
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
     //     do it here but nsNodeInfoManager is a concrete class that we don't
     //     want to expose to users of the nsIDocument API outside of Gecko.
   }
@@ -1166,16 +1173,19 @@ protected:
 
   // If true, whoever is creating the document has gotten it to the
   // point where it's safe to start layout on it.
   PRPackedBool mMayStartLayout;
   
   // True iff we've ever fired a DOMTitleChanged event for this document
   PRPackedBool mHaveFiredTitleChange;
 
+  // True iff IsShowing() should be returning true
+  PRPackedBool mIsShowing;
+  
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
   nsCString mContentLanguage;
   nsCString mContentType;
 
   // The document's security info
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -37,16 +37,17 @@
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIChannel;
 interface nsIDOMDocument;
 interface nsIDOMEventListener;
 interface nsIPrincipal;
 interface nsIScriptContext;
+interface nsIURI;
 interface nsIVariant;
 interface nsPIDOMWindow;
 
 [scriptable, uuid(6ce0a193-b033-4c3d-b748-f851b09261f5)]
 interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
   // event handler attributes
   attribute nsIDOMEventListener onabort;
   attribute nsIDOMEventListener onerror;
@@ -96,17 +97,17 @@ interface nsIXMLHttpRequestUpload : nsIX
  *   The 'onload', 'onerror', and 'onreadystatechange' attributes moved to
  *   nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using
  *   those.
  *
  * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless
  * you're aware of all the security implications.  And then think twice about
  * it.
  */
-[scriptable, uuid(48ce10a0-c585-4e8f-a5f5-1ac1e47cc501)]
+[scriptable, uuid(ad78bf21-2227-447e-8ed5-824a017c265f)]
 interface nsIXMLHttpRequest : nsISupports
 {
   /**
    * The request uses a channel in order to perform the
    * request.  This attribute represents the channel used
    * for the request.  NULL if the channel has not yet been
    * created.
    *
@@ -335,20 +336,23 @@ interface nsIXMLHttpRequest : nsISupport
    * Initialize the object for use from C++ code with the principal, script
    * context, and owner window that should be used.
    *
    * @param principal The principal to use for the request. This must not be
    *                  null.
    * @param scriptContext The script context to use for the request. May be
    *                      null.
    * @param ownerWindow The associated window for the request. May be null.
+   * @param baseURI The base URI to use when resolving relative URIs. May be
+   *                null.
    */
   [noscript] void init(in nsIPrincipal principal,
                        in nsIScriptContext scriptContext,
-                       in nsPIDOMWindow ownerWindow);
+                       in nsPIDOMWindow ownerWindow,
+                       in nsIURI baseURI);
 
   /**
    * Upload process can be tracked by adding event listener to |upload|.
    */
   readonly attribute nsIXMLHttpRequestUpload upload;
 
   /**
    * Meant to be a script-only mechanism for setting a callback function.
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1261,19 +1261,17 @@ nsContentSink::StartLayout(PRBool aIgnor
   nsCOMPtr<nsIPresShell> shell;
   while ((shell = iter.GetNextShell())) {
     // Make sure we don't call InitialReflow() for a shell that has
     // already called it. This can happen when the layout frame for
     // an iframe is constructed *between* the Embed() call for the
     // docshell in the iframe, and the content sink's call to OpenBody().
     // (Bug 153815)
 
-    PRBool didInitialReflow = PR_FALSE;
-    shell->GetDidInitialReflow(&didInitialReflow);
-    if (didInitialReflow) {
+    if (shell->DidInitialReflow()) {
       // XXX: The assumption here is that if something already
       // called InitialReflow() on this shell, it also did some of
       // the setup below, so we do nothing and just move on to the
       // next shell in the list.
 
       continue;
     }
 
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -72,17 +72,20 @@ nsDOMAttribute::nsDOMAttribute(nsDOMAttr
 
 
   // We don't add a reference to our content. It will tell us
   // to drop our reference when it goes away.
 }
 
 nsDOMAttribute::~nsDOMAttribute()
 {
-  NS_IF_RELEASE(mChild);
+  if (mChild) {
+    static_cast<nsTextNode*>(mChild)->UnbindFromAttribute();
+    NS_RELEASE(mChild);
+  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttribute)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttribute)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mChild)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_LISTENERMANAGER
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -7090,16 +7090,20 @@ nsDocument::OnPageShow(PRBool aPersisted
         nsCOMPtr<nsILink> link = do_QueryInterface(links->Item(i, PR_FALSE));
         if (link) {
           link->LinkAdded();
         }
       }
     }
   }
 
+  // Set mIsShowing before firing events, in case those event handlers
+  // move us around.
+  mIsShowing = PR_TRUE;
+  
   nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, aPersisted);
   DispatchEventToWindow(&event);
 }
 
 void
 nsDocument::OnPageHide(PRBool aPersisted)
 {
   // Send out notifications that our <link> elements are detached,
@@ -7116,16 +7120,20 @@ nsDocument::OnPageHide(PRBool aPersisted
         nsCOMPtr<nsILink> link = do_QueryInterface(links->Item(i, PR_FALSE));
         if (link) {
           link->LinkRemoved();
         }
       }
     }
   }
 
+  // Set mIsShowing before firing events, in case those event handlers
+  // move us around.
+  mIsShowing = PR_FALSE;
+  
   // Now send out a PageHide event.
   nsPageTransitionEvent event(PR_TRUE, NS_PAGE_HIDE, aPersisted);
   DispatchEventToWindow(&event);
 
   mVisible = PR_FALSE;
 }
 
 void
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -308,38 +308,47 @@ FirePageHideEvent(nsIDocShellTreeItem* a
 
   for (PRUint32 i = 0; i < kids.Length(); ++i) {
     if (kids[i]) {
       FirePageHideEvent(kids[i], aChromeEventHandler);
     }
   }
 }
 
+// The pageshow event is fired for a given document only if IsShowing() returns
+// the same thing as aFireIfShowing.  This gives us a way to fire pageshow only
+// on documents that are still loading or only on documents that are already
+// loaded.
 static void
 FirePageShowEvent(nsIDocShellTreeItem* aItem,
-                  nsIDOMEventTarget* aChromeEventHandler)
+                  nsIDOMEventTarget* aChromeEventHandler,
+                  PRBool aFireIfShowing)
 {
   PRInt32 childCount = 0;
   aItem->GetChildCount(&childCount);
   nsAutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
   kids.AppendElements(childCount);
   for (PRInt32 i = 0; i < childCount; ++i) {
     aItem->GetChildAt(i, getter_AddRefs(kids[i]));
   }
 
   for (PRUint32 i = 0; i < kids.Length(); ++i) {
     if (kids[i]) {
-      FirePageShowEvent(kids[i], aChromeEventHandler);
+      FirePageShowEvent(kids[i], aChromeEventHandler, aFireIfShowing);
     }
   }
 
-  nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, PR_TRUE);
   nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(aItem);
-  event.target = do_QueryInterface(doc);
-  nsEventDispatcher::Dispatch(aChromeEventHandler, nsnull, &event);
+  nsCOMPtr<nsIDocument> internalDoc = do_QueryInterface(doc);
+  NS_ASSERTION(internalDoc, "What happened here?");
+  if (internalDoc->IsShowing() == aFireIfShowing) {
+    nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, PR_TRUE);
+    event.target = do_QueryInterface(doc);
+    nsEventDispatcher::Dispatch(aChromeEventHandler, nsnull, &event);
+  }
 }
 
 static void
 SetTreeOwnerAndChromeEventHandlerOnDocshellTree(nsIDocShellTreeItem* aItem,
                                                 nsIDocShellTreeOwner* aOwner,
                                                 nsIDOMEventTarget* aHandler)
 {
   NS_PRECONDITION(aItem, "Must have item");
@@ -604,45 +613,48 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   if (mInSwap || aOther->mInSwap) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
   mInSwap = aOther->mInSwap = PR_TRUE;
 
-  // Fire pagehide events.  Note that we do NOT fire these in the normal way,
-  // but just fire them on the chrome event handlers.
+  // Fire pageshow events on still-loading pages, and then fire pagehide
+  // events.  Note that we do NOT fire these in the normal way, but just fire
+  // them on the chrome event handlers.
+  FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_FALSE);
+  FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_FALSE);
   FirePageHideEvent(ourTreeItem, ourChromeEventHandler);
   FirePageHideEvent(otherTreeItem, otherChromeEventHandler);
   
   nsIFrame* ourFrame = ourShell->GetPrimaryFrameFor(ourContent);
   nsIFrame* otherFrame = otherShell->GetPrimaryFrameFor(otherContent);
   if (!ourFrame || !otherFrame) {
     mInSwap = aOther->mInSwap = PR_FALSE;
-    FirePageShowEvent(ourTreeItem, ourChromeEventHandler);
-    FirePageShowEvent(otherTreeItem, otherChromeEventHandler);
+    FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_TRUE);
+    FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_TRUE);
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsIFrameFrame* ourFrameFrame = nsnull;
   CallQueryInterface(ourFrame, &ourFrameFrame);
   if (!ourFrameFrame) {
     mInSwap = aOther->mInSwap = PR_FALSE;
-    FirePageShowEvent(ourTreeItem, ourChromeEventHandler);
-    FirePageShowEvent(otherTreeItem, otherChromeEventHandler);
+    FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_TRUE);
+    FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_TRUE);
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // OK.  First begin to swap the docshells in the two nsIFrames
   rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
   if (NS_FAILED(rv)) {
     mInSwap = aOther->mInSwap = PR_FALSE;
-    FirePageShowEvent(ourTreeItem, ourChromeEventHandler);
-    FirePageShowEvent(otherTreeItem, otherChromeEventHandler);
+    FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_TRUE);
+    FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_TRUE);
     return rv;
   }
 
   // Now move the docshells to the right docshell trees.  Note that this
   // resets their treeowners to null.
   ourParentItem->RemoveChild(ourTreeItem);
   otherParentItem->RemoveChild(otherTreeItem);
   if (ourType == nsIDocShellTreeItem::typeContent) {
@@ -685,18 +697,18 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   if (ourFrame == ourShell->GetPrimaryFrameFor(ourContent) &&
       otherFrame == otherShell->GetPrimaryFrameFor(otherContent)) {
     ourFrameFrame->EndSwapDocShells(otherFrame);
   }
 
   ourParentDocument->FlushPendingNotifications(Flush_Layout);
   otherParentDocument->FlushPendingNotifications(Flush_Layout);
   
-  FirePageShowEvent(ourTreeItem, otherChromeEventHandler);
-  FirePageShowEvent(otherTreeItem, ourChromeEventHandler);
+  FirePageShowEvent(ourTreeItem, otherChromeEventHandler, PR_TRUE);
+  FirePageShowEvent(otherTreeItem, ourChromeEventHandler, PR_TRUE);
 
   mInSwap = aOther->mInSwap = PR_FALSE;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameLoader::Destroy()
 {
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1477,17 +1477,16 @@ GK_ATOM(cdataTagName, "#cdata-section")
 GK_ATOM(commentTagName, "#comment")
 GK_ATOM(documentNodeName, "#document")
 GK_ATOM(documentFragmentNodeName, "#document-fragment")
 GK_ATOM(documentTypeNodeName, "#document-type")
 GK_ATOM(processingInstructionTagName, "#processing-instruction")
 GK_ATOM(textTagName, "#text")
 
 // Frame types
-GK_ATOM(areaFrame, "AreaFrame")
 GK_ATOM(bcTableCellFrame, "BCTableCellFrame") // table cell in border collapsing model
 GK_ATOM(blockFrame, "BlockFrame")
 GK_ATOM(boxFrame, "BoxFrame")
 GK_ATOM(brFrame, "BRFrame")
 GK_ATOM(bulletFrame, "BulletFrame")
 GK_ATOM(columnSetFrame, "ColumnSetFrame")
 GK_ATOM(comboboxControlFrame, "ComboboxControlFrame")
 GK_ATOM(comboboxDisplayFrame, "ComboboxDisplayFrame")
@@ -1530,16 +1529,19 @@ GK_ATOM(tableColFrame, "TableColFrame")
 GK_ATOM(tableColGroupFrame, "TableColGroupFrame")
 GK_ATOM(tableFrame, "TableFrame")
 GK_ATOM(tableOuterFrame, "TableOuterFrame")
 GK_ATOM(tableRowGroupFrame, "TableRowGroupFrame")
 GK_ATOM(tableRowFrame, "TableRowFrame")
 GK_ATOM(textInputFrame,"TextInputFrame")
 GK_ATOM(textFrame, "TextFrame")
 GK_ATOM(viewportFrame, "ViewportFrame")
+#ifdef MOZ_XUL
+GK_ATOM(XULLabelFrame, "XULLabelFrame")
+#endif
 #ifdef MOZ_SVG
 GK_ATOM(svgAFrame, "SVGAFrame")
 GK_ATOM(svgClipPathFrame, "SVGClipPathFrame")
 GK_ATOM(svgDefsFrame, "SVGDefsFrame")
 GK_ATOM(svgFilterFrame, "SVGFilterFrame")
 GK_ATOM(svgForeignObjectFrame, "SVGForeignObjectFrame")
 GK_ATOM(svgGenericContainerFrame, "SVGGenericContainerFrame")
 GK_ATOM(svgGFrame, "SVGGFrame")
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1103,32 +1103,34 @@ nsXMLHttpRequest::Init()
   return NS_OK;
 }
 /**
  * This Init method should only be called by C++ consumers.
  */
 NS_IMETHODIMP
 nsXMLHttpRequest::Init(nsIPrincipal* aPrincipal,
                        nsIScriptContext* aScriptContext,
-                       nsPIDOMWindow* aOwnerWindow)
+                       nsPIDOMWindow* aOwnerWindow,
+                       nsIURI* aBaseURI)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
   // This object may have already been initialized in the other Init call above
   // if JS was on the stack. Clear the old values for mScriptContext and mOwner
   // if new ones are not supplied here.
 
   mPrincipal = aPrincipal;
   mScriptContext = aScriptContext;
   if (aOwnerWindow) {
     mOwner = aOwnerWindow->GetCurrentInnerWindow();
   }
   else {
     mOwner = nsnull;
   }
+  mBaseURI = aBaseURI;
 
   return NS_OK;
 }
 
 /**
  * This Initialize method is called from XPConnect via nsIJSNativeInitializer.
  */
 NS_IMETHODIMP
@@ -1821,17 +1823,20 @@ nsXMLHttpRequest::OpenRequest(const nsAC
     mState &= ~XML_HTTP_REQUEST_ASYNC;
   }
 
   mState &= ~XML_HTTP_REQUEST_MPART_HEADERS;
 
   nsCOMPtr<nsIDocument> doc = GetDocumentFromScriptContext(mScriptContext);
   
   nsCOMPtr<nsIURI> baseURI;
-  if (doc) {
+  if (mBaseURI) {
+    baseURI = mBaseURI;
+  }
+  else if (doc) {
     baseURI = doc->GetBaseURI();
   }
 
   rv = NS_NewURI(getter_AddRefs(uri), url, nsnull, baseURI);
   if (NS_FAILED(rv)) return rv;
 
   // mScriptContext should be initialized because of GetBaseURI() above.
   // Still need to consider the case that doc is nsnull however.
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -473,16 +473,18 @@ protected:
    * want to also be notified for.  These are inited lazily if we're
    * asked for the relevant interface.
    */
   nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
   nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
 
   nsIRequestObserver* mRequestObserver;
 
+  nsCOMPtr<nsIURI> mBaseURI;
+
   PRUint32 mState;
 
   nsRefPtr<nsXMLHttpRequestUpload> mUpload;
   PRUint64 mUploadTransferred;
   PRUint64 mUploadTotal;
   PRPackedBool mUploadComplete;
   PRUint64 mUploadProgress; // For legacy
   PRUint64 mUploadProgressMax; // For legacy
--- a/content/base/test/TestNativeXMLHttpRequest.cpp
+++ b/content/base/test/TestNativeXMLHttpRequest.cpp
@@ -84,17 +84,17 @@ nsresult TestNativeXMLHttpRequest()
   nsCOMPtr<nsIScriptSecurityManager> secman =
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
   TEST_ENSURE_SUCCESS(rv, "Couldn't get script security manager!");
 
   nsCOMPtr<nsIPrincipal> systemPrincipal;
   rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
   TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!");
 
-  rv = xhr->Init(systemPrincipal, nsnull, nsnull);
+  rv = xhr->Init(systemPrincipal, nsnull, nsnull, nsnull);
   TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
 
   rv = xhr->OpenRequest(getString, testURL, PR_FALSE, empty, empty);
   TEST_ENSURE_SUCCESS(rv, "OpenRequest failed!");
 
   rv = xhr->Send(nsnull);
   TEST_ENSURE_SUCCESS(rv, "Send failed!");
 
--- a/content/base/test/file_CrossSiteXHR_cache_server.sjs
+++ b/content/base/test/file_CrossSiteXHR_cache_server.sjs
@@ -1,45 +1,43 @@
-function d(s) { dump(s + "\n"); }
-
-function handleRequest(request, response)
-{
-  var query = {};
-  request.queryString.split('&').forEach(function (val) {
-    var [name, value] = val.split('=');
-    query[name] = unescape(value);
-  });
-
-  var isPreflight = request.method == "OPTIONS";
-
-  // Send response
-
-  response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
-
-  if (isPreflight) {
-    var secData = {};
-
-    if (request.hasHeader("Access-Control-Request-Headers")) {
-      var magicHeader =
-        request.getHeader("Access-Control-Request-Headers").split(",").
-        filter(function(name) /^magic-/.test(name))[0];
-    }
-
-    if (magicHeader) {
-      secData = eval(unescape(magicHeader.substr(6)));
-      secData.allowHeaders = (secData.allowHeaders || "") + "," + magicHeader;
-    }
-
-    if (secData.allowHeaders)
-      response.setHeader("Access-Control-Allow-Headers", secData.allowHeaders);
-
-    if (secData.allowMethods)
-      response.setHeader("Access-Control-Allow-Methods", secData.allowMethods);
-
-    if (secData.cacheTime)
-      response.setHeader("Access-Control-Max-Age", secData.cacheTime.toString());
-
-    return;
-  }
-
-  response.setHeader("Content-Type", "application/xml", false);
-  response.write("<res>hello pass</res>\n");
-}
+function handleRequest(request, response)
+{
+  var query = {};
+  request.queryString.split('&').forEach(function (val) {
+    var [name, value] = val.split('=');
+    query[name] = unescape(value);
+  });
+
+  var isPreflight = request.method == "OPTIONS";
+
+  // Send response
+
+  response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
+
+  if (isPreflight) {
+    var secData = {};
+
+    if (request.hasHeader("Access-Control-Request-Headers")) {
+      var magicHeader =
+        request.getHeader("Access-Control-Request-Headers").split(",").
+        filter(function(name) /^magic-/.test(name))[0];
+    }
+
+    if (magicHeader) {
+      secData = eval(unescape(magicHeader.substr(6)));
+      secData.allowHeaders = (secData.allowHeaders || "") + "," + magicHeader;
+    }
+
+    if (secData.allowHeaders)
+      response.setHeader("Access-Control-Allow-Headers", secData.allowHeaders);
+
+    if (secData.allowMethods)
+      response.setHeader("Access-Control-Allow-Methods", secData.allowMethods);
+
+    if (secData.cacheTime)
+      response.setHeader("Access-Control-Max-Age", secData.cacheTime.toString());
+
+    return;
+  }
+
+  response.setHeader("Content-Type", "application/xml", false);
+  response.write("<res>hello pass</res>\n");
+}
--- a/content/base/test/file_CrossSiteXHR_server.sjs
+++ b/content/base/test/file_CrossSiteXHR_server.sjs
@@ -1,87 +1,101 @@
-function handleRequest(request, response)
-{
-  try {
-  var query = {};
-  request.queryString.split('&').forEach(function (val) {
-    [name, value] = val.split('=');
-    query[name] = unescape(value);
-  });
-
-  var isPreflight = request.method == "OPTIONS";
-
-  // Check that request was correct
-  if (!isPreflight && "headers" in query) {
-    headers = eval(query.headers);
-    for(headerName in headers) {
-      if (request.getHeader(headerName) != headers[headerName]) {
-        throw "Header " + headerName + " had wrong value. Expected " +
-              headers[headerName] + " got " + request.getHeader(headerName);
-      }
-    }
-  }
-  if (isPreflight && "requestHeaders" in query &&
-      request.getHeader("Access-Control-Request-Headers") != query.requestHeaders) {
-    throw "Access-Control-Request-Headers had wrong value. Expected " +
-          query.requestHeaders + " got " +
-          request.getHeader("Access-Control-Request-Headers");
-  }
-  if (isPreflight && "requestMethod" in query &&
-      request.getHeader("Access-Control-Request-Method") != query.requestMethod) {
-    throw "Access-Control-Request-Method had wrong value. Expected " +
-          query.requestMethod + " got " +
-          request.getHeader("Access-Control-Request-Method");
-  }
-  if ("origin" in query && request.getHeader("Origin") != query.origin) {
-    throw "Origin had wrong value. Expected " + query.origin + " got " +
-          request.getHeader("Origin");
-  }
-  if ("cookie" in query) {
-    cookies = {};
-    request.getHeader("Cookie").split(/ *; */).forEach(function (val) {
-      [name, value] = val.split('=');
-      cookies[name] = unescape(value);
-    });
-    
-    query.cookie.split(",").forEach(function (val) {
-      [name, value] = val.split('=');
-      if (cookies[name] != value) {
-        throw "Cookie " + name  + " had wrong value. Expected " + value +
-              " got " + cookies[name];
-      }
-    });
-  }
-  if ("noCookie" in query && request.hasHeader("Cookie")) {
-    throw "Got cookies when didn't expect to";
-  }
-
-
-  // Send response
-       
-  if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight))
-    response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
-
-  if (query.allowCred)
-    response.setHeader("Access-Control-Allow-Credentials", "true");
-
-  if (query.setCookie)
-    response.setHeader("Set-Cookie", query.setCookie + "; path=/");
-
-
-  if (isPreflight) {
-    if (query.allowHeaders)
-      response.setHeader("Access-Control-Allow-Headers", query.allowHeaders);
-
-    if (query.allowMethods)
-      response.setHeader("Access-Control-Allow-Methods", query.allowMethods);
-
-    return;
-  }
-
-  response.setHeader("Content-Type", "application/xml", false);
-  response.write("<res>hello pass</res>\n");
-  
-  } catch (e) {
-    dump(e + "\n");
-    throw e;
-  }
-}
+function handleRequest(request, response)
+{
+  var query = {};
+  request.queryString.split('&').forEach(function (val) {
+    [name, value] = val.split('=');
+    query[name] = unescape(value);
+  });
+
+  var isPreflight = request.method == "OPTIONS";
+
+  // Check that request was correct
+
+  if (!isPreflight && "headers" in query) {
+    headers = eval(query.headers);
+    for(headerName in headers) {
+      if (request.getHeader(headerName) != headers[headerName]) {
+        sendHttp500(response,
+          "Header " + headerName + " had wrong value. Expected " +
+          headers[headerName] + " got " + request.getHeader(headerName));
+        return;
+      }
+    }
+  }
+
+  if (isPreflight && "requestHeaders" in query &&
+      request.getHeader("Access-Control-Request-Headers") != query.requestHeaders) {
+    sendHttp500(response,
+      "Access-Control-Request-Headers had wrong value. Expected " +
+      query.requestHeaders + " got " +
+      request.getHeader("Access-Control-Request-Headers"));
+    return;
+  }
+
+  if (isPreflight && "requestMethod" in query &&
+      request.getHeader("Access-Control-Request-Method") != query.requestMethod) {
+    sendHttp500(response,
+      "Access-Control-Request-Method had wrong value. Expected " +
+      query.requestMethod + " got " +
+      request.getHeader("Access-Control-Request-Method"));
+    return;
+  }
+
+  if ("origin" in query && request.getHeader("Origin") != query.origin) {
+    sendHttp500(response,
+      "Origin had wrong value. Expected " + query.origin + " got " +
+      request.getHeader("Origin"));
+    return;
+  }
+
+  if ("cookie" in query) {
+    cookies = {};
+    request.getHeader("Cookie").split(/ *; */).forEach(function (val) {
+      [name, value] = val.split('=');
+      cookies[name] = unescape(value);
+    });
+    
+    query.cookie.split(",").forEach(function (val) {
+      [name, value] = val.split('=');
+      if (cookies[name] != value) {
+        sendHttp500(response,
+          "Cookie " + name  + " had wrong value. Expected " + value +
+          " got " + cookies[name]);
+        return;
+      }
+    });
+  }
+
+  if ("noCookie" in query && request.hasHeader("Cookie")) {
+    sendHttp500(response,
+      "Got cookies when didn't expect to: " + request.getHeader("Cookie"));
+    return;
+  }
+
+  // Send response
+       
+  if (query.allowOrigin && (!isPreflight || !query.noAllowPreflight))
+    response.setHeader("Access-Control-Allow-Origin", query.allowOrigin);
+
+  if (query.allowCred)
+    response.setHeader("Access-Control-Allow-Credentials", "true");
+
+  if (query.setCookie)
+    response.setHeader("Set-Cookie", query.setCookie + "; path=/");
+
+  if (isPreflight) {
+    if (query.allowHeaders)
+      response.setHeader("Access-Control-Allow-Headers", query.allowHeaders);
+
+    if (query.allowMethods)
+      response.setHeader("Access-Control-Allow-Methods", query.allowMethods);
+
+    return;
+  }
+
+  response.setHeader("Content-Type", "application/xml", false);
+  response.write("<res>hello pass</res>\n");
+}
+
+function sendHttp500(response, text) {
+  response.setStatusLine(null, 500, text);
+}
--- a/content/base/test/test_CrossSiteXHR.html
+++ b/content/base/test/test_CrossSiteXHR.html
@@ -1,574 +1,574 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
-  <title>Test for Cross Site XMLHttpRequest</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body onload="gen.next()">
-<p id="display">
-<iframe id=loader></iframe>
-</p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.8">
-
-SimpleTest.waitForExplicitFinish();
-
-var origins =
-  [['http://example.org'],
-   ['http://example.org:80', 'http://example.org'],
-   ['http://sub1.test1.example.org'],
-   ['http://test2.example.org:8000'],
-   //['https://example.com:443'],
-   //['https://sub1.test1.example.com:443'],
-   ['http://sub1.\xe4lt.example.org:8000', 'http://sub1.xn--lt-uia.example.org:8000'],
-   ['http://sub2.\xe4lt.example.org', 'http://sub2.xn--lt-uia.example.org'],
-   ['http://ex\xe4mple.test', 'http://xn--exmple-cua.test'],
-   ['http://\u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1.\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae',
-    'http://xn--hxajbheg2az3al.xn--jxalpdlp'],
-   ];
-
-window.addEventListener("message", function(e) {
-  gen.send(e.data);
-}, false);
-
-gen = runTest();
-
-function runTest() {
-  var loader = document.getElementById('loader');
-  var loaderWindow = loader.contentWindow;
-  loader.onload = function () { gen.next() };
-
-  // Test preflight-less requests
-  baseURL = "http://localhost:8888/tests/content/base/test/" +
-             "file_CrossSiteXHR_server.sjs?";
-  for each(originPair in origins) {
-    origin = originPair[1] || originPair[0];
-
-    loader.src = originPair[0] + "/tests/content/base/test/file_CrossSiteXHR_inner.html";
-    yield;
-
-    port = /:\d+/;
-    passTests = [
-      origin,
-      "*",
-      " \t " + origin + "\t \t",
-      "\t \t* \t ",
-    ];
-    failTests = [
-      "",
-      " ",
-      port.test(origin) ? origin.replace(port, "")
-                        : origin + ":1234",
-      port.test(origin) ? origin.replace(port, ":")
-                        : origin + ":",
-      origin + "/",
-      origin + "#",
-      origin + "?",
-      origin + "\\",
-      origin + "%",
-      origin + "@",
-      origin + "/hello",
-      "foo:bar@" + origin,
-      "* " + origin,
-      origin + " " + origin,
-      "allow <" + origin + ">",
-      "<" + origin + ">",
-      "<*>",
-      origin.substr(0, 5) == "https" ? origin.replace("https", "http")
-                                     : origin.replace("http", "https"),
-      origin.replace("://", "://www."),
-      origin.replace("://", ":// "),
-      origin.replace(/\/[^.]+\./, "/"),
-    ];
-
-    for each(method in ["GET", "POST"]) {
-      var headers = method == "POST" ?
-        { "Content-Type": "text/plain" } :
-        null;
-
-      for each(allowOrigin in passTests) {
-        req = {
-          url: baseURL +
-               "allowOrigin=" + escape(allowOrigin) +
-               "&origin=" + escape(origin),
-          method: method,
-          headers: headers,
-        };
-        loaderWindow.postMessage(req.toSource(), origin);
-
-        res = eval(yield);
-        is(res.didFail, false, "shouldn't have failed");
-        is(res.status, 200, "wrong status");
-        is(res.responseXML,
-           "<res>hello pass</res>",
-           "wrong responseXML in test for " + allowOrigin);
-        is(res.responseText, "<res>hello pass</res>\n",
-           "wrong responseText in test for " + allowOrigin);
-        is(res.events.join(","),
-           "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
-           "wrong responseText in test for " + allowOrigin);
-      }
-
-      for each(allowOrigin in failTests) {
-        req = {
-          url: baseURL + "allowOrigin=" + escape(allowOrigin),
-          method: method,
-          headers: headers,
-        };
-        loaderWindow.postMessage(req.toSource(), origin);
-
-        res = eval(yield);
-        is(res.didFail, true, "should have failed for " + allowOrigin);
-        is(res.responseText, "", "should have no text for " + allowOrigin);
-        is(res.status, 0, "should have no status for " + allowOrigin);
-        is(res.responseXML, null, "should have no XML for " + allowOrigin);
-        is(res.events.join(","),
-           "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
-           "wrong events in test for " + allowOrigin);
-        is(res.progressEvents, 0,
-           "wrong events in test for " + allowOrigin);
-      }
-    }
-  }
-
-  // Test preflighted requests
-  loader.src = "http://example.org/tests/content/base/test/file_CrossSiteXHR_inner.html";
-  origin = "http://example.org";
-  yield;
-
-  passTests = [{ method: "GET",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "second-header": "secondValue",
-                            "third-header": "thirdValue" },
-                 allowHeaders: "x-my-header, second-header, third-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "second-header": "secondValue",
-                            "third-header": "thirdValue" },
-                 allowHeaders: "x-my-header,second-header,third-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "second-header": "secondValue",
-                            "third-header": "thirdValue" },
-                 allowHeaders: "x-my-header ,second-header ,third-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "second-header": "secondValue",
-                            "third-header": "thirdValue" },
-                 allowHeaders: "x-my-header , second-header , third-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "second-header": "secondValue" },
-                 allowHeaders: ",  x-my-header, , ,, second-header, ,   ",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "second-header": "secondValue" },
-                 allowHeaders: "x-my-header, second-header, unused-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "X-My-Header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header": "secondValue" },
-                 allowHeaders: "x-my-header, long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header",
-               },
-               { method: "GET",
-                 headers: { "x-my%-header": "myValue" },
-                 allowHeaders: "x-my%-header",
-               },
-               { method: "GET",
-                 headers: { "Content-Type": "baz/bin",
-                            "Accept": "foo/bar",
-                            "Accept-Language": "sv-SE" },
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "text/plain" },
-                 noAllowPreflight: 1,
-               },
-               { method: "POST",
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "foo/bar" },
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "text/plain",
-                            "Accept": "foo/bar",
-                            "Accept-Language": "sv-SE" },
-                 noAllowPreflight: 1,
-               },
-               { method: "POST",
-                 headers: { "Accept": "foo/bar",
-                            "Accept-Language": "sv-SE",
-                            "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header",
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "text/plain",
-                            "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header",
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "foo/bar",
-                            "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header",
-               },
-               { method: "POST",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header",
-               },
-               { method: "POST",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header, $_%",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "POST, PUT, XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "POST, XXDELETE, PUT",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "XXDELETE, POST, PUT",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "POST ,PUT ,XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "POST,PUT,XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "POST , PUT , XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "  ,,  PUT ,,  ,    , XXDELETE  ,  ,",
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "text/plain" },
-                 uploadProgress: "uploadprogress",
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "text/plain" },
-                 uploadProgress: "progress",
-               },
-               ];
-  failTests = [{ method: "GET",
-                 headers: { "x-my-header": "myValue" },
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "y-my-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header y-my-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header, y-my-header z",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue" },
-                 allowHeaders: "x-my-header, y-my-he(ader",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "myValue",
-                            "y-my-header": "secondValue" },
-                 allowHeaders: "x-my-header",
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "" },
-               },
-               { method: "GET",
-                 headers: { "x-my-header": "",
-                            "y-my-header": "" },
-                 allowHeaders: "x-my-header",
-               },
-               { method: "POST",
-                 noAllowPreflight: 1,
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "foo/bar" },
-                 noAllowPreflight: 1,
-               },
-               { method: "XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "PUT",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "XXDELETEZ",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "XXDELETE PUT",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "XXDELETE, PUT Z",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "XXDELETE, PU(T",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "PUT XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "PUT Z, XXDELETE",
-               },
-               { method: "XXDELETE",
-                 allowMethods: "PU(T, XXDELETE",
-               },
-               { method: "MYMETHOD",
-                 allowMethods: "myMethod",
-               },
-               { method: "PUT",
-                 allowMethods: "put",
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "text/plain" },
-                 noAllowPreflight: 1,
-                 uploadProgress: "uploadprogress",
-               },
-               { method: "POST",
-                 headers: { "Content-Type": "text/plain" },
-                 noAllowPreflight: 1,
-                 uploadProgress: "progress",
-               },
-               ];
-
-  for each(test in passTests) {
-    req = {
-      url: baseURL + "&allowOrigin=" + escape(origin) +
-           "&origin=" + escape(origin) +
-           "&requestMethod=" + test.method,
-      method: test.method,
-      headers: test.headers,
-      uploadProgress: test.uploadProgress,
-    };
-
-    if (test.noAllowPreflight)
-      req.url += "&noAllowPreflight";
-
-    if ("headers" in test) {
-      req.url += "&headers=" + escape(test.headers.toSource());
-      reqHeaders =
-        escape([name for (name in test.headers)].filter(function(name)
-          name != "Content-Type" &&
-          name != "Accept" &&
-          name != "Accept-Language").join(","));
-      req.url += reqHeaders ? "&requestHeaders=" + reqHeaders : "";
-    }
-    if ("allowHeaders" in test)
-      req.url += "&allowHeaders=" + escape(test.allowHeaders);
-    if ("allowMethods" in test)
-      req.url += "&allowMethods=" + escape(test.allowMethods);
-
-    loaderWindow.postMessage(req.toSource(), origin);
-
-    res = eval(yield);
-    is(res.didFail, false,
-      "shouldn't have failed in test for " + test.toSource());
-    is(res.status, 200, "wrong status in test for " + test.toSource());
-    is(res.responseXML, "<res>hello pass</res>",
-       "wrong responseXML in test for " + test.toSource());
-    is(res.responseText, "<res>hello pass</res>\n",
-       "wrong responseText in test for " + test.toSource());
-    is(res.events.join(","),
-       "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
-       "wrong responseText in test for " + test.toSource());
-  }
-
-  for each(test in failTests) {
-    req = {
-      url: baseURL + "allowOrigin=" + escape(origin),
-      method: test.method,
-      headers: test.headers,
-      uploadProgress: test.uploadProgress,
-    };
-
-    if (test.noAllowPreflight)
-      req.url += "&noAllowPreflight";
-
-    if ("allowHeaders" in test)
-      req.url += "&allowHeaders=" + escape(test.allowHeaders);
-    if ("allowMethods" in test)
-      req.url += "&allowMethods=" + escape(test.allowMethods);
-
-    loaderWindow.postMessage(req.toSource(), origin);
-
-    res = eval(yield);
-    is(res.didFail, true,
-      "should have failed in test for " + test.toSource());
-    is(res.status, 0, "wrong status in test for " + test.toSource());
-    is(res.responseXML, null,
-       "wrong responseXML in test for " + test.toSource());
-    is(res.responseText, "",
-       "wrong responseText in test for " + test.toSource());
-    is(res.events.join(","),
-       "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
-       "wrong events in test for " + test.toSource());
-    is(res.progressEvents, 0,
-       "wrong events in test for " + test.toSource());
-  }
-
-
-  // Test cookie behavior
-  tests = [{ pass: 1,
-             method: "GET",
-             withCred: 1,
-             allowCred: 1,
-           },
-           { pass: 0,
-             method: "GET",
-             withCred: 1,
-             allowCred: 0,
-           },
-           { pass: 0,
-             method: "GET",
-             withCred: 1,
-             allowCred: 1,
-             origin: "*",
-           },
-           { pass: 1,
-             method: "GET",
-             withCred: 0,
-             allowCred: 1,
-             origin: "*",
-           },
-           { pass: 1,
-             method: "GET",
-             setCookie: "a=1",
-             withCred: 1,
-             allowCred: 1,
-           },
-           { pass: 1,
-             method: "GET",
-             cookie: "a=1",
-             withCred: 1,
-             allowCred: 1,
-           },
-           { pass: 1,
-             method: "GET",
-             noCookie: 1,
-             withCred: 0,
-             allowCred: 1,
-           },
-           { pass: 0,
-             method: "GET",
-             noCookie: 1,
-             withCred: 1,
-             allowCred: 1,
-           },
-           { pass: 1,
-             method: "GET",
-             setCookie: "a=2",
-             withCred: 0,
-             allowCred: 1,
-           },
-           { pass: 1,
-             method: "GET",
-             cookie: "a=1",
-             withCred: 1,
-             allowCred: 1,
-           },
-           { pass: 1,
-             method: "GET",
-             setCookie: "a=2",
-             withCred: 1,
-             allowCred: 1,
-           },
-           { pass: 1,
-             method: "GET",
-             cookie: "a=2",
-             withCred: 1,
-             allowCred: 1,
-           },
-           ];
-
-  for each(test in tests) {
-    req = {
-      url: baseURL + "allowOrigin=" + escape(test.origin || origin),
-      method: test.method,
-      headers: test.headers,
-      withCred: test.withCred,
-    };
-
-    if (test.allowCred)
-      req.url += "&allowCred";
-
-    if (test.setCookie)
-      req.url += "&setCookie=" + escape(test.setCookie);
-    if (test.cookie)
-      req.url += "&cookie=" + escape(test.cookie);
-    if (test.noCookie)
-      req.url += "&noCookie";
-
-    if ("allowHeaders" in test)
-      req.url += "&allowHeaders=" + escape(test.allowHeaders);
-    if ("allowMethods" in test)
-      req.url += "&allowMethods=" + escape(test.allowMethods);
-
-    loaderWindow.postMessage(req.toSource(), origin);
-
-    res = eval(yield);
-    if (test.pass) {
-      is(res.didFail, false,
-        "shouldn't have failed in test for " + test.toSource());
-      is(res.status, 200, "wrong status in test for " + test.toSource());
-      is(res.responseXML, "<res>hello pass</res>",
-         "wrong responseXML in test for " + test.toSource());
-      is(res.responseText, "<res>hello pass</res>\n",
-         "wrong responseText in test for " + test.toSource());
-      is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
-         "wrong responseText in test for " + test.toSource());
-    }
-    else {
-      is(res.didFail, true,
-        "should have failed in test for " + test.toSource());
-      is(res.status, 0, "wrong status in test for " + test.toSource());
-      is(res.responseXML, null,
-         "wrong responseXML in test for " + test.toSource());
-      is(res.responseText, "",
-         "wrong responseText in test for " + test.toSource());
-      is(res.events.join(","),
-         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
-         "wrong events in test for " + test.toSource());
-      is(res.progressEvents, 0,
-         "wrong events in test for " + test.toSource());
-    }
-  }
-
-  SimpleTest.finish();
-
-  yield;
-}
-
-</script>
-</pre>
-</body>
-</html>
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
+  <title>Test for Cross Site XMLHttpRequest</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="gen.next()">
+<p id="display">
+<iframe id=loader></iframe>
+</p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.8">
+
+SimpleTest.waitForExplicitFinish();
+
+var origins =
+  [['http://example.org'],
+   ['http://example.org:80', 'http://example.org'],
+   ['http://sub1.test1.example.org'],
+   ['http://test2.example.org:8000'],
+   //['https://example.com:443'],
+   //['https://sub1.test1.example.com:443'],
+   ['http://sub1.\xe4lt.example.org:8000', 'http://sub1.xn--lt-uia.example.org:8000'],
+   ['http://sub2.\xe4lt.example.org', 'http://sub2.xn--lt-uia.example.org'],
+   ['http://ex\xe4mple.test', 'http://xn--exmple-cua.test'],
+   ['http://\u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1.\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae',
+    'http://xn--hxajbheg2az3al.xn--jxalpdlp'],
+   ];
+
+window.addEventListener("message", function(e) {
+  gen.send(e.data);
+}, false);
+
+gen = runTest();
+
+function runTest() {
+  var loader = document.getElementById('loader');
+  var loaderWindow = loader.contentWindow;
+  loader.onload = function () { gen.next() };
+
+  // Test preflight-less requests
+  baseURL = "http://localhost:8888/tests/content/base/test/" +
+             "file_CrossSiteXHR_server.sjs?";
+  for each(originPair in origins) {
+    origin = originPair[1] || originPair[0];
+
+    loader.src = originPair[0] + "/tests/content/base/test/file_CrossSiteXHR_inner.html";
+    yield;
+
+    port = /:\d+/;
+    passTests = [
+      origin,
+      "*",
+      " \t " + origin + "\t \t",
+      "\t \t* \t ",
+    ];
+    failTests = [
+      "",
+      " ",
+      port.test(origin) ? origin.replace(port, "")
+                        : origin + ":1234",
+      port.test(origin) ? origin.replace(port, ":")
+                        : origin + ":",
+      origin + "/",
+      origin + "#",
+      origin + "?",
+      origin + "\\",
+      origin + "%",
+      origin + "@",
+      origin + "/hello",
+      "foo:bar@" + origin,
+      "* " + origin,
+      origin + " " + origin,
+      "allow <" + origin + ">",
+      "<" + origin + ">",
+      "<*>",
+      origin.substr(0, 5) == "https" ? origin.replace("https", "http")
+                                     : origin.replace("http", "https"),
+      origin.replace("://", "://www."),
+      origin.replace("://", ":// "),
+      origin.replace(/\/[^.]+\./, "/"),
+    ];
+
+    for each(method in ["GET", "POST"]) {
+      var headers = method == "POST" ?
+        { "Content-Type": "text/plain" } :
+        null;
+
+      for each(allowOrigin in passTests) {
+        req = {
+          url: baseURL +
+               "allowOrigin=" + escape(allowOrigin) +
+               "&origin=" + escape(origin),
+          method: method,
+          headers: headers,
+        };
+        loaderWindow.postMessage(req.toSource(), origin);
+
+        res = eval(yield);
+        is(res.didFail, false, "shouldn't have failed");
+        is(res.status, 200, "wrong status");
+        is(res.responseXML,
+           "<res>hello pass</res>",
+           "wrong responseXML in test for " + allowOrigin);
+        is(res.responseText, "<res>hello pass</res>\n",
+           "wrong responseText in test for " + allowOrigin);
+        is(res.events.join(","),
+           "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+           "wrong responseText in test for " + allowOrigin);
+      }
+
+      for each(allowOrigin in failTests) {
+        req = {
+          url: baseURL + "allowOrigin=" + escape(allowOrigin),
+          method: method,
+          headers: headers,
+        };
+        loaderWindow.postMessage(req.toSource(), origin);
+
+        res = eval(yield);
+        is(res.didFail, true, "should have failed for " + allowOrigin);
+        is(res.responseText, "", "should have no text for " + allowOrigin);
+        is(res.status, 0, "should have no status for " + allowOrigin);
+        is(res.responseXML, null, "should have no XML for " + allowOrigin);
+        is(res.events.join(","),
+           "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+           "wrong events in test for " + allowOrigin);
+        is(res.progressEvents, 0,
+           "wrong events in test for " + allowOrigin);
+      }
+    }
+  }
+
+  // Test preflighted requests
+  loader.src = "http://example.org/tests/content/base/test/file_CrossSiteXHR_inner.html";
+  origin = "http://example.org";
+  yield;
+
+  passTests = [{ method: "GET",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "second-header": "secondValue",
+                            "third-header": "thirdValue" },
+                 allowHeaders: "x-my-header, second-header, third-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "second-header": "secondValue",
+                            "third-header": "thirdValue" },
+                 allowHeaders: "x-my-header,second-header,third-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "second-header": "secondValue",
+                            "third-header": "thirdValue" },
+                 allowHeaders: "x-my-header ,second-header ,third-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "second-header": "secondValue",
+                            "third-header": "thirdValue" },
+                 allowHeaders: "x-my-header , second-header , third-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "second-header": "secondValue" },
+                 allowHeaders: ",  x-my-header, , ,, second-header, ,   ",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "second-header": "secondValue" },
+                 allowHeaders: "x-my-header, second-header, unused-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "X-My-Header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header": "secondValue" },
+                 allowHeaders: "x-my-header, long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header-long-header",
+               },
+               { method: "GET",
+                 headers: { "x-my%-header": "myValue" },
+                 allowHeaders: "x-my%-header",
+               },
+               { method: "GET",
+                 headers: { "Content-Type": "baz/bin",
+                            "Accept": "foo/bar",
+                            "Accept-Language": "sv-SE" },
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "text/plain" },
+                 noAllowPreflight: 1,
+               },
+               { method: "POST",
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "foo/bar" },
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "text/plain",
+                            "Accept": "foo/bar",
+                            "Accept-Language": "sv-SE" },
+                 noAllowPreflight: 1,
+               },
+               { method: "POST",
+                 headers: { "Accept": "foo/bar",
+                            "Accept-Language": "sv-SE",
+                            "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header",
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "text/plain",
+                            "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header",
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "foo/bar",
+                            "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header",
+               },
+               { method: "POST",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header",
+               },
+               { method: "POST",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header, $_%",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "POST, PUT, XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "POST, XXDELETE, PUT",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "XXDELETE, POST, PUT",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "POST ,PUT ,XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "POST,PUT,XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "POST , PUT , XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "  ,,  PUT ,,  ,    , XXDELETE  ,  ,",
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "text/plain" },
+                 uploadProgress: "uploadprogress",
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "text/plain" },
+                 uploadProgress: "progress",
+               },
+               ];
+  failTests = [{ method: "GET",
+                 headers: { "x-my-header": "myValue" },
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "y-my-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header y-my-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header, y-my-header z",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue" },
+                 allowHeaders: "x-my-header, y-my-he(ader",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "myValue",
+                            "y-my-header": "secondValue" },
+                 allowHeaders: "x-my-header",
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "" },
+               },
+               { method: "GET",
+                 headers: { "x-my-header": "",
+                            "y-my-header": "" },
+                 allowHeaders: "x-my-header",
+               },
+               { method: "POST",
+                 noAllowPreflight: 1,
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "foo/bar" },
+                 noAllowPreflight: 1,
+               },
+               { method: "XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "PUT",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "XXDELETEZ",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "XXDELETE PUT",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "XXDELETE, PUT Z",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "XXDELETE, PU(T",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "PUT XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "PUT Z, XXDELETE",
+               },
+               { method: "XXDELETE",
+                 allowMethods: "PU(T, XXDELETE",
+               },
+               { method: "MYMETHOD",
+                 allowMethods: "myMethod",
+               },
+               { method: "PUT",
+                 allowMethods: "put",
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "text/plain" },
+                 noAllowPreflight: 1,
+                 uploadProgress: "uploadprogress",
+               },
+               { method: "POST",
+                 headers: { "Content-Type": "text/plain" },
+                 noAllowPreflight: 1,
+                 uploadProgress: "progress",
+               },
+               ];
+
+  for each(test in passTests) {
+    req = {
+      url: baseURL + "&allowOrigin=" + escape(origin) +
+           "&origin=" + escape(origin) +
+           "&requestMethod=" + test.method,
+      method: test.method,
+      headers: test.headers,
+      uploadProgress: test.uploadProgress,
+    };
+
+    if (test.noAllowPreflight)
+      req.url += "&noAllowPreflight";
+
+    if ("headers" in test) {
+      req.url += "&headers=" + escape(test.headers.toSource());
+      reqHeaders =
+        escape([name for (name in test.headers)].filter(function(name)
+          name != "Content-Type" &&
+          name != "Accept" &&
+          name != "Accept-Language").join(","));
+      req.url += reqHeaders ? "&requestHeaders=" + reqHeaders : "";
+    }
+    if ("allowHeaders" in test)
+      req.url += "&allowHeaders=" + escape(test.allowHeaders);
+    if ("allowMethods" in test)
+      req.url += "&allowMethods=" + escape(test.allowMethods);
+
+    loaderWindow.postMessage(req.toSource(), origin);
+
+    res = eval(yield);
+    is(res.didFail, false,
+      "shouldn't have failed in test for " + test.toSource());
+    is(res.status, 200, "wrong status in test for " + test.toSource());
+    is(res.responseXML, "<res>hello pass</res>",
+       "wrong responseXML in test for " + test.toSource());
+    is(res.responseText, "<res>hello pass</res>\n",
+       "wrong responseText in test for " + test.toSource());
+    is(res.events.join(","),
+       "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+       "wrong responseText in test for " + test.toSource());
+  }
+
+  for each(test in failTests) {
+    req = {
+      url: baseURL + "allowOrigin=" + escape(origin),
+      method: test.method,
+      headers: test.headers,
+      uploadProgress: test.uploadProgress,
+    };
+
+    if (test.noAllowPreflight)
+      req.url += "&noAllowPreflight";
+
+    if ("allowHeaders" in test)
+      req.url += "&allowHeaders=" + escape(test.allowHeaders);
+    if ("allowMethods" in test)
+      req.url += "&allowMethods=" + escape(test.allowMethods);
+
+    loaderWindow.postMessage(req.toSource(), origin);
+
+    res = eval(yield);
+    is(res.didFail, true,
+      "should have failed in test for " + test.toSource());
+    is(res.status, 0, "wrong status in test for " + test.toSource());
+    is(res.responseXML, null,
+       "wrong responseXML in test for " + test.toSource());
+    is(res.responseText, "",
+       "wrong responseText in test for " + test.toSource());
+    is(res.events.join(","),
+       "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+       "wrong events in test for " + test.toSource());
+    is(res.progressEvents, 0,
+       "wrong events in test for " + test.toSource());
+  }
+
+
+  // Test cookie behavior
+  tests = [{ pass: 1,
+             method: "GET",
+             withCred: 1,
+             allowCred: 1,
+           },
+           { pass: 0,
+             method: "GET",
+             withCred: 1,
+             allowCred: 0,
+           },
+           { pass: 0,
+             method: "GET",
+             withCred: 1,
+             allowCred: 1,
+             origin: "*",
+           },
+           { pass: 1,
+             method: "GET",
+             withCred: 0,
+             allowCred: 1,
+             origin: "*",
+           },
+           { pass: 1,
+             method: "GET",
+             setCookie: "a=1",
+             withCred: 1,
+             allowCred: 1,
+           },
+           { pass: 1,
+             method: "GET",
+             cookie: "a=1",
+             withCred: 1,
+             allowCred: 1,
+           },
+           { pass: 1,
+             method: "GET",
+             noCookie: 1,
+             withCred: 0,
+             allowCred: 1,
+           },
+           { pass: 0,
+             method: "GET",
+             noCookie: 1,
+             withCred: 1,
+             allowCred: 1,
+           },
+           { pass: 1,
+             method: "GET",
+             setCookie: "a=2",
+             withCred: 0,
+             allowCred: 1,
+           },
+           { pass: 1,
+             method: "GET",
+             cookie: "a=1",
+             withCred: 1,
+             allowCred: 1,
+           },
+           { pass: 1,
+             method: "GET",
+             setCookie: "a=2",
+             withCred: 1,
+             allowCred: 1,
+           },
+           { pass: 1,
+             method: "GET",
+             cookie: "a=2",
+             withCred: 1,
+             allowCred: 1,
+           },
+           ];
+
+  for each(test in tests) {
+    req = {
+      url: baseURL + "allowOrigin=" + escape(test.origin || origin),
+      method: test.method,
+      headers: test.headers,
+      withCred: test.withCred,
+    };
+
+    if (test.allowCred)
+      req.url += "&allowCred";
+
+    if (test.setCookie)
+      req.url += "&setCookie=" + escape(test.setCookie);
+    if (test.cookie)
+      req.url += "&cookie=" + escape(test.cookie);
+    if (test.noCookie)
+      req.url += "&noCookie";
+
+    if ("allowHeaders" in test)
+      req.url += "&allowHeaders=" + escape(test.allowHeaders);
+    if ("allowMethods" in test)
+      req.url += "&allowMethods=" + escape(test.allowMethods);
+
+    loaderWindow.postMessage(req.toSource(), origin);
+
+    res = eval(yield);
+    if (test.pass) {
+      is(res.didFail, false,
+        "shouldn't have failed in test for " + test.toSource());
+      is(res.status, 200, "wrong status in test for " + test.toSource());
+      is(res.responseXML, "<res>hello pass</res>",
+         "wrong responseXML in test for " + test.toSource());
+      is(res.responseText, "<res>hello pass</res>\n",
+         "wrong responseText in test for " + test.toSource());
+      is(res.events.join(","),
+         "opening,rs1,sending,rs1,loadstart,rs2,rs3,rs4,load",
+         "wrong responseText in test for " + test.toSource());
+    }
+    else {
+      is(res.didFail, true,
+        "should have failed in test for " + test.toSource());
+      is(res.status, 0, "wrong status in test for " + test.toSource());
+      is(res.responseXML, null,
+         "wrong responseXML in test for " + test.toSource());
+      is(res.responseText, "",
+         "wrong responseText in test for " + test.toSource());
+      is(res.events.join(","),
+         "opening,rs1,sending,rs1,loadstart,rs2,rs4,error",
+         "wrong events in test for " + test.toSource());
+      is(res.progressEvents, 0,
+         "wrong events in test for " + test.toSource());
+    }
+  }
+
+  SimpleTest.finish();
+
+  yield;
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -82,17 +82,17 @@ nsresult
 NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
 nsresult
 NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
 nsresult
 NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsDragEvent *aEvent);
 nsresult
 NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsKeyEvent *aEvent);
 nsresult
-NS_NewDOMMutationEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsMutationEvent* aEvent);
+NS_NewDOMMutationEvent(nsIDOMEvent** aResult NS_OUTPARAM, nsPresContext* aPresContext, class nsMutationEvent* aEvent);
 nsresult
 NS_NewDOMPopupBlockedEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsPopupBlockedEvent* aEvent);
 nsresult
 NS_NewDOMTextEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsTextEvent* aEvent);
 nsresult
 NS_NewDOMBeforeUnloadEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsBeforePageUnloadEvent* aEvent);
 nsresult
 NS_NewDOMPageTransitionEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsPageTransitionEvent* aEvent);
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -138,17 +138,17 @@
 #include "nsIProperties.h"
 #include "nsISupportsPrimitives.h"
 #include "nsEventDispatcher.h"
 #include "nsPresShellIterator.h"
 
 #include "nsServiceManagerUtils.h"
 #include "nsITimer.h"
 #include "nsIFontMetrics.h"
-
+#include "nsIDOMXULDocument.h"
 #include "nsIDragService.h"
 #include "nsIDragSession.h"
 #include "nsDOMDataTransfer.h"
 #include "nsContentAreaDragDrop.h"
 #ifdef MOZ_XUL
 #include "nsTreeBodyFrame.h"
 #endif
 
@@ -1540,31 +1540,39 @@ GetAccessModifierMask(nsISupports* aDocS
   default:
     return -1; // invalid modifier
   }
 }
 
 static PRBool
 IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
 {
-  if (!aFrame)
+  if (!aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::accesskey, aKey,
+                             eIgnoreCase))
     return PR_FALSE;
 
-  if (!aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::accesskey, aKey, eIgnoreCase))
+  nsCOMPtr<nsIDOMXULDocument> xulDoc =
+    do_QueryInterface(aContent->GetOwnerDoc());
+  if (!xulDoc && !aContent->IsNodeOfType(nsINode::eXUL))
+    return PR_TRUE;
+
+    // For XUL we do visibility checks.
+  if (!aFrame)
     return PR_FALSE;
 
   if (aFrame->IsFocusable())
     return PR_TRUE;
 
   if (!aFrame->GetStyleVisibility()->IsVisible())
     return PR_FALSE;
 
   if (!aFrame->AreAncestorViewsVisible())
     return PR_FALSE;
 
+  // XUL controls can be activated.
   nsCOMPtr<nsIDOMXULControlElement> control(do_QueryInterface(aContent));
   if (control)
     return PR_TRUE;
 
   if (aContent->IsNodeOfType(nsINode::eHTML)) {
     nsIAtom* tag = aContent->Tag();
 
     // HTML area, label and legend elements are never focusable, so
--- a/content/events/test/test_bug409604.html
+++ b/content/events/test/test_bug409604.html
@@ -17,17 +17,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
   /** Test for Bug 409604 **/
 
   var modifier = Components.interfaces.nsIDOMNSEvent.ALT_MASK |
                  Components.interfaces.nsIDOMNSEvent.SHIFT_MASK;
-  var expectedFocus = "d,g,h,k,l,m";
+  var expectedFocus = "d,g,h,k,l,m,n";
   // XXX the "map" test is causing trouble, see bug 433089
   // var expectedClick = "a,b,c,e,f,i,j";
   var expectedClick = "a,c,e,f,i,j";
   var focusArray = expectedFocus.split(",");
   var clickArray = expectedClick.split(",");
   var invalidElementId = "invalid";
   var invalidTags = [
       {tag: "abbr", content: "text", attribs: {title: "something"}},
@@ -110,19 +110,19 @@ https://bugzilla.mozilla.org/show_bug.cg
     } else {
       prefs.setIntPref("contentAccess", newValue);
     }
   }
 
   function handleFocus(e) {
     ok("accessKey" in e, "(focus) accesskey property not found on element");
     var expected = focusArray.shift();
-    // "k" is a special case because the element receiving the focus is not
-    // the element which has the accesskey.
-    if (expected == "k") {
+    // "k" and "n" are a special cases because the element receiving the focus
+    // is not the element which has the accesskey.
+    if (expected == "k" || expected == "n") {
       ok(e.value == "test for label", "(focus) unexpected element: " + e.value +
          " expected: " + "test for label");
     // "l" is a special case because the element receiving the focus is not
     // the element which has the accesskey.
     } else if (expected == "l") {
       ok(e.value == "test for legend", "(focus) unexpected element: " + e.value +
          " expected: " + "test for legend");
     } else {
@@ -307,17 +307,17 @@ https://bugzilla.mozilla.org/show_bug.cg
         <td>legend</td><td><fieldset><legend accesskey="l">test legend</legend>
                            <input type="text" value="test for legend" onfocus="handleFocus(event.target);"></fieldset></td>
       </tr>
       <tr>
         <td>textarea</td><td><textarea onfocus="handleFocus(event.target);" accesskey="m">test text</textarea></td>
       </tr>
       <tr>
         <td>label (label invisible)</td><td><label for="txt1" accesskey="n" style="display:none">test label</label>
-                          <input type="text" id="txt1" value="test for label" onfocus="handleInvalid(event.target);"></td>
+                          <input type="text" id="txt1" value="test for label" onfocus="handleFocus(event.target);"></td>
       </tr>
       <tr>
         <td>label (control invisible)</td><td><label for="txt2" accesskey="o">test label</label>
                           <input type="text" id="txt2" value="test for label" onfocus="handleInvalid(event.target);" style="display:none"></td>
       </tr>
     </tbody>
   </table>
   <dl id="dl"></dl>
--- a/content/html/document/src/nsMediaDocument.cpp
+++ b/content/html/document/src/nsMediaDocument.cpp
@@ -274,19 +274,17 @@ nsMediaDocument::CreateSyntheticDocument
 
 nsresult
 nsMediaDocument::StartLayout()
 {
   mMayStartLayout = PR_TRUE;
   nsPresShellIterator iter(this);
   nsCOMPtr<nsIPresShell> shell;
   while ((shell = iter.GetNextShell())) {
-    PRBool didInitialReflow = PR_FALSE;
-    shell->GetDidInitialReflow(&didInitialReflow);
-    if (didInitialReflow) {
+    if (shell->DidInitialReflow()) {
       // Don't mess with this presshell: someone has already handled
       // its initial reflow.
       continue;
     }
     
     nsRect visibleArea = shell->GetPresContext()->GetVisibleArea();
     nsresult rv = shell->InitialReflow(visibleArea.width, visibleArea.height);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/content/media/video/src/nsMediaDecoder.cpp
+++ b/content/media/video/src/nsMediaDecoder.cpp
@@ -200,16 +200,19 @@ void nsMediaDecoder::Paint(gfxContext* a
     return;
 
   nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
   if (!pat)
     return;
 
   // Make the source image fill the rectangle completely
   pat->SetMatrix(gfxMatrix().Scale(mRGBWidth/aRect.Width(), mRGBHeight/aRect.Height()));
+  // Set PAD mode so that when the video is being scaled, we do not sample
+  // outside the bounds of the video image.
+  pat->SetExtend(gfxPattern::EXTEND_PAD);
 
   /* Draw RGB surface onto frame */
   aContext->NewPath();
   aContext->PixelSnappedRectangleAndSetPattern(aRect, pat);
   aContext->Fill();
 
 #ifdef DEBUG_FRAME_RATE
   {
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -83,41 +83,47 @@ public:
 
   NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
     { mVal.ConvertToSpecifiedUnits(unitType, nsnull); return NS_OK; }
 
 private:
   nsSVGAngle mVal;
 };
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMBaseVal)
-NS_IMPL_RELEASE(nsSVGAngle::DOMBaseVal)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGAngle::DOMBaseVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGAngle::DOMAnimVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGAngle::DOMAnimatedAngle, mSVGElement)
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMAnimVal)
-NS_IMPL_RELEASE(nsSVGAngle::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGAngle::DOMBaseVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGAngle::DOMBaseVal)
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMAnimatedAngle)
-NS_IMPL_RELEASE(nsSVGAngle::DOMAnimatedAngle)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGAngle::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGAngle::DOMAnimVal)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGAngle::DOMAnimatedAngle)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGAngle::DOMAnimatedAngle)
 
 NS_IMPL_ADDREF(DOMSVGAngle)
 NS_IMPL_RELEASE(DOMSVGAngle)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMBaseVal)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAngle::DOMBaseVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMAnimVal)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAngle::DOMAnimVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMAnimatedAngle)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAngle::DOMAnimatedAngle)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedAngle)
 NS_INTERFACE_MAP_END
 
 NS_INTERFACE_MAP_BEGIN(DOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
--- a/content/svg/content/src/nsSVGAngle.h
+++ b/content/svg/content/src/nsSVGAngle.h
@@ -88,17 +88,18 @@ private:
   void NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue,
                               nsSVGElement *aSVGElement);
   void ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement);
   nsresult ToDOMBaseVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
   nsresult ToDOMAnimVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
 
   struct DOMBaseVal : public nsIDOMSVGAngle
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal)
 
     DOMBaseVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -127,17 +128,18 @@ private:
         return NS_OK; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { mVal->ConvertToSpecifiedUnits(unitType, mSVGElement); return NS_OK; }
   };
 
   struct DOMAnimVal : public nsIDOMSVGAngle
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal)
 
     DOMAnimVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -163,17 +165,18 @@ private:
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
   };
 
   struct DOMAnimatedAngle : public nsIDOMSVGAnimatedAngle
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedAngle)
 
     DOMAnimatedAngle(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(nsIDOMSVGAngle **aBaseVal)
--- a/content/svg/content/src/nsSVGAnimatedTransformList.cpp
+++ b/content/svg/content/src/nsSVGAnimatedTransformList.cpp
@@ -182,17 +182,17 @@ nsSVGAnimatedTransformList::DidModifySVG
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 // Exported creation functions:
 
 nsresult
 NS_NewSVGAnimatedTransformList(nsIDOMSVGAnimatedTransformList** result,
-                      nsIDOMSVGTransformList* baseVal)
+                               nsIDOMSVGTransformList* baseVal)
 {
   *result = nsnull;
   
   nsSVGAnimatedTransformList* animatedTransformList = new nsSVGAnimatedTransformList();
   if(!animatedTransformList) return NS_ERROR_OUT_OF_MEMORY;
   NS_ADDREF(animatedTransformList);
 
   animatedTransformList->Init(baseVal);
--- a/content/svg/content/src/nsSVGBoolean.cpp
+++ b/content/svg/content/src/nsSVGBoolean.cpp
@@ -31,20 +31,22 @@
  * 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 "nsSVGBoolean.h"
 
-NS_IMPL_ADDREF(nsSVGBoolean::DOMAnimatedBoolean)
-NS_IMPL_RELEASE(nsSVGBoolean::DOMAnimatedBoolean)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGBoolean::DOMAnimatedBoolean, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGBoolean::DOMAnimatedBoolean)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGBoolean::DOMAnimatedBoolean)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGBoolean::DOMAnimatedBoolean)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGBoolean::DOMAnimatedBoolean)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedBoolean)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedBoolean)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 nsresult
@@ -89,9 +91,8 @@ nsSVGBoolean::ToDOMAnimatedBoolean(nsIDO
 {
   *aResult = new DOMAnimatedBoolean(this, aSVGElement);
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
   return NS_OK;
 }
-
--- a/content/svg/content/src/nsSVGBoolean.h
+++ b/content/svg/content/src/nsSVGBoolean.h
@@ -67,17 +67,18 @@ public:
 private:
 
   PRPackedBool mAnimVal;
   PRPackedBool mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedBoolean : public nsIDOMSVGAnimatedBoolean
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedBoolean)
 
     DOMAnimatedBoolean(nsSVGBoolean* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGBoolean* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRBool* aResult)
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -315,19 +315,19 @@ nsSVGElement::ParseAttribute(PRInt32 aNa
     }
     else {
       aResult.SetTo(svg_value);
     }
     mSuppressNotification = PR_FALSE;
     return PR_TRUE;
   }
 
+  nsresult rv = NS_OK;
   PRBool foundMatch = PR_FALSE;
   if (aNamespaceID == kNameSpaceID_None) {
-    nsresult rv;
 
     // Check for nsSVGLength2 attribute
     LengthAttributesInfo lengthInfo = GetLengthInfo();
 
     PRUint32 i;
     for (i = 0; i < lengthInfo.mLengthCount; i++) {
       if (aAttribute == *lengthInfo.mLengthInfo[i].mName) {
         rv = lengthInfo.mLengths[i].SetBaseValueString(aValue, this, PR_FALSE);
@@ -424,40 +424,40 @@ nsSVGElement::ParseAttribute(PRInt32 aNa
           if (NS_FAILED(rv)) {
             enumInfo.Reset(i);
           }
           foundMatch = PR_TRUE;
           break;
         }
       }
     }
-
-    if (foundMatch) {
-      if (NS_FAILED(rv)) {
-        ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
-        return PR_FALSE;
-      }
-      aResult.SetTo(aValue);
-      return PR_TRUE;
-    }
   }
 
   if (!foundMatch) {
     // Check for nsSVGString attribute
     StringAttributesInfo stringInfo = GetStringInfo();
     for (PRUint32 i = 0; i < stringInfo.mStringCount; i++) {
       if (aNamespaceID == stringInfo.mStringInfo[i].mNamespaceID &&
           aAttribute == *stringInfo.mStringInfo[i].mName) {
         stringInfo.mStrings[i].SetBaseValue(aValue, this, PR_FALSE);
         foundMatch = PR_TRUE;
         break;
       }
     }
   }
 
+  if (foundMatch) {
+    if (NS_FAILED(rv)) {
+      ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
+      return PR_FALSE;
+    }
+    aResult.SetTo(aValue);
+    return PR_TRUE;
+  }
+
   return nsSVGElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                           aResult);
 }
 
 nsresult
 nsSVGElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                         PRBool aNotify)
 {
@@ -589,17 +589,19 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespa
     }
   }
 
   if (!foundMatch) {
     // Now check for one of the old style basetypes going away
     nsCOMPtr<nsISVGValue> svg_value = GetMappedAttribute(aNamespaceID, aName);
 
     if (svg_value) {
+      mSuppressNotification = PR_TRUE;
       ResetOldStyleBaseType(svg_value);
+      mSuppressNotification = PR_FALSE;
     }
   }
 
   return nsSVGElementBase::UnsetAttr(aNamespaceID, aName, aNotify);
 }
 
 void
 nsSVGElement::ResetOldStyleBaseType(nsISVGValue *svg_value)
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -358,9 +358,19 @@ NS_NewSVG##_elementName##Element(nsICont
     return rv;                                                               \
   }                                                                          \
                                                                              \
   *aResult = it;                                                             \
                                                                              \
   return rv;                                                                 \
 }
 
+// No unlinking, we'd need to null out the value pointer (the object it
+// points to is held by the element) and null-check it everywhere.
+#define NS_SVG_VAL_IMPL_CYCLE_COLLECTION(_val, _element)                     \
+NS_IMPL_CYCLE_COLLECTION_CLASS(_val)                                         \
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val)                                \
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(_element, nsIContent) \
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                        \
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_val)
+
+
 #endif // __NS_SVGELEMENT_H__
--- a/content/svg/content/src/nsSVGEnum.cpp
+++ b/content/svg/content/src/nsSVGEnum.cpp
@@ -33,20 +33,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGEnum.h"
 #include "nsIAtom.h"
 #include "nsSVGElement.h"
 
-NS_IMPL_ADDREF(nsSVGEnum::DOMAnimatedEnum)
-NS_IMPL_RELEASE(nsSVGEnum::DOMAnimatedEnum)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGEnum::DOMAnimatedEnum, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGEnum::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGEnum::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGEnum::DOMAnimatedEnum)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGEnum::DOMAnimatedEnum)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedEnumeration)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedEnumeration)
 NS_INTERFACE_MAP_END
 
 nsSVGEnumMapping *
 nsSVGEnum::GetMapping(nsSVGElement *aSVGElement)
 {
--- a/content/svg/content/src/nsSVGEnum.h
+++ b/content/svg/content/src/nsSVGEnum.h
@@ -78,17 +78,18 @@ private:
   nsSVGEnumValue mAnimVal;
   nsSVGEnumValue mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   nsSVGEnumMapping *GetMapping(nsSVGElement *aSVGElement);
 
   struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedEnum)
 
     DOMAnimatedEnum(nsSVGEnum* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGEnum *mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRUint16* aResult)
--- a/content/svg/content/src/nsSVGForeignObjectElement.h
+++ b/content/svg/content/src/nsSVGForeignObjectElement.h
@@ -62,17 +62,17 @@ public:
   NS_DECL_NSIDOMSVGFOREIGNOBJECTELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGForeignObjectElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGForeignObjectElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGForeignObjectElementBase::)
 
   // nsIContent interface
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   
   enum { X, Y, WIDTH, HEIGHT };
--- a/content/svg/content/src/nsSVGImageElement.cpp
+++ b/content/svg/content/src/nsSVGImageElement.cpp
@@ -85,17 +85,17 @@ public:
   virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                 const nsAString* aValue, PRBool aNotify);
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
 
   virtual PRInt32 IntrinsicState() const;
 
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   // nsSVGPathGeometryElement methods:
   virtual void ConstructPath(gfxContext *aCtx);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
   nsresult LoadSVGImage(PRBool aForce, PRBool aNotify);
--- a/content/svg/content/src/nsSVGInteger.cpp
+++ b/content/svg/content/src/nsSVGInteger.cpp
@@ -31,20 +31,23 @@
  * 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 "nsSVGInteger.h"
 
-NS_IMPL_ADDREF(nsSVGInteger::DOMAnimatedInteger)
-NS_IMPL_RELEASE(nsSVGInteger::DOMAnimatedInteger)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGInteger::DOMAnimatedInteger, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGInteger::DOMAnimatedInteger)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGInteger::DOMAnimatedInteger)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGInteger::DOMAnimatedInteger)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGInteger::DOMAnimatedInteger)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedInteger)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedInteger)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 nsresult
@@ -91,9 +94,8 @@ nsSVGInteger::ToDOMAnimatedInteger(nsIDO
 {
   *aResult = new DOMAnimatedInteger(this, aSVGElement);
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
   return NS_OK;
 }
-
--- a/content/svg/content/src/nsSVGInteger.h
+++ b/content/svg/content/src/nsSVGInteger.h
@@ -67,17 +67,18 @@ public:
 private:
 
   PRInt32 mAnimVal;
   PRInt32 mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedInteger : public nsIDOMSVGAnimatedInteger
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedInteger)
 
     DOMAnimatedInteger(nsSVGInteger* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGInteger* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRInt32* aResult)
--- a/content/svg/content/src/nsSVGLength2.cpp
+++ b/content/svg/content/src/nsSVGLength2.cpp
@@ -38,38 +38,44 @@
 
 #include "nsSVGLength2.h"
 #include "prdtoa.h"
 #include "nsTextFormatter.h"
 #include "nsSVGSVGElement.h"
 #include "nsIFrame.h"
 #include "nsSVGIntegrationUtils.h"
 
-NS_IMPL_ADDREF(nsSVGLength2::DOMBaseVal)
-NS_IMPL_RELEASE(nsSVGLength2::DOMBaseVal)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength, mSVGElement)
 
-NS_IMPL_ADDREF(nsSVGLength2::DOMAnimVal)
-NS_IMPL_RELEASE(nsSVGLength2::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMBaseVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMBaseVal)
 
-NS_IMPL_ADDREF(nsSVGLength2::DOMAnimatedLength)
-NS_IMPL_RELEASE(nsSVGLength2::DOMAnimatedLength)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimVal)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGLength2::DOMBaseVal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMAnimatedLength)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimatedLength)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGLength)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGLength2::DOMAnimVal)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMAnimVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGLength)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGLength2::DOMAnimatedLength)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedLength)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedLength)
 NS_INTERFACE_MAP_END
 
 static nsIAtom** const unitMap[] =
 {
   nsnull, /* SVG_LENGTHTYPE_UNKNOWN */
--- a/content/svg/content/src/nsSVGLength2.h
+++ b/content/svg/content/src/nsSVGLength2.h
@@ -118,17 +118,18 @@ private:
   void NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue,
                               nsSVGElement *aSVGElement);
   void ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement);
   nsresult ToDOMBaseVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement);
   nsresult ToDOMAnimVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement);
 
   struct DOMBaseVal : public nsIDOMSVGLength
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal)
 
     DOMBaseVal(nsSVGLength2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGLength2* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -157,17 +158,18 @@ private:
         return NS_OK; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { mVal->ConvertToSpecifiedUnits(unitType, mSVGElement); return NS_OK; }
   };
 
   struct DOMAnimVal : public nsIDOMSVGLength
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal)
 
     DOMAnimVal(nsSVGLength2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGLength2* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -193,17 +195,18 @@ private:
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
   };
 
   struct DOMAnimatedLength : public nsIDOMSVGAnimatedLength
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedLength)
 
     DOMAnimatedLength(nsSVGLength2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGLength2* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(nsIDOMSVGLength **aBaseVal)
--- a/content/svg/content/src/nsSVGLineElement.cpp
+++ b/content/svg/content/src/nsSVGLineElement.cpp
@@ -59,17 +59,17 @@ public:
   NS_DECL_NSIDOMSVGLINEELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGLineElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGLineElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGLineElementBase::)
 
   // nsIContent interface
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   // nsSVGPathGeometryElement methods:
   virtual PRBool IsMarkable() { return PR_TRUE; }
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
   virtual void ConstructPath(gfxContext *aCtx);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
--- a/content/svg/content/src/nsSVGMarkerElement.cpp
+++ b/content/svg/content/src/nsSVGMarkerElement.cpp
@@ -73,20 +73,22 @@ nsSVGElement::AngleInfo nsSVGMarkerEleme
   { &nsGkAtoms::orient, 0, nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED }
 };
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Marker)
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_ADDREF(nsSVGOrientType::DOMAnimatedEnum)
-NS_IMPL_RELEASE(nsSVGOrientType::DOMAnimatedEnum)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGOrientType::DOMAnimatedEnum, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGOrientType::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGOrientType::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGOrientType::DOMAnimatedEnum)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGOrientType::DOMAnimatedEnum)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedEnumeration)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedEnumeration)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
 
--- a/content/svg/content/src/nsSVGMarkerElement.h
+++ b/content/svg/content/src/nsSVGMarkerElement.h
@@ -66,17 +66,18 @@ public:
                              nsSVGElement* aSVGElement);
 
 private:
   nsSVGEnumValue mAnimVal;
   nsSVGEnumValue mBaseVal;
 
   struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedEnum)
 
     DOMAnimatedEnum(nsSVGOrientType* aVal,
                     nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGOrientType *mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
@@ -115,17 +116,17 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsSVGElement::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::)
 
   // nsISVGValueObserver
   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
                                      nsISVGValue::modificationType aModType);
 
   // nsIContent interface
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual PRBool GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                          nsAString& aResult) const;
   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                              PRBool aNotify);
 
   // nsSVGElement specializations:
   virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
--- a/content/svg/content/src/nsSVGNumber2.cpp
+++ b/content/svg/content/src/nsSVGNumber2.cpp
@@ -33,20 +33,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGNumber2.h"
 #include "nsTextFormatter.h"
 #include "prdtoa.h"
 
-NS_IMPL_ADDREF(nsSVGNumber2::DOMAnimatedNumber)
-NS_IMPL_RELEASE(nsSVGNumber2::DOMAnimatedNumber)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGNumber2::DOMAnimatedNumber)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGNumber2::DOMAnimatedNumber)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGNumber2::DOMAnimatedNumber)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedNumber)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedNumber)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 nsresult
--- a/content/svg/content/src/nsSVGNumber2.h
+++ b/content/svg/content/src/nsSVGNumber2.h
@@ -68,17 +68,18 @@ public:
 private:
 
   float mAnimVal;
   float mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedNumber : public nsIDOMSVGAnimatedNumber
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedNumber)
 
     DOMAnimatedNumber(nsSVGNumber2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGNumber2* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(float* aResult)
--- a/content/svg/content/src/nsSVGPathElement.h
+++ b/content/svg/content/src/nsSVGPathElement.h
@@ -87,17 +87,17 @@ public:
   NS_DECL_NSIDOMSVGANIMATEDPATHDATA
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGPathElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGPathElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGPathElementBase::)
 
   // nsIContent interface
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   // nsISVGValueObserver
   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
                                      nsISVGValue::modificationType aModType);
 
   // nsSVGPathGeometryElement methods:
   virtual PRBool IsDependentAttribute(nsIAtom *aName);
   virtual PRBool IsMarkable();
--- a/content/svg/content/src/nsSVGPatternElement.h
+++ b/content/svg/content/src/nsSVGPatternElement.h
@@ -88,17 +88,17 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   NS_FORWARD_NSIDOMNODE(nsSVGElement::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGElement::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::)
 
   // nsIContent interface
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
 
   void PushUpdate();
 
   virtual LengthAttributesInfo GetLengthInfo();
--- a/content/svg/content/src/nsSVGPolyElement.h
+++ b/content/svg/content/src/nsSVGPolyElement.h
@@ -54,17 +54,17 @@ protected:
 
 public:
   //interfaces
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGANIMATEDPOINTS
 
   // nsIContent interface
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
   
   // nsSVGPathGeometryElement methods:
   virtual PRBool IsDependentAttribute(nsIAtom *aName);
   virtual PRBool IsMarkable() { return PR_TRUE; }
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
   virtual void ConstructPath(gfxContext *aCtx);
 
 protected:
--- a/content/svg/content/src/nsSVGString.cpp
+++ b/content/svg/content/src/nsSVGString.cpp
@@ -31,20 +31,22 @@
  * 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 "nsSVGString.h"
 
-NS_IMPL_ADDREF(nsSVGString::DOMAnimatedString)
-NS_IMPL_RELEASE(nsSVGString::DOMAnimatedString)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGString::DOMAnimatedString, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGString::DOMAnimatedString)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGString::DOMAnimatedString)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGString::DOMAnimatedString)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGString::DOMAnimatedString)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedString)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedString)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 void
--- a/content/svg/content/src/nsSVGString.h
+++ b/content/svg/content/src/nsSVGString.h
@@ -65,17 +65,18 @@ public:
 private:
 
   nsString mAnimVal;
   nsString mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedString : public nsIDOMSVGAnimatedString
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedString)
 
     DOMAnimatedString(nsSVGString* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGString* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(nsAString & aResult)
--- a/content/svg/content/src/nsSVGSwitchElement.cpp
+++ b/content/svg/content/src/nsSVGSwitchElement.cpp
@@ -47,20 +47,30 @@ NS_SVG_PassesConditionalProcessingTests(
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Switch)
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGSwitchElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSVGSwitchElement,
+                                                  nsSVGSwitchElementBase)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mActiveChild)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGSwitchElement,
+                                                nsSVGSwitchElementBase)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mActiveChild)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
 NS_IMPL_ADDREF_INHERITED(nsSVGSwitchElement,nsSVGSwitchElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGSwitchElement,nsSVGSwitchElementBase)
 
-NS_INTERFACE_TABLE_HEAD(nsSVGSwitchElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGSwitchElement)
   NS_NODE_INTERFACE_TABLE4(nsSVGSwitchElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGSwitchElement)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGSwitchElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGSwitchElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
--- a/content/svg/content/src/nsSVGSwitchElement.h
+++ b/content/svg/content/src/nsSVGSwitchElement.h
@@ -53,16 +53,18 @@ protected:
 public:
   nsIContent * GetActiveChild()
   { return mActiveChild; }
   void MaybeInvalidate();
     
   // interfaces:
 
   NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSVGSwitchElement,
+                                           nsSVGSwitchElementBase)
   NS_DECL_NSIDOMSVGSWITCHELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGSwitchElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGSwitchElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGSwitchElementBase::)
 
   // nsINode
--- a/content/svg/content/src/nsSVGSymbolElement.cpp
+++ b/content/svg/content/src/nsSVGSymbolElement.cpp
@@ -65,17 +65,17 @@ public:
   NS_DECL_NSIDOMSVGFITTOVIEWBOX
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGElement::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGElement::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::)
 
   // nsIContent interface
-  NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
 
   nsCOMPtr<nsIDOMSVGAnimatedRect> mViewBox;
   nsCOMPtr<nsIDOMSVGAnimatedPreserveAspectRatio> mPreserveAspectRatio;
 };
--- a/content/svg/content/test/Makefile.in
+++ b/content/svg/content/test/Makefile.in
@@ -52,12 +52,13 @@ include $(topsrcdir)/config/rules.mk
 		dataTypes-helper.svg \
 		test_getSubStringLength.xhtml \
 		getSubStringLength-helper.svg \
 		test_pathSeg.xhtml \
 		test_scientific.html \
 		scientific-helper.svg \
 		test_text.html \
 		text-helper.svg \
+		test_valueLeaks.xhtml \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/svg/content/test/test_valueLeaks.xhtml
@@ -0,0 +1,76 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=467671
+-->
+<head>
+  <title>Test for Bug 467671</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=467671">Mozilla Bug 467671</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 467671 **/
+
+function storeSVGPropertyAsExpando(localName, prop)
+{
+    var elem = document.createElementNS("http://www.w3.org/2000/svg", localName);
+
+    elem.addEventListener("click", function(){}, false);
+
+    var propVal = elem[prop];
+    Object.prototype.toSource[prop + "_expando"] = propVal;
+    if (propVal instanceof SVGAnimatedAngle || propVal instanceof SVGAnimatedLength) {
+        Object.prototype.toSource[prop + "_baseVal_expando"] = propVal.baseVal;
+        Object.prototype.toSource[prop + "_animVal_expando"] = propVal.animVal;
+    }
+}
+
+// angle
+storeSVGPropertyAsExpando("marker", "orientAngle");
+
+// boolean
+storeSVGPropertyAsExpando("feConvolveMatrix", "preserveAlpha");
+
+// enum
+storeSVGPropertyAsExpando("feConvolveMatrix", "edgeMode");
+
+// special marker enum
+storeSVGPropertyAsExpando("marker", "orientType");
+
+// integer
+storeSVGPropertyAsExpando("feConvolveMatrix", "orderX");
+
+// length
+storeSVGPropertyAsExpando("feConvolveMatrix", "x");
+
+// number
+storeSVGPropertyAsExpando("feConvolveMatrix", "divisor");
+
+// string
+storeSVGPropertyAsExpando("feConvolveMatrix", "in1");
+
+var elem1 = document.createElementNS("http://www.w3.org/2000/svg", "switch");
+var elem2 = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+elem1.appendChild(elem2);
+document.getElementById("content").appendChild(elem1);
+
+elem2.addEventListener("click", function(){}, false);
+
+Object.prototype.toSource.expando = elem1;
+
+ok(true, "SVG shouldn't leak.");
+
+]]>
+</script>
+</pre>
+</body>
+</html>
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1337,17 +1337,17 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpa
         if ((aName == nsGkAtoms::activetitlebarcolor ||
              aName == nsGkAtoms::inactivetitlebarcolor) &&
             doc && doc->GetRootContent() == this) {
             // Use 0, 0, 0, 0 as the "none" color.
             SetTitlebarColor(NS_RGBA(0, 0, 0, 0), aName == nsGkAtoms::activetitlebarcolor);
         }
 
         // If the accesskey attribute is removed, unregister it here
-        // Also see nsAreaFrame, nsBoxFrame and nsTextBoxFrame's AttributeChanged
+        // Also see nsXULLabelFrame, nsBoxFrame and nsTextBoxFrame's AttributeChanged
         if (aName == nsGkAtoms::accesskey || aName == nsGkAtoms::control) {
             UnregisterAccessKey(oldValue);
         }
 
         // Check to see if the OBSERVES attribute is being unset.  If so, we
         // need to remove our broadcaster goop completely.
         if (doc && (aName == nsGkAtoms::observes ||
                           aName == nsGkAtoms::command)) {
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -3883,20 +3883,18 @@ nsXULDocument::AddPrototypeSheets()
 nsForwardReference::Result
 nsXULDocument::OverlayForwardReference::Resolve()
 {
     // Resolve a forward reference from an overlay element; attempt to
     // hook it up into the main document.
     nsresult rv;
     nsCOMPtr<nsIContent> target;
 
-    PRBool notify = PR_FALSE;
     nsIPresShell *shell = mDocument->GetPrimaryShell();
-    if (shell)
-        shell->GetDidInitialReflow(&notify);
+    PRBool notify = shell && shell->DidInitialReflow();
 
     nsAutoString id;
     mOverlay->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
     if (id.IsEmpty()) {
         // mOverlay is a direct child of <overlay> and has no id.
         // Insert it under the root element in the base document.
         nsIContent* root = mDocument->GetRootContent();
         if (!root) {
--- a/content/xul/templates/src/nsXULContentBuilder.cpp
+++ b/content/xul/templates/src/nsXULContentBuilder.cpp
@@ -744,19 +744,18 @@ nsXULContentBuilder::BuildContentFromTem
                 //    <label value="?title"/>
                 //  </vbox>
                 rv = BuildContentFromTemplate(tmplKid, aResourceNode, realKid, PR_FALSE,
                                               PR_FALSE, aChild, PR_FALSE, aMatch,
                                               nsnull /* don't care */,
                                               nsnull /* don't care */);
                 if (NS_FAILED(rv)) return rv;
 
-                if (isGenerationElement && !(mFlags & eDontRecurse)) {
-                    // if recursion is allowed, continue by building the next
-                    // level of children
+                if (isGenerationElement) {
+                    // build the next level of children
                     rv = CreateContainerContents(realKid, aChild, PR_FALSE,
                                                  PR_FALSE, PR_FALSE);
                     if (NS_FAILED(rv)) return rv;
                 }
             }
 
             // We'll _already_ have added the unique elements; but if
             // it's -not- unique, then use the XUL sort service now to
@@ -1017,26 +1016,19 @@ nsXULContentBuilder::CreateTemplateAndCo
                                     PR_FALSE, PR_TRUE);
         }
     }
     else if (!(mFlags & eDontRecurse)) {
         // The content map will contain the generation elements (the ones that
         // are given ids) and only those elements, so get the reference point
         // from the corresponding match.
         nsTemplateMatch *match = nsnull;
-        if (mContentSupportMap.Get(aElement, &match)) {
-            // don't generate children if child processing isn't allowed
-            PRBool mayProcessChildren;
-            nsresult rv = match->mResult->GetMayProcessChildren(&mayProcessChildren);
-            if (NS_FAILED(rv) || !mayProcessChildren)
-                return rv;
-
+        if (mContentSupportMap.Get(aElement, &match))
             CreateContainerContents(aElement, match->mResult, aForceCreation,
                                     PR_FALSE, PR_TRUE);
-        }
     }
 
     PR_LOG(gXULTemplateLog, PR_LOG_ALWAYS,
            ("nsXULContentBuilder::CreateTemplateAndContainerContents end"));
 
     return NS_OK;
 }
 
@@ -1045,16 +1037,27 @@ nsXULContentBuilder::CreateContainerCont
                                              nsIXULTemplateResult* aResult,
                                              PRBool aForceCreation,
                                              PRBool aNotify,
                                              PRBool aNotifyAtEnd)
 {
     if (!aForceCreation && !IsOpen(aElement))
         return NS_OK;
 
+    // don't generate children if recursion or child processing isn't allowed
+    if (aResult != mRootResult) {
+        if (mFlags & eDontRecurse)
+            return NS_OK;
+
+        PRBool mayProcessChildren;
+        nsresult rv = aResult->GetMayProcessChildren(&mayProcessChildren);
+        if (NS_FAILED(rv) || !mayProcessChildren)
+            return rv;
+    }
+
     nsCOMPtr<nsIRDFResource> refResource;
     GetResultResource(aResult, getter_AddRefs(refResource));
     if (! refResource)
         return NS_ERROR_FAILURE;
 
     // Avoid re-entrant builds for the same resource.
     if (IsActivated(refResource))
         return NS_OK;
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -186,17 +186,17 @@ nsXULTemplateQueryProcessorXML::GetDatas
     nsIScriptContext *context = scriptObject->GetContext();
     NS_ENSURE_TRUE(context, NS_OK);
 
     nsCOMPtr<nsIXMLHttpRequest> req =
         do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(scriptObject);
-    req->Init(docPrincipal, context, owner);
+    req->Init(docPrincipal, context, owner, nsnull);
 
     rv = req->OpenRequest(NS_LITERAL_CSTRING("GET"), uriStr, PR_TRUE,
                           EmptyString(), EmptyString());
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(req));
     rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -64,16 +64,18 @@ include $(topsrcdir)/config/rules.mk
 		bug113934_window.xul \
 		test_bug215405.xul \
 		bug215405_window.xul \
 		test_bug364461.xul \
 		bug364461_window.xul \
 		test_bug396519.xul \
 		bug396519_window.xul \
 		test_bug428288.html \
+		test_bug449778.xul \
+		bug449778_window.xul \
 		test_bug454235.xul \
 		bug454235-subframe.xul \
 		test_bug456980.xul \
 		$(NULL)
 
 libs:: $(_HTTP_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/bug449778_window.xul
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 449778" onload="doTheTest()"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <hbox id="parent">
+  </hbox>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+    var imports = [ "SimpleTest", "is", "isnot", "ok", "snapshotWindow",
+                    "compareSnapshots", "onerror" ];
+    for each (var import in imports) {
+      window[import] = window.opener.wrappedJSObject[import];
+    }
+
+    function $(id) {
+      return document.getElementById(id);
+    }
+
+    function addBrowser(parent, id, width, height) {
+      var b =
+        document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
+      b.setAttribute("type", "content");
+      b.setAttribute("id", id);
+      b.setAttribute("width", width);
+      b.setAttribute("height", height);
+      $(parent).appendChild(b);
+    }
+    addBrowser("parent", "f1", 300, 200);
+    addBrowser("parent", "f2", 300, 200);
+
+    /** Test for Bug 449778 **/
+    var doc1 = "data:text/html,<html><body>This is a test</body></html>";
+    var doc2 = "data:text/html,<html><body>This is a second test</body></html>";
+    var doc3 = "data:text/html,<html><body>This is a <script>var evt = document.createEvent('Events'); evt.initEvent('testEvt', true, true); document.dispatchEvent(evt);</script>third test</body></html>";
+
+
+    $("f1").setAttribute("src", doc1);
+    $("f2").setAttribute("src", doc2);
+
+    function doTheTest() {
+      var strs = { "f1": "", "f2" : "" };
+      function attachListener(node, type) {
+        var listener = function(e) {
+          if (strs[node.id]) strs[node.id] += " ";
+          strs[node.id] += node.id + ".page" + type;
+        }
+        node.addEventListener("page" + type, listener, false);
+
+        listener.detach = function() {
+          node.removeEventListener("page" + type, listener, false);
+        }
+        return listener;
+      }
+
+      var l1 = attachListener($("f1"), "show");
+      var l2 = attachListener($("f1"), "hide");
+      var l3 = attachListener($("f2"), "show");
+      var l4 = attachListener($("f2"), "hide");
+
+      $("f1").swapDocShells($("f2"));
+
+      is(strs["f1"], "f1.pagehide f1.pageshow",
+              "Expected hide then show on first loaded page");
+      is(strs["f2"], "f2.pagehide f2.pageshow",
+              "Expected hide then show on second loaded page");
+
+      function listener2() {
+        $("f2").removeEventListener("testEvt", listener2, false);
+
+        strs = { "f1": "", "f2" : "" };
+
+        $("f1").swapDocShells($("f2"));
+        is(strs["f1"], "f1.pagehide",
+           "Expected hide on already-loaded page, then nothing");
+        is(strs["f2"], "f2.pageshow f2.pagehide f2.pageshow",
+           "Expected show on still-loading page, then hide on it, then show " +
+           "on already-loaded page");
+
+        strs = { "f1": "", "f2" : "" };
+
+        $("f1").addEventListener("pageshow", listener3, false);
+      }
+
+      function listener3() {
+        $("f1").removeEventListener("pageshow", listener3, false);
+
+        is(strs["f1"], "f1.pageshow",
+           "Expected show as our page finishes loading");
+        is(strs["f2"], "", "Expected no more events here.");
+
+        l1.detach();
+        l2.detach();
+        l3.detach();
+        l4.detach();
+
+        window.close();
+        SimpleTest.finish();
+      }
+
+      $("f2").addEventListener("testEvt", listener2, false, true);
+      $("f2").setAttribute("src", doc3);
+    }
+
+  ]]></script>
+</window>
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_bug449778.xul
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=449778
+-->
+<window title="Mozilla Bug 449778"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=449778"
+     target="_blank">Mozilla Bug 396519</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+    SimpleTest.waitForExplicitFinish();
+
+    addLoadEvent(function() {
+      window.open("bug449778_window.xul", "bug449778",
+                  "chrome,width=800,height=800");
+    });
+
+  ]]></script>
+</window>
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -5233,28 +5233,32 @@ private:
 //static
 nsresult
 nsDOMConstructor::Create(const PRUnichar* aName,
                          const nsGlobalNameStruct* aNameStruct,
                          nsPIDOMWindow* aOwner,
                          nsDOMConstructor** aResult)
 {
   *aResult = nsnull;
-  // Prevent creating a constructor if
-  // - aOwner is inner window which doesn't have outer window or
-  // - outer window doesn't have inner window or
-  // - caller can't access outer window's inner window.
+  // Prevent creating a constructor if aOwner is inner window which doesn't have
+  // an outer window. If the outer window doesn't have an inner window or the
+  // caller can't access the outer window's current inner window then try to use
+  // the owner (so long as it is, in fact, an inner window). If that doesn't
+  // work then prevent creation also.
   nsPIDOMWindow* outerWindow = aOwner->GetOuterWindow();
   nsPIDOMWindow* currentInner =
-    outerWindow ? outerWindow->GetCurrentInnerWindow() : nsnull;
-  if (!currentInner ||
+    outerWindow ? outerWindow->GetCurrentInnerWindow() : aOwner;
+  if (!outerWindow ||
       (aOwner != currentInner &&
-       !nsContentUtils::CanCallerAccess(currentInner))) {
+       !nsContentUtils::CanCallerAccess(currentInner) &&
+       !(currentInner = aOwner)->IsInnerWindow())) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
+  NS_ASSERTION(nsContentUtils::CanCallerAccess(currentInner),
+               "Must be able to access currentInner!");
   *aResult = new nsDOMConstructor(aName, aNameStruct, currentInner);
   NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
   NS_ADDREF(*aResult);
   return NS_OK;
 }
 
 NS_IMPL_ADDREF(nsDOMConstructor)
 NS_IMPL_RELEASE(nsDOMConstructor)
--- a/dom/src/base/nsGlobalWindow.cpp
+++ b/dom/src/base/nsGlobalWindow.cpp
@@ -1791,35 +1791,46 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       if (currentInner && currentInner->mJSObject) {
         PRBool termFuncSet = PR_FALSE;
 
         if (oldDoc == aDocument) {
-          JSContext *cx = nsContentUtils::GetCurrentJSContext();
+          // Suspend the current context's request before Pop() resumes the old
+          // context's request.
+          JSAutoSuspendRequest asr(cx);
+
+          // Pop our context here so that we get the correct one for the
+          // termination function.
+          cxPusher.Pop();
+
+          JSContext *oldCx = nsContentUtils::GetCurrentJSContext();
 
           nsIScriptContext *callerScx;
-          if (cx && (callerScx = GetScriptContextFromJSContext(cx))) {
+          if (oldCx && (callerScx = GetScriptContextFromJSContext(oldCx))) {
             // We're called from document.open() (and document.open() is
             // called from JS), clear the scope etc in a termination
             // function on the calling context to prevent clearing the
             // calling scope.
             NS_ASSERTION(!currentInner->IsFrozen(),
                 "How does this opened window get into session history");
 
-            JSAutoRequest ar(cx);
+            JSAutoRequest ar(oldCx);
 
             callerScx->SetTerminationFunction(ClearWindowScope,
                                               static_cast<nsIDOMWindow *>
                                                          (currentInner));
 
             termFuncSet = PR_TRUE;
           }
+
+          // Re-push our context.
+          cxPusher.Push(cx);
         }
 
         // Don't clear scope on our current inner window if it's going to be
         // held in the bfcache.
         if (!currentInner->IsFrozen()) {
           // Skip the ClearScope if we set a termination function to do
           // it ourselves, later.
           currentInner->FreeInnerObjects(!termFuncSet);
--- a/dom/src/threads/nsDOMWorker.h
+++ b/dom/src/threads/nsDOMWorker.h
@@ -72,16 +72,17 @@ class nsDOMWorker : public nsIWorker,
 {
   friend class nsDOMWorkerFeature;
   friend class nsDOMWorkerFunctions;
   friend class nsDOMWorkerRefPtr;
   friend class nsDOMWorkerScope;
   friend class nsDOMWorkerScriptLoader;
   friend class nsDOMWorkerTimeout;
   friend class nsDOMWorkerXHR;
+  friend class nsDOMWorkerXHRProxy;
   friend class nsReportErrorRunnable;
 
   friend JSBool DOMWorkerOperationCallback(JSContext* aCx);
   friend void DOMWorkerErrorReporter(JSContext* aCx,
                                      const char* aMessage,
                                      JSErrorReport* aReport);
 
 #ifdef DEBUG
--- a/dom/src/threads/nsDOMWorkerPool.cpp
+++ b/dom/src/threads/nsDOMWorkerPool.cpp
@@ -38,17 +38,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsDOMWorkerPool.h"
 
 // Interfaces
 #include "nsIDocument.h"
 #include "nsIDOMClassInfo.h"
 #include "nsIJSContextStack.h"
-#include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIServiceManager.h"
 #include "nsIThreadManager.h"
 #include "nsIXPConnect.h"
 #include "nsPIDOMWindow.h"
 
 // Other includes
 #include "nsAutoLock.h"
@@ -226,17 +225,8 @@ nsDOMWorkerPool::Resume()
   if (count) {
     for (PRUint32 index = 0; index < count; index++) {
       workers[index]->Resume();
     }
     nsAutoMonitor mon(mMonitor);
     mon.NotifyAll();
   }
 }
-
-nsIScriptContext*
-nsDOMWorkerPool::ScriptContext()
-{
-  NS_ASSERTION(NS_IsMainThread(),
-               "Don't touch the non-threadsafe script context off the main "
-               "thread!");
-  return mParentGlobal->GetContext();
-}
--- a/dom/src/threads/nsDOMWorkerPool.h
+++ b/dom/src/threads/nsDOMWorkerPool.h
@@ -57,18 +57,16 @@ class nsDOMWorkerPool
 {
 public:
   nsDOMWorkerPool(nsIScriptGlobalObject* aGlobalObject,
                   nsIDocument* aDocument);
 
   NS_IMETHOD_(nsrefcnt) AddRef();
   NS_IMETHOD_(nsrefcnt) Release();
 
-  nsIScriptContext* ScriptContext();
-
   nsIScriptGlobalObject* ScriptGlobalObject() {
     return mParentGlobal;
   }
 
   nsIDocument* ParentDocument() {
     return mParentDocument;
   }
 
--- a/dom/src/threads/nsDOMWorkerXHR.cpp
+++ b/dom/src/threads/nsDOMWorkerXHR.cpp
@@ -813,17 +813,18 @@ nsDOMWorkerXHR::SetMozBackgroundRequest(
     return NS_ERROR_NOT_AVAILABLE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWorkerXHR::Init(nsIPrincipal* aPrincipal,
                      nsIScriptContext* aScriptContext,
-                     nsPIDOMWindow* aOwnerWindow)
+                     nsPIDOMWindow* aOwnerWindow,
+                     nsIURI* aBaseURI)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_NOTREACHED("No one should be calling this!");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsDOMWorkerXHR::GetUpload(nsIXMLHttpRequestUpload** aUpload)
--- a/dom/src/threads/nsDOMWorkerXHRProxy.cpp
+++ b/dom/src/threads/nsDOMWorkerXHRProxy.cpp
@@ -399,23 +399,22 @@ nsDOMWorkerXHRProxy::InitInternal()
   nsDOMWorker* worker = mWorkerXHR->mWorker;
   nsRefPtr<nsDOMWorkerPool> pool = worker->Pool();
 
   if (worker->IsCanceled()) {
     return NS_ERROR_ABORT;
   }
 
   nsIPrincipal* nodePrincipal = pool->ParentDocument()->NodePrincipal();
-  nsIScriptContext* scriptContext = pool->ScriptContext();
-  NS_ASSERTION(nodePrincipal && scriptContext, "Shouldn't be null!");
 
   nsRefPtr<nsXMLHttpRequest> xhrConcrete = new nsXMLHttpRequest();
   NS_ENSURE_TRUE(xhrConcrete, NS_ERROR_OUT_OF_MEMORY);
 
-  nsresult rv = xhrConcrete->Init(nodePrincipal, scriptContext, nsnull);
+  nsresult rv = xhrConcrete->Init(nodePrincipal, nsnull, nsnull,
+                                  worker->GetURI());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Call QI manually here to avoid keeping up with the cast madness of
   // nsXMLHttpRequest.
   nsCOMPtr<nsIXMLHttpRequest> xhr =
     do_QueryInterface(static_cast<nsIXMLHttpRequest*>(xhrConcrete));
   NS_ENSURE_TRUE(xhr, NS_ERROR_NO_INTERFACE);
 
@@ -732,16 +731,20 @@ nsDOMWorkerXHRProxy::HandleEvent(nsIDOME
   PRBool isUpload = IsUploadEvent(aEvent);
 
   if ((isUpload && type >= MAX_UPLOAD_LISTENER_TYPE) ||
       (!isUpload && type >= MAX_XHR_LISTENER_TYPE)) {
     NS_ERROR("We shouldn't ever get a strange event from main thread XHR!");
     return NS_OK;
   }
 
+  // This will be filled if the request has completed and we're running in
+  // sync mode.
+  nsRefPtr<nsDOMWorkerXHRFinishSyncXHRRunnable> syncFinishedRunnable;
+
   PRBool requestDone;
   if (type == LISTENER_TYPE_ABORT || type == LISTENER_TYPE_ERROR ||
       type == LISTENER_TYPE_LOAD) {
     requestDone = PR_TRUE;
 
     nsAutoPtr<ProgressInfo>& progressInfo = isUpload ?
                                             mUploadProgressInfo :
                                             mDownloadProgressInfo;
@@ -755,18 +758,20 @@ nsDOMWorkerXHRProxy::HandleEvent(nsIDOME
       NS_ASSERTION(progressEvent, "Should always QI to nsIDOMProgressEvent!");
       if (progressEvent) {
         progressEvent->GetLengthComputable(&progressInfo->computable);
         progressEvent->GetLoaded(&progressInfo->loaded);
         progressEvent->GetTotal(&progressInfo->total);
       }
     }
 
-    // Dummy memory barrier.
+    NS_ASSERTION(!syncFinishedRunnable, "This shouldn't be set!");
+
     nsAutoLock lock(mWorkerXHR->Lock());
+    mSyncFinishedRunnable.swap(syncFinishedRunnable);
   }
   else {
     requestDone = PR_FALSE;
   }
 
   if (mCanceled) {
     // When Abort is called on nsXMLHttpRequest (either from a proxied Abort
     // call or from DestroyInternal) the OnStopRequest call is not run
@@ -813,17 +818,23 @@ nsDOMWorkerXHRProxy::HandleEvent(nsIDOME
       if (newEvent) {
         // Already had a saved progress/load event so no need to generate
         // another. Bail out rather than dispatching runnable.
         return NS_OK;
       }
     }
   }
 
-  return HandleEventRunnable(runnable);
+  rv = HandleEventRunnable(runnable);
+
+  if (syncFinishedRunnable) {
+    syncFinishedRunnable->Dispatch();
+  }
+
+  return rv;
 }
 
 nsresult
 nsDOMWorkerXHRProxy::HandleEventRunnable(nsIRunnable* aRunnable)
 {
   NS_ASSERTION(aRunnable, "Null pointer!");
 
   nsresult rv;
@@ -1157,21 +1168,10 @@ nsDOMWorkerXHRProxy::OnStopRequest(nsIRe
                                    nsresult /* aStatus */)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   NS_ASSERTION(mOwnedByXHR, "Inconsistent state!");
 
   FlipOwnership();
 
-  nsRefPtr<nsDOMWorkerXHRFinishSyncXHRRunnable> syncFinishedRunnable;
-  {
-    nsAutoLock lock(mWorkerXHR->Lock());
-    mSyncFinishedRunnable.swap(syncFinishedRunnable);
-  }
-
-  if (syncFinishedRunnable) {
-    nsresult rv = syncFinishedRunnable->Dispatch();
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
   return NS_OK;
 }
--- a/dom/src/threads/test/relativeLoad_sub_worker.js
+++ b/dom/src/threads/test/relativeLoad_sub_worker.js
@@ -1,11 +1,18 @@
 const importSubURL = "relativeLoad_sub_import.js";
 
 onmessage = function(event) {
+  var xhr = new XMLHttpRequest();
+  xhr.open("GET", "testXHR.txt", false);
+  xhr.send(null);
+  if (xhr.status != 404) {
+    throw "Loaded an xhr from the wrong location!";
+  }
+
   importScripts(importSubURL);
   var worker = new Worker("relativeLoad_sub_worker2.js");
   worker.onerror = function(event) {
     throw event.data;
   };
   worker.onmessage = function(event) {
     if (event.data != workerSubURL) {
       throw "Bad data!";
--- a/dom/src/threads/test/relativeLoad_worker.js
+++ b/dom/src/threads/test/relativeLoad_worker.js
@@ -1,11 +1,20 @@
 const importURL = "relativeLoad_import.js";
 
 onmessage = function(event) {
+  var xhr = new XMLHttpRequest();
+  xhr.open("GET", "testXHR.txt", false);
+  xhr.send(null);
+  dump("XXXben: " + xhr.responseText + "\n");
+  if (xhr.status != 200 ||
+      xhr.responseText != "A noisy noise annoys an oyster.") {
+    throw "Couldn't get xhr text from where we wanted it!";
+  }
+
   importScripts(importURL);
   var worker = new Worker("relativeLoad_worker2.js");
   worker.onerror = function(event) {
     throw event.data;
   };
   worker.onmessage = function(event) {
     if (event.data != workerURL) {
       throw "Bad data!";
deleted file mode 100644
--- a/editor/README.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<html>
-<!-- ***** 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) 1998-1999
-   - the Initial Developer. All Rights Reserved.
-   -
-   - Contributor(s):
-   -   Daniel Howard
-   -
-   - Alternatively, the contents of this file may be used under the terms of
-   - either of 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 ***** -->
-<body>
-<h1>
-<span CLASS=LXRSHORTDESC>
-HTML (i.e. Composer) and plaintext editor<p>
-</span>
-</h1>
-<span CLASS=LXRLONGDESC>
-The editor directory contains C++ interfaces, C++ code, and XUL/Javascript
-for the embeddable editor component, which is used for the HTML Editor
-("Composer"), for plain and html mail compose, and for text fields and
-text areas throughout the product.
-<p>
-The editor is designed like a "browser window with editing features": it
-adds some special classes for editing text and managing transaction
-undo/redo, but reuses browser code for nearly everything else.
-</span>
-</body>
-</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/crashtests/467647-1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script type="text/javascript">
+
+function boom()
+{
+  document.getElementById("s").focus();
+  try { 
+    document.execCommand("insertorderedlist", false, null);
+  } catch(e) { }
+}
+
+</script>
+</head>
+
+<body onload="boom();"><span id="s" contenteditable="true">One<div></div></span><marquee></marquee></body>
+
+</html>
--- a/editor/libeditor/html/crashtests/crashtests.list
+++ b/editor/libeditor/html/crashtests/crashtests.list
@@ -1,6 +1,7 @@
 load 336081-1.xhtml # asserts (no bug?)
 load 382778-1.html
 load 407074-1.html
 load 407277-1.html
 load 420439.html
 load 428489-1.html
+load 467647-1.html
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -79,16 +79,17 @@
 #include "InsertTextTxn.h"
 #include "DeleteTextTxn.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 
 #include "nsFrameSelection.h"
 #include "nsIDOM3Node.h"
 #include "nsContentUtils.h"
+#include "nsTArray.h"
 
 //const static char* kMOZEditorBogusNodeAttr="MOZ_EDITOR_BOGUS_NODE";
 //const static char* kMOZEditorBogusNodeValue="TRUE";
 
 enum
 {
   kLonely = 0,
   kPrevSib = 1,
@@ -5753,49 +5754,52 @@ nsHTMLEditRules::GetNodesForOperation(ns
 
   nsresult res = NS_OK;
   
   // bust up any inlines that cross our range endpoints,
   // but only if we are allowed to touch content.
   
   if (!aDontTouchContent)
   {
-    nsVoidArray rangeItemArray;
+    nsAutoTArray<nsRangeStore, 16> rangeItemArray;
+    if (!rangeItemArray.AppendElements(rangeCount)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    NS_ASSERTION(rangeCount == rangeItemArray.Length(), "How did that happen?");
+
     // first register ranges for special editor gravity
-    // XXXbz doesn't this leak all the nsRangeStore structs on error
-    // conditions??
     for (i = 0; i < (PRInt32)rangeCount; i++)
     {
       opRange = inArrayOfRanges[0];
-      nsRangeStore *item = new nsRangeStore();
-      if (!item) return NS_ERROR_NULL_POINTER;
+      nsRangeStore *item = rangeItemArray.Elements() + i;
       item->StoreRange(opRange);
       mHTMLEditor->mRangeUpdater.RegisterRangeItem(item);
-      rangeItemArray.AppendElement((void*)item);
       inArrayOfRanges.RemoveObjectAt(0);
     }    
-    // now bust up inlines
-    for (i = rangeCount-1; i >= 0; i--)
-    {
-      nsRangeStore *item = (nsRangeStore*)rangeItemArray.ElementAt(i);
-      res = BustUpInlinesAtRangeEndpoints(*item);
-      if (NS_FAILED(res)) return res;    
+    // now bust up inlines.  Safe to start at rangeCount-1, since we
+    // asserted we have enough items above.
+    for (i = rangeCount-1; i >= 0 && NS_SUCCEEDED(res); i--)
+    {
+      res = BustUpInlinesAtRangeEndpoints(rangeItemArray[i]);
     } 
     // then unregister the ranges
     for (i = 0; i < rangeCount; i++)
     {
-      nsRangeStore *item = (nsRangeStore*)rangeItemArray.ElementAt(0);
-      if (!item) return NS_ERROR_NULL_POINTER;
-      rangeItemArray.RemoveElementAt(0);
+      nsRangeStore *item = rangeItemArray.Elements() + i;
       mHTMLEditor->mRangeUpdater.DropRangeItem(item);
-      res = item->GetRange(address_of(opRange));
-      if (NS_FAILED(res)) return res;
-      delete item;
+      nsresult res2 = item->GetRange(address_of(opRange));
+      if (NS_FAILED(res2) && NS_SUCCEEDED(res)) {
+        // Remember the failure, but keep going so we make sure to unregister
+        // all our range items.
+        res = res2;
+      }
       inArrayOfRanges.AppendObject(opRange);
-    }    
+    }
+    if (NS_FAILED(res)) return res;
   }
   // gather up a list of all the nodes
   for (i = 0; i < rangeCount; i++)
   {
     opRange = inArrayOfRanges[i];
     
     nsDOMSubtreeIterator iter;
     res = iter.Init(opRange);
--- a/editor/libeditor/text/nsEditorEventListeners.cpp
+++ b/editor/libeditor/text/nsEditorEventListeners.cpp
@@ -1037,23 +1037,22 @@ FindSelectionRoot(nsIEditor *aEditor, ns
 
     return root;
   }
 
   if (flags & nsIPlaintextEditor::eEditorReadonlyMask) {
     // We still want to allow selection in a readonly editor.
     nsCOMPtr<nsIDOMElement> rootElement;
     aEditor->GetRootElement(getter_AddRefs(rootElement));
+    if (!rootElement) {
+      return nsnull;
+    }
 
     CallQueryInterface(rootElement, &root);
 
-    if (!root && document) {
-      NS_IF_ADDREF(root = document->GetRootContent());
-    }
-
     return root;
   }
 
   if (!aContent->HasFlag(NODE_IS_EDITABLE)) {
     return nsnull;
   }
 
   // For non-readonly editors we want to find the root of the editable subtree
--- a/extensions/universalchardet/src/base/nsCodingStateMachine.h
+++ b/extensions/universalchardet/src/base/nsCodingStateMachine.h
@@ -91,17 +91,16 @@ protected:
 
 extern SMModel UTF8SMModel;
 extern SMModel Big5SMModel;
 extern SMModel EUCJPSMModel;
 extern SMModel EUCKRSMModel;
 extern SMModel EUCTWSMModel;
 extern SMModel GB18030SMModel;
 extern SMModel SJISSMModel;
-extern SMModel UCS2BESMModel;
 
 
 extern SMModel HZSMModel;
 extern SMModel ISO2022CNSMModel;
 extern SMModel ISO2022JPSMModel;
 extern SMModel ISO2022KRSMModel;
 
 #endif /* nsCodingStateMachine_h__ */
--- a/extensions/universalchardet/src/base/nsMBCSSM.cpp
+++ b/extensions/universalchardet/src/base/nsMBCSSM.cpp
@@ -429,129 +429,16 @@ SMModel SJISSMModel = {
   {eIdxSft4bits, eSftMsk4bits, eBitSft4bits, eUnitMsk4bits, SJIS_cls },
    6,
   {eIdxSft4bits, eSftMsk4bits, eBitSft4bits, eUnitMsk4bits, SJIS_st },
   SJISCharLenTable,
   "Shift_JIS",
 };
 
 
-static PRUint32 UCS2BE_cls [ 256 / 8 ] = {
-PCK4BITS(0,0,0,0,0,0,0,0),  // 00 - 07 
-PCK4BITS(0,0,1,0,0,2,0,0),  // 08 - 0f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 10 - 17 
-PCK4BITS(0,0,0,3,0,0,0,0),  // 18 - 1f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 20 - 27 
-PCK4BITS(0,3,3,3,3,3,0,0),  // 28 - 2f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 30 - 37 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 38 - 3f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 40 - 47 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 48 - 4f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 50 - 57 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 58 - 5f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 60 - 67 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 68 - 6f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 70 - 77 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 78 - 7f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 80 - 87 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 88 - 8f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 90 - 97 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 98 - 9f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // a0 - a7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // a8 - af 
-PCK4BITS(0,0,0,0,0,0,0,0),  // b0 - b7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // b8 - bf 
-PCK4BITS(0,0,0,0,0,0,0,0),  // c0 - c7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // c8 - cf 
-PCK4BITS(0,0,0,0,0,0,0,0),  // d0 - d7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // d8 - df 
-PCK4BITS(0,0,0,0,0,0,0,0),  // e0 - e7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // e8 - ef 
-PCK4BITS(0,0,0,0,0,0,0,0),  // f0 - f7 
-PCK4BITS(0,0,0,0,0,0,4,5)   // f8 - ff 
-};
-
-
-static PRUint32 UCS2BE_st [ 7] = {
-PCK4BITS(     5,     7,     7,eError,     4,     3,eError,eError),//00-07 
-PCK4BITS(eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe),//08-0f 
-PCK4BITS(eItsMe,eItsMe,     6,     6,     6,     6,eError,eError),//10-17 
-PCK4BITS(     6,     6,     6,     6,     6,eItsMe,     6,     6),//18-1f 
-PCK4BITS(     6,     6,     6,     6,     5,     7,     7,eError),//20-27 
-PCK4BITS(     5,     8,     6,     6,eError,     6,     6,     6),//28-2f 
-PCK4BITS(     6,     6,     6,     6,eError,eError,eStart,eStart) //30-37 
-};
-
-static const PRUint32 UCS2BECharLenTable[] = {2, 2, 2, 0, 2, 2};
-
-SMModel UCS2BESMModel = {
-  {eIdxSft4bits, eSftMsk4bits, eBitSft4bits, eUnitMsk4bits, UCS2BE_cls },
-   6,
-  {eIdxSft4bits, eSftMsk4bits, eBitSft4bits, eUnitMsk4bits, UCS2BE_st },
-  UCS2BECharLenTable,
-  "UTF-16BE",
-};
-
-static PRUint32 UCS2LE_cls [ 256 / 8 ] = {
-PCK4BITS(0,0,0,0,0,0,0,0),  // 00 - 07 
-PCK4BITS(0,0,1,0,0,2,0,0),  // 08 - 0f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 10 - 17 
-PCK4BITS(0,0,0,3,0,0,0,0),  // 18 - 1f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 20 - 27 
-PCK4BITS(0,3,3,3,3,3,0,0),  // 28 - 2f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 30 - 37 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 38 - 3f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 40 - 47 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 48 - 4f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 50 - 57 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 58 - 5f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 60 - 67 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 68 - 6f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 70 - 77 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 78 - 7f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 80 - 87 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 88 - 8f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 90 - 97 
-PCK4BITS(0,0,0,0,0,0,0,0),  // 98 - 9f 
-PCK4BITS(0,0,0,0,0,0,0,0),  // a0 - a7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // a8 - af 
-PCK4BITS(0,0,0,0,0,0,0,0),  // b0 - b7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // b8 - bf 
-PCK4BITS(0,0,0,0,0,0,0,0),  // c0 - c7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // c8 - cf 
-PCK4BITS(0,0,0,0,0,0,0,0),  // d0 - d7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // d8 - df 
-PCK4BITS(0,0,0,0,0,0,0,0),  // e0 - e7 
-PCK4BITS(0,0,0,0,0,0,0,0),  // e8 - ef 
-PCK4BITS(0,0,0,0,0,0,0,0),  // f0 - f7 
-PCK4BITS(0,0,0,0,0,0,4,5)   // f8 - ff 
-};
-
-
-static PRUint32 UCS2LE_st [ 7] = {
-PCK4BITS(     6,     6,     7,     6,     4,     3,eError,eError),//00-07 
-PCK4BITS(eError,eError,eError,eError,eItsMe,eItsMe,eItsMe,eItsMe),//08-0f 
-PCK4BITS(eItsMe,eItsMe,     5,     5,     5,eError,eItsMe,eError),//10-17 
-PCK4BITS(     5,     5,     5,eError,     5,eError,     6,     6),//18-1f 
-PCK4BITS(     7,     6,     8,     8,     5,     5,     5,eError),//20-27 
-PCK4BITS(     5,     5,     5,eError,eError,eError,     5,     5),//28-2f 
-PCK4BITS(     5,     5,     5,eError,     5,eError,eStart,eStart) //30-37 
-};
-
-static const PRUint32 UCS2LECharLenTable[] = {2, 2, 2, 2, 2, 2};
-
-SMModel UCS2LESMModel = {
-  {eIdxSft4bits, eSftMsk4bits, eBitSft4bits, eUnitMsk4bits, UCS2LE_cls },
-   6,
-  {eIdxSft4bits, eSftMsk4bits, eBitSft4bits, eUnitMsk4bits, UCS2LE_st },
-  UCS2LECharLenTable,
-  "UTF-16LE",
-};
-
-
 static PRUint32 UTF8_cls [ 256 / 8 ] = {
 //PCK4BITS(0,1,1,1,1,1,1,1),  // 00 - 07 
 PCK4BITS(1,1,1,1,1,1,1,1),  // 00 - 07  //allow 0x00 as a legal value
 PCK4BITS(1,1,1,1,1,1,0,0),  // 08 - 0f 
 PCK4BITS(1,1,1,1,1,1,1,1),  // 10 - 17 
 PCK4BITS(1,1,1,0,1,1,1,1),  // 18 - 1f 
 PCK4BITS(1,1,1,1,1,1,1,1),  // 20 - 27 
 PCK4BITS(1,1,1,1,1,1,1,1),  // 28 - 2f 
--- a/gfx/public/nsIImage.h
+++ b/gfx/public/nsIImage.h
@@ -39,18 +39,18 @@
 #define nsIImage_h___
 
 #include "nsISupports.h"
 #include "nsMargin.h"
 #include "nsRect.h"
 
 class gfxASurface;
 class gfxPattern;
-class gfxMatrix;
-class gfxRect;
+struct gfxMatrix;
+struct gfxRect;
 class gfxContext;
 
 class nsIDeviceContext;
 
 struct nsColorMap
 {
   //I lifted this from the image lib. The difference is that
   //this uses nscolor instead of NI_RGB. Multiple color pollution
deleted file mode 100644
--- a/intl/chardet/tools/genucs2be.pl
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/local/bin/perl
-use strict;
-require "genverifier.pm";
-use genverifier;
-
-
-my(@ucs2be_cls);
-my(@ucs2be_st);
-my($ucs2be_ver);
-
-
-# We look at the following UCS2 char
-# U+FEFF->ItsMe if it is the first Unicode
-# U+FFFF->Error
-# U+FFFE->Error
-# U+0d0d->Error
-# U+0a0d->Error
-# U+1bxx->Error
-# U+29xx->Error
-# U+2axx->Error
-# U+2bxx->Error
-# U+2cxx->Error
-# U+2dxx->Error
-# 
-# In UCS2-Big Endian it will be
-# 
-# Ev Od 
-# FE FF->ItsMe for the first two bytes
-# FF FF->Error
-# FF FE->Error
-# 0d 0d->Error
-# 0a 0d->Error
-# 1b   ->Error
-# 29   ->Error
-# 2a   ->Error
-# 2b   ->Error
-# 2c   ->Error
-# 2d   ->Error
-# 
-# Now we classified the char
-# 0a:k1
-# 0d:k2
-# 1b:k3
-# 29-2d:k3
-# fe:k4
-# ff:k5
-# others:k0
-# 
-@ucs2be_cls = (
- [ 0x0a, 0x0a, 1 ],
- [ 0x0d, 0x0d, 2 ],
- [ 0x1b, 0x1b, 3 ],
- [ 0x29, 0x2d, 3 ],
- [ 0xfe, 0xfe, 4 ],
- [ 0xff, 0xff, 5 ],
- [ 0x00, 0xff, 0 ]
-);
-
-
-# For Big Endian 
-# 
-# 0:k5->3
-# 0:k4->4
-# 0:k1,k2->7
-# 0:k3->1
-# 0:k0->5
-# 3:k4,k5->1
-# 3:*->6
-# 4:k5->2
-# 4:*->6
-# 5:*->6
-# 6:k1,k2->7
-# 6:k3->1
-# 6:k5->8
-# 6:*->5
-# 7:k2->1
-# 7:*->6
-# 8:k4,k5->1
-# 8:*->6
-
-package genverifier;
-@ucs2be_st = (
-# 0  1  2  3  4  5  
-  5, 7, 7, 1, 4, 3,  # state 0 - Start
-  1, 1, 1, 1, 1, 1,  # state 1 - Error
-  2, 2, 2, 2, 2, 2,  # state 2 - ItsMe
-  6, 6, 6, 6, 1, 1,  # state 3   1st byte got FF
-  6, 6, 6, 6, 6, 2,  # state 4   1st byte got FE
-  6, 6, 6, 6, 6, 6,  # state 5   Odd byte
-  5, 7, 7, 1, 5, 8,  # state 6   Even Byte
-  6, 6, 1, 6, 6, 6,  # state 7   Got 0A or 0D
-  6, 6, 6, 6, 1, 1,  # state 8   Got FF
-);
-
-
-$ucs2be_ver = genverifier::GenVerifier("UCS2BE", "UTF-16BE", 
-               \@ucs2be_cls, 6,     \@ucs2be_st);
-print $ucs2be_ver;
-
-
-
deleted file mode 100644
--- a/intl/chardet/tools/genucs2le.pl
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/local/bin/perl
-use strict;
-require "genverifier.pm";
-use genverifier;
-
-
-my(@ucs2le_cls);
-my(@ucs2le_st);
-my($ucs2le_ver);
-
-# We look at the following UCS2
-# U+FEFF->ItsMe if it is the first Unicode
-# U+FFFF->Error
-# U+FFFE->Error
-# U+0d0d->Error
-# U+0a0d->Error
-# U+1bxx->Error
-# U+29xx->Error
-# U+2axx->Error
-# U+2bxx->Error
-# U+2cxx->Error
-# U+2dxx->Error
-# 
-# In UCS2-Little Endian it will be
-# 
-# Ev Od
-# FF FE->ItsMe for the first two bytes
-# FF FF->Error
-# FE FF->Error
-# 0d 0d->Error
-# 0d 0a->Error
-#    1b->Error
-#    29->Error
-#    2a->Error
-#    2b->Error
-#    2c->Error
-#    2d->Error
-# 
-# Now we classified the char
-# 0a:k1
-# 0d:k2
-# 1b:k3
-# 29-2d:k3
-# fe:k4
-# ff:k5
-# others:k0
-
-@ucs2le_cls = (
- [ 0x0a, 0x0a, 1 ],
- [ 0x0d, 0x0d, 2 ],
- [ 0x1b, 0x1b, 3 ],
- [ 0x29, 0x2d, 3 ],
- [ 0xfe, 0xfe, 4 ],
- [ 0xff, 0xff, 5 ],
- [ 0x00, 0xff, 0 ]
-);
-
-
-# For Little Endian 
-# 0:k5->3
-# 0:k4->4
-# 0:k2->7
-# 0:*->6
-# 3:k4->2
-# 3:k5->1
-# 3:k3->1
-# 3:*->5
-# 4:k3,k5->1
-# 4:*->5
-# 5:k4,k5->8
-# 5:k2->7
-# 5:*->6
-# 6:k3->1
-# 6:*->5
-# 7:k1,k2->1
-# 7:k3->1
-# 7:*->5
-# 8:k5->1
-# 8:k3->1
-# 8:*->5
-
-
-package genverifier;
-@ucs2le_st = (
-# 0  1  2  3  4  5  
-  6, 6, 7, 6, 4, 3, # state 0 - Start
-  1, 1, 1, 1, 1, 1, # state 1 - Error
-  2, 2, 2, 2, 2, 2, # state 2 - ItsMe
-  5, 5, 5, 1, 2, 1, # state 3   1st byte Got FF 
-  5, 5, 5, 1, 5, 1, # state 4   1st byte Got FE
-  6, 6, 7, 6, 8, 8, # state 5   Even Byte
-  5, 5, 5, 1, 5, 5, # state 6   Odd Byte
-  5, 1, 1, 1, 5, 5, # state 7   Got 0d
-  5, 5, 5, 1, 5, 1, # state 8   Got FF
-);
-
-
-$ucs2le_ver = genverifier::GenVerifier("UCS2LE", "UTF-16LE", \@ucs2le_cls,
-              6,     \@ucs2le_st);
-print $ucs2le_ver;
-
-
-
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -51,28 +51,25 @@ endif
 
 ifndef JS_MOZ_INSTALL
 # This is the appropriate behavior for GNU-style 'make install'.  For
 # Mozilla in-tree behavior, leaving NSDISTMODE unset is the right
 # thing; config/js/Makefile.in sets JS_MOZ_INSTALL in that case.
 NSDISTMODE	= copy
 endif
 
-ifdef JS_NATIVE_EDITLINE
-DIRS += editline
-endif
+MODULE		= js
+LIBRARY_NAME	= mozjs
+GRE_MODULE	= 1
 
-# editline needs to get built before the shell
-DIRS += shell
-
-MODULE		    = js
-LIBRARY_NAME	    = mozjs
-STATIC_LIBRARY_NAME = js_static
-GRE_MODULE	    = 1
-
+PROGRAM         = js$(BIN_SUFFIX)
+# The shell uses some 'HIDDEN' symbols to produce statistics, so we
+# link directly against the .o files, not against the JS shared
+# library.
+PROGOBJS	= js.$(OBJ_SUFFIX) $(OBJS)
 LIBS		= $(NSPR_LIBS)
 
 ifdef GNU_CXX
 ifdef INTEL_CXX
 # icc gets special optimize flags
 ifdef MOZ_PROFILE_GENERATE
 MODULE_OPTIMIZE_FLAGS = -O0
 else
@@ -102,22 +99,20 @@ endif
 ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
 LIBRARY_NAME	= js$(MOZ_BITS)$(VERSION_NUMBER)
 endif
 
 # JavaScript must be built shared, even for static builds, as it is used by
 # other modules which are always built shared. Failure to do so results in
 # the js code getting copied into xpinstall and jsd as well as mozilla-bin,
 # and then the static data cells used for locking no longer work.
-#
-# In fact, we now build both a static and a shared library, as the
-# JS shell would like to link to the static library.
 
+ifndef JS_STATIC_BUILD
 FORCE_SHARED_LIB = 1
-FORCE_STATIC_LIB = 1
+endif
 
 ifeq (86,$(findstring 86,$(OS_TEST)))
 ifeq (64,$(findstring 64,$(OS_TEST)))
 else
 DEFINES += -DAVMPLUS_IA32
 NANOJIT_ARCH = i386
 ENABLE_JIT = 1
 endif
@@ -619,32 +614,30 @@ js-config: js-config.in Makefile $(DEPTH
 SCRIPTS = js-config
 
 install:: $(INSTALLED_HEADERS)
 	$(INSTALL) $(IFLAGS1) $^ $(includedir)/$(MODULE)
 
 install:: $(SCRIPTS) $(PROGRAM)
 	$(INSTALL) $(IFLAGS2) $^ $(bindir)
 
-install:: $(LIBRARY)
-ifneq (,$(LIBRARY))
-	$(INSTALL) $(IFLAGS1) $(LIBRARY) $(libdir)
-endif
-ifneq (,$(IMPORT_LIBRARY))
-	$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(libdir)
-endif
-
 # The Mozilla top-level makefiles use install-runtime-libs directly to
 # place an additional copy of the libraries in the 'dist/bin'
 # directory.
 install:: install-runtime-libs
 install-runtime-libs:: $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
+ifneq (,$(LIBRARY))
+	$(INSTALL) $(IFLAGS1) $(LIBRARY) $(libdir)
+endif
 ifneq (,$(SHARED_LIBRARY))
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(libdir)
 endif
+ifneq (,$(IMPORT_LIBRARY))
+	$(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(libdir)
+endif
 
 # Extra dependancies and rules for auto-generated headers
 host_jskwgen.$(OBJ_SUFFIX): jsversion.h jskeyword.tbl
 
 # Use CURDIR to avoid finding a jsautokw.h in the source tree (from a
 # previous build?) via VPATH when we're building in a separate tree.
 $(CURDIR)/jsautokw.h: host_jskwgen$(HOST_BIN_SUFFIX)
 	./host_jskwgen$(HOST_BIN_SUFFIX) $@
--- a/js/src/config/autoconf.mk.in
+++ b/js/src/config/autoconf.mk.in
@@ -101,16 +101,17 @@ EAZEL_PROFILER_CFLAGS=@EAZEL_PROFILER_CF
 EAZEL_PROFILER_LIBS=@EAZEL_PROFILER_LIBS@
 GC_LEAK_DETECTOR = @GC_LEAK_DETECTOR@
 NS_TRACE_MALLOC = @NS_TRACE_MALLOC@
 INCREMENTAL_LINKER = @INCREMENTAL_LINKER@
 MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@
 BUILD_STATIC_LIBS = @BUILD_STATIC_LIBS@
 ENABLE_TESTS	= @ENABLE_TESTS@
 JS_ULTRASPARC_OPTS = @JS_ULTRASPARC_OPTS@
+JS_STATIC_BUILD = @JS_STATIC_BUILD@
 
 TAR=@TAR@
 
 # The MOZ_UI_LOCALE var is used to build a particular locale. Do *not*
 # use the var to change any binary files. Do *not* use this var unless you
 # write rules for the "clean-locale" and "locale" targets.
 MOZ_UI_LOCALE = @MOZ_UI_LOCALE@
 
@@ -263,19 +264,16 @@ SDP		= @SDP@
 NSINSTALL_BIN	= @NSINSTALL_BIN@
 
 NSPR_CONFIG	= @NSPR_CONFIG@
 NSPR_CFLAGS	= @NSPR_CFLAGS@
 NSPR_LIBS	= @NSPR_LIBS@
 
 USE_DEPENDENT_LIBS = @USE_DEPENDENT_LIBS@
 
-JS_NATIVE_EDITLINE = @JS_NATIVE_EDITLINE@
-EDITLINE_LIBS      = @EDITLINE_LIBS@
-
 # MKSHLIB_FORCE_ALL is used to force the linker to include all object
 # files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker
 # to normal behavior. Makefile's that create shared libraries out of
 # archives use these flags to force in all of the .o files in the
 # archives into the shared library.
 WRAP_MALLOC_LIB         = @WRAP_MALLOC_LIB@
 WRAP_MALLOC_CFLAGS      = @WRAP_MALLOC_CFLAGS@
 DSO_CFLAGS              = @DSO_CFLAGS@
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -68,18 +68,16 @@ COMMA = ,
 CHECK_VARS := \
  XPI_NAME \
  LIBRARY_NAME \
  MODULE \
  DEPTH \
  SHORT_LIBNAME \
  XPI_PKGNAME \
  INSTALL_EXTENSION_ID \
- SHARED_LIBRARY_NAME \
- STATIC_LIBRARY_NAME \
  $(NULL)
 
 # checks for internal spaces or trailing spaces in the variable
 # named by $x
 check-variable = $(if $(filter-out 0 1,$(words $($(x))z)),$(error Spaces are not allowed in $(x)))
 
 $(foreach x,$(CHECK_VARS),$(check-variable))
 
@@ -356,28 +354,16 @@ ifndef _ENABLE_PIC
 DSO_CFLAGS=
 ifeq ($(OS_ARCH)_$(HAVE_GCC3_ABI),Darwin_1)
 DSO_PIC_CFLAGS=-mdynamic-no-pic
 else
 DSO_PIC_CFLAGS=
 endif
 endif
 
-ifndef SHARED_LIBRARY_NAME
-ifdef LIBRARY_NAME
-SHARED_LIBRARY_NAME=$(LIBRARY_NAME)
-endif
-endif
-
-ifndef STATIC_LIBRARY_NAME
-ifdef LIBRARY_NAME
-STATIC_LIBRARY_NAME=$(LIBRARY_NAME)
-endif
-endif
-
 # This comes from configure
 ifdef MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 endif
 
 # Enable profile-based feedback
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
 ifdef MOZ_PROFILE_GENERATE
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -214,52 +214,52 @@ endif # ENABLE_TESTS
 #
 # Library rules
 #
 # If BUILD_STATIC_LIBS or FORCE_STATIC_LIB is set, build a static library.
 # Otherwise, build a shared library.
 #
 
 ifndef LIBRARY
-ifdef STATIC_LIBRARY_NAME
+ifdef LIBRARY_NAME
 ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
 ifdef SHORT_LIBNAME
-STATIC_LIBRARY_NAME	:= $(SHORT_LIBNAME)
+LIBRARY_NAME		:= $(SHORT_LIBNAME)
 endif
 endif
-LIBRARY			:= $(LIB_PREFIX)$(STATIC_LIBRARY_NAME).$(LIB_SUFFIX)
-endif # STATIC_LIBRARY_NAME
-endif # LIBRARY
+LIBRARY			:= $(LIB_PREFIX)$(LIBRARY_NAME).$(LIB_SUFFIX)
+endif
+endif
 
 ifndef HOST_LIBRARY
 ifdef HOST_LIBRARY_NAME
 HOST_LIBRARY		:= $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX)
 endif
 endif
 
 ifdef LIBRARY
 ifneq (_1,$(FORCE_SHARED_LIB)_$(BUILD_STATIC_LIBS))
 ifdef MKSHLIB
 
 ifdef LIB_IS_C_ONLY
 MKSHLIB			= $(MKCSHLIB)
 endif
 
 ifdef MAKE_FRAMEWORK
-SHARED_LIBRARY		:= $(SHARED_LIBRARY_NAME)
+SHARED_LIBRARY		:= $(LIBRARY_NAME)
 else
-SHARED_LIBRARY		:= $(DLL_PREFIX)$(SHARED_LIBRARY_NAME)$(DLL_SUFFIX)
+SHARED_LIBRARY		:= $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
 endif
 
 ifeq ($(OS_ARCH),OS2)
 DEF_FILE		:= $(SHARED_LIBRARY:.dll=.def)
 endif
 
 ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
-IMPORT_LIBRARY		:= $(LIB_PREFIX)$(SHARED_LIBRARY_NAME).$(IMPORT_LIB_SUFFIX)
+IMPORT_LIBRARY		:= $(LIB_PREFIX)$(LIBRARY_NAME).$(IMPORT_LIB_SUFFIX)
 endif
 
 ifdef MOZ_ENABLE_LIBXUL
 EMBED_MANIFEST_AT=2
 endif
 
 endif # MKSHLIB
 endif # FORCE_SHARED_LIB && !BUILD_STATIC_LIBS
@@ -314,32 +314,39 @@ COMPILE_PDBFILE = generated.pdb
 endif
 
 LINK_PDBFILE = $(basename $(@F)).pdb
 ifdef MOZ_DEBUG
 CODFILE=$(basename $(@F)).cod
 endif
 
 ifdef MOZ_MAPINFO
-ifdef SHARED_LIBRARY_NAME
-MAPFILE=$(SHARED_LIBRARY_NAME).map
+ifdef LIBRARY_NAME
+MAPFILE=$(LIBRARY_NAME).map
 else
 MAPFILE=$(basename $(@F)).map
 endif # LIBRARY_NAME
 endif # MOZ_MAPINFO
 
 ifdef DEFFILE
 OS_LDFLAGS += -DEF:$(DEFFILE)
 EXTRA_DEPS += $(DEFFILE)
 endif
 
 ifdef MAPFILE
 OS_LDFLAGS += -MAP:$(MAPFILE)
+#CFLAGS += -Fm$(MAPFILE)
+#CXXFLAGS += -Fm$(MAPFILE)
 endif
 
+#ifdef CODFILE
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#endif
+
 endif # !GNU_CC
 
 ifdef ENABLE_CXX_EXCEPTIONS
 ifdef GNU_CC
 CXXFLAGS		+= -fexceptions
 else
 ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
 CXXFLAGS		+= -GX
@@ -829,23 +836,23 @@ endif
 #
 # Rule to create list of libraries for final link
 #
 export::
 ifdef LIBRARY_NAME
 ifdef EXPORT_LIBRARY
 ifdef IS_COMPONENT
 ifdef BUILD_STATIC_LIBS
-	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMPS) $(STATIC_LIBRARY_NAME)
+	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMPS) $(LIBRARY_NAME)
 ifdef MODULE_NAME
 	@$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMP_NAMES) $(MODULE_NAME)
 endif
-endif # BUILD_STATIC_LIBS
-else  # !IS_COMPONENT
-	$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_LIBS) $(STATIC_LIBRARY_NAME)
+endif
+else
+	$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_LIBS) $(LIBRARY_NAME)
 endif # IS_COMPONENT
 endif # EXPORT_LIBRARY
 endif # LIBRARY_NAME
 
 # Create dependencies on static (and shared EXTRA_DSO_LIBS) libraries
 LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(LIBS))
 HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(HOST_LIBS))
 DSO_LDOPTS_DEPS = $(EXTRA_DSO_LIBS) $(filter %.$(LIB_SUFFIX), $(EXTRA_DSO_LDOPTS))
@@ -1171,17 +1178,17 @@ endif
 
 ifeq (,$(filter-out WINNT WINCE, $(OS_ARCH)))
 $(IMPORT_LIBRARY): $(SHARED_LIBRARY)
 endif
 
 ifeq ($(OS_ARCH),OS2)
 $(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS)
 	rm -f $@
-	echo LIBRARY $(SHARED_LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@
+	echo LIBRARY $(LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@
 	echo PROTMODE >> $@
 	echo CODE    LOADONCALL MOVEABLE DISCARDABLE >> $@
 	echo DATA    PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
 	echo EXPORTS >> $@
 ifeq ($(IS_COMPONENT),1)
 ifeq ($(HAS_EXTRAEXPORTS),1)
 ifndef MOZ_OS2_USE_DECLSPEC
 	$(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -3803,16 +3803,17 @@ dnl = Application
 dnl =
 dnl ========================================================
 
 MOZ_ARG_HEADER(Application)
 
 BUILD_STATIC_LIBS=
 ENABLE_TESTS=1
 MOZ_DBGRINFO_MODULES=
+JS_STATIC_BUILD=
 
 dnl ========================================================
 dnl =
 dnl = Components & Features
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Components and Features)
 
@@ -4740,43 +4741,33 @@ dnl ====================================
 MOZ_ARG_HEADER(Static build options)
 
 MOZ_ARG_ENABLE_BOOL(static,
 [  --enable-static         Enable building of internal static libs],
     BUILD_STATIC_LIBS=1,
     BUILD_STATIC_LIBS=)
 
 dnl ========================================================
-dnl = Link js shell to system readline
+dnl = Force JS to be a static lib
 dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(readline,
-[  --enable-readline  Link js shell to system readline library],
-    JS_WANT_READLINE=1,
-    JS_WANT_READLINE= )
-
-JS_NATIVE_EDITLINE=
-EDITLINE_LIBS=
-
-dnl Conveniently, Win32 sets SKIP_LIBRARY_CHECKS...
-if test -z "$SKIP_LIBRARY_CHECKS"; then
-  if test -n "$JS_WANT_READLINE"; then
-    AC_CHECK_LIB(readline, readline,
-                 EDITLINE_LIBS="-lreadline",
-                 AC_MSG_ERROR([No system readline library found.]))
-  else
-    dnl By default, we use editline
-    JS_NATIVE_EDITLINE=1
-    EDITLINE_LIBS='$(DEPTH)/editline/$(LIB_PREFIX)editline.$(LIB_SUFFIX)'
-  fi
-
-  dnl Either way, we want to build with line editing support.
-  AC_DEFINE(EDITLINE)
+MOZ_ARG_ENABLE_BOOL(js-static-build,
+[  --enable-js-static-build  Force js to be a static lib],
+    JS_STATIC_BUILD=1,
+    JS_STATIC_BUILD= )
+
+AC_SUBST(JS_STATIC_BUILD)
+        
+if test -n "$JS_STATIC_BUILD"; then
+    AC_DEFINE(EXPORT_JS_API)
+
+if test -z "$BUILD_STATIC_LIBS"; then
+    AC_MSG_ERROR([--enable-js-static-build is only compatible with --enable-static])
 fi
-AC_SUBST(JS_NATIVE_EDITLINE)
-AC_SUBST(EDITLINE_LIBS)
+
+fi
 
 dnl ========================================================
 dnl =
 dnl = Standalone module options
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Standalone module options (Not for building Mozilla))
 
@@ -5151,28 +5142,21 @@ egrep -v "$_EGREP_PATTERN" confdefs.h.sa
 AC_OUTPUT_MAKE_DEFS()
 MOZ_DEFINES=$DEFS
 AC_SUBST(MOZ_DEFINES)
 rm -f confdefs.h
 mv confdefs.h.save confdefs.h
 
 MAKEFILES="
   Makefile
-  shell/Makefile
   config/Makefile
   config/autoconf.mk
   config/mkdepend/Makefile
 "
 
-if test -n "$JS_NATIVE_EDITLINE"; then
-   MAKEFILES="$MAKEFILES
-editline/Makefile
-"
-fi
-
 dnl 
 dnl Run a perl script to quickly create the makefiles.
 dnl If it succeeds, it outputs a shell command to set CONFIG_FILES
 dnl   for the files it cannot handle correctly. This way, config.status
 dnl   will handle these files.
 dnl If it fails, nothing is set and config.status will run as usual.
 dnl
 dnl This does not change the $MAKEFILES variable.
deleted file mode 100644
--- a/js/src/editline/Makefile.in
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*- Mode: makefile -*-
-#
-# ***** 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 Spidermonkey build system.
-#
-# The Initial Developer of the Original Code is
-# The Mozilla Foundation.
-# Portions created by the Initial Developer are Copyright (C) 2008
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-# Ted Mielczarek <ted.mielczarek@gmail.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of 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 *****
-
-DEPTH = ..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH           = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-LIBRARY_NAME = editline
-FORCE_STATIC_LIB = 1
-
-CSRCS = editline.c sysunix.c
-
-DEFINES += -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX \
-	-DHAVE_STDLIB -DUNIQUE_HISTORY
-
-include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/js/src/js.cpp
@@ -0,0 +1,4110 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** 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 Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+/*
+ * JS shell.
+ */
+#include "jsstddef.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include "jstypes.h"
+#include "jsarena.h"
+#include "jsutil.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+
+#ifdef LIVECONNECT
+#include "jsjava.h"
+#endif
+
+#ifdef JSDEBUGGER
+#include "jsdebug.h"
+#ifdef JSDEBUGGER_JAVA_UI
+#include "jsdjava.h"
+#endif /* JSDEBUGGER_JAVA_UI */
+#ifdef JSDEBUGGER_C_UI
+#include "jsdb.h"
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+
+#if defined(XP_WIN) || defined(XP_OS2)
+#include <io.h>     /* for isatty() */
+#endif
+
+typedef enum JSShellExitCode {
+    EXITCODE_RUNTIME_ERROR      = 3,
+    EXITCODE_FILE_NOT_FOUND     = 4,
+    EXITCODE_OUT_OF_MEMORY      = 5
+} JSShellExitCode;
+
+size_t gStackChunkSize = 8192;
+
+/* Assume that we can not use more than 5e5 bytes of C stack by default. */
+static size_t gMaxStackSize = 500000;
+static jsuword gStackBase;
+
+static size_t gScriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
+
+static JSBool gEnableBranchCallback = JS_FALSE;
+static uint32 gBranchCount;
+static uint32 gBranchLimit;
+
+int gExitCode = 0;
+JSBool gQuitting = JS_FALSE;
+FILE *gErrFile = NULL;
+FILE *gOutFile = NULL;
+
+static JSBool reportWarnings = JS_TRUE;
+static JSBool compileOnly = JS_FALSE;
+
+typedef enum JSShellErrNum {
+#define MSG_DEF(name, number, count, exception, format) \
+    name = number,
+#include "jsshell.msg"
+#undef MSG_DEF
+    JSShellErr_Limit
+#undef MSGDEF
+} JSShellErrNum;
+
+static const JSErrorFormatString *
+my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
+static JSObject *
+split_setup(JSContext *cx);
+
+#ifdef EDITLINE
+JS_BEGIN_EXTERN_C
+extern char     *readline(const char *prompt);
+extern void     add_history(char *line);
+JS_END_EXTERN_C
+#endif
+
+static JSBool
+GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
+#ifdef EDITLINE
+    /*
+     * Use readline only if file is stdin, because there's no way to specify
+     * another handle.  Are other filehandles interactive?
+     */
+    if (file == stdin) {
+        char *linep = readline(prompt);
+        if (!linep)
+            return JS_FALSE;
+        if (linep[0] != '\0')
+            add_history(linep);
+        strcpy(bufp, linep);
+        JS_free(cx, linep);
+        bufp += strlen(bufp);
+        *bufp++ = '\n';
+        *bufp = '\0';
+    } else
+#endif
+    {
+        char line[256];
+        fprintf(gOutFile, prompt);
+        fflush(gOutFile);
+        if (!fgets(line, sizeof line, file))
+            return JS_FALSE;
+        strcpy(bufp, line);
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+my_BranchCallback(JSContext *cx, JSScript *script)
+{
+    if (++gBranchCount == gBranchLimit) {
+        if (script) {
+            if (script->filename)
+                fprintf(gErrFile, "%s:", script->filename);
+            fprintf(gErrFile, "%u: script branch callback (%u callbacks)\n",
+                    script->lineno, gBranchLimit);
+        } else {
+            fprintf(gErrFile, "native branch callback (%u callbacks)\n",
+                    gBranchLimit);
+        }
+        gBranchCount = 0;
+        return JS_FALSE;
+    }
+#ifdef JS_THREADSAFE
+    if ((gBranchCount & 0xff) == 1) {
+#endif
+        if ((gBranchCount & 0x3fff) == 1)
+            JS_MaybeGC(cx);
+#ifdef JS_THREADSAFE
+        else
+            JS_YieldRequest(cx);
+    }
+#endif
+    return JS_TRUE;
+}
+
+static void
+SetContextOptions(JSContext *cx)
+{
+    jsuword stackLimit;
+
+    if (gMaxStackSize == 0) {
+        /*
+         * Disable checking for stack overflow if limit is zero.
+         */
+        stackLimit = 0;
+    } else {
+#if JS_STACK_GROWTH_DIRECTION > 0
+        stackLimit = gStackBase + gMaxStackSize;
+#else
+        stackLimit = gStackBase - gMaxStackSize;
+#endif
+    }
+    JS_SetThreadStackLimit(cx, stackLimit);
+    JS_SetScriptStackQuota(cx, gScriptStackQuota);
+    if (gEnableBranchCallback) {
+        JS_SetBranchCallback(cx, my_BranchCallback);
+        JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
+    }
+}
+
+static void
+Process(JSContext *cx, JSObject *obj, char *filename, JSBool forceTTY)
+{
+    JSBool ok, hitEOF;
+    JSScript *script;
+    jsval result;
+    JSString *str;
+    char buffer[4096];
+    char *bufp;
+    int lineno;
+    int startline;
+    FILE *file;
+    uint32 oldopts;
+
+    if (forceTTY || !filename || strcmp(filename, "-") == 0) {
+        file = stdin;
+    } else {
+        file = fopen(filename, "r");
+        if (!file) {
+            JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+                                 JSSMSG_CANT_OPEN, filename, strerror(errno));
+            gExitCode = EXITCODE_FILE_NOT_FOUND;
+            return;
+        }
+    }
+
+    SetContextOptions(cx);
+
+#ifndef WINCE
+    /* windows mobile (and possibly other os's) does not have a TTY */
+    if (!forceTTY && !isatty(fileno(file))) {
+        /*
+         * It's not interactive - just execute it.
+         *
+         * Support the UNIX #! shell hack; gobble the first line if it starts
+         * with '#'.  TODO - this isn't quite compatible with sharp variables,
+         * as a legal js program (using sharp variables) might start with '#'.
+         * But that would require multi-character lookahead.
+         */
+        int ch = fgetc(file);
+        if (ch == '#') {
+            while((ch = fgetc(file)) != EOF) {
+                if (ch == '\n' || ch == '\r')
+                    break;
+            }
+        }
+        ungetc(ch, file);
+
+        oldopts = JS_GetOptions(cx);
+        JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+        script = JS_CompileFileHandle(cx, obj, filename, file);
+        JS_SetOptions(cx, oldopts);
+        if (script) {
+            if (!compileOnly)
+                (void)JS_ExecuteScript(cx, obj, script, NULL);
+            JS_DestroyScript(cx, script);
+        }
+
+        if (file != stdin)
+            fclose(file);
+        return;
+    }
+#endif /* WINCE */
+
+    /* It's an interactive filehandle; drop into read-eval-print loop. */
+    lineno = 1;
+    hitEOF = JS_FALSE;
+    do {
+        bufp = buffer;
+        *bufp = '\0';
+
+        /*
+         * Accumulate lines until we get a 'compilable unit' - one that either
+         * generates an error (before running out of source) or that compiles
+         * cleanly.  This should be whenever we get a complete statement that
+         * coincides with the end of a line.
+         */
+        startline = lineno;
+        do {
+            if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
+                hitEOF = JS_TRUE;
+                break;
+            }
+            bufp += strlen(bufp);
+            lineno++;
+        } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
+
+        /* Clear any pending exception from previous failed compiles.  */
+        JS_ClearPendingException(cx);
+        script = JS_CompileScript(cx, obj, buffer, strlen(buffer), "typein",
+                                  startline);
+        if (script) {
+            if (!compileOnly) {
+                ok = JS_ExecuteScript(cx, obj, script, &result);
+                if (ok && !JSVAL_IS_VOID(result)) {
+                    str = JS_ValueToString(cx, result);
+                    if (str)
+                        fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
+                    else
+                        ok = JS_FALSE;
+                }
+            }
+            JS_DestroyScript(cx, script);
+        }
+    } while (!hitEOF && !gQuitting);
+    fprintf(gOutFile, "\n");
+    if (file != stdin)
+        fclose(file);
+    return;
+}
+
+static int
+usage(void)
+{
+    fprintf(gErrFile, "%s\n", JS_GetImplementationVersion());
+    fprintf(gErrFile, "usage: js [-zKPswWxCi] [-b branchlimit] [-c stackchunksize] [-o option] [-v version] [-f scriptfile] [-e script] [-S maxstacksize] "
+#ifdef JS_GC_ZEAL
+"[-Z gczeal] "
+#endif
+"[scriptfile] [scriptarg...]\n");
+    return 2;
+}
+
+/*
+ * JSContext option name to flag map. The option names are in alphabetical
+ * order for better reporting.
+ */
+static const struct {
+    const char  *name;
+    uint32      flag;
+} js_options[] = {
+    {"anonfunfix",      JSOPTION_ANONFUNFIX},
+    {"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)
+{
+    for (size_t i = 0; i != JS_ARRAY_LENGTH(js_options); ++i) {
+        if (strcmp(name, js_options[i].name) == 0)
+            return js_options[i].flag;
+    }
+
+    char* msg = JS_sprintf_append(NULL,
+                                  "unknown option name '%s'."
+                                  " The valid names are ", name);
+    for (size_t i = 0; i != JS_ARRAY_LENGTH(js_options); ++i) {
+        if (!msg)
+            break;
+        msg = JS_sprintf_append(msg, "%s%s", js_options[i].name,
+                                (i + 2 < JS_ARRAY_LENGTH(js_options)
+                                 ? ", "
+                                 : i + 2 == JS_ARRAY_LENGTH(js_options)
+                                 ? " and "
+                                 : "."));
+    }
+    if (!msg) {
+        JS_ReportOutOfMemory(cx);
+    } else {
+        JS_ReportError(cx, msg);
+        free(msg);
+    }
+    return 0;
+}
+
+extern JSClass global_class;
+
+static int
+ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
+{
+    int i, j, length;
+    JSObject *argsObj;
+    char *filename = NULL;
+    JSBool isInteractive = JS_TRUE;
+    JSBool forceTTY = JS_FALSE;
+
+    /*
+     * Scan past all optional arguments so we can create the arguments object
+     * before processing any -f options, which must interleave properly with
+     * -v and -w options.  This requires two passes, and without getopt, we'll
+     * have to keep the option logic here and in the second for loop in sync.
+     */
+    for (i = 0; i < argc; i++) {
+        if (argv[i][0] != '-' || argv[i][1] == '\0') {
+            ++i;
+            break;
+        }
+        switch (argv[i][1]) {
+          case 'b':
+          case 'c':
+          case 'f':
+          case 'e':
+          case 'v':
+          case 'S':
+#ifdef JS_GC_ZEAL
+          case 'Z':
+#endif
+            ++i;
+            break;
+          default:;
+        }
+    }
+
+    /*
+     * Create arguments early and define it to root it, so it's safe from any
+     * GC calls nested below, and so it is available to -f <file> arguments.
+     */
+    argsObj = JS_NewArrayObject(cx, 0, NULL);
+    if (!argsObj)
+        return 1;
+    if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj),
+                           NULL, NULL, 0)) {
+        return 1;
+    }
+
+    length = argc - i;
+    for (j = 0; j < length; j++) {
+        JSString *str = JS_NewStringCopyZ(cx, argv[i++]);
+        if (!str)
+            return 1;
+        if (!JS_DefineElement(cx, argsObj, j, STRING_TO_JSVAL(str),
+                              NULL, NULL, JSPROP_ENUMERATE)) {
+            return 1;
+        }
+    }
+
+    for (i = 0; i < argc; i++) {
+        if (argv[i][0] != '-' || argv[i][1] == '\0') {
+            filename = argv[i++];
+            isInteractive = JS_FALSE;
+            break;
+        }
+
+        switch (argv[i][1]) {
+        case 'v':
+            if (++i == argc)
+                return usage();
+
+            JS_SetVersion(cx, (JSVersion) atoi(argv[i]));
+            break;
+
+#ifdef JS_GC_ZEAL
+        case 'Z':
+            if (++i == argc)
+                return usage();
+            JS_SetGCZeal(cx, atoi(argv[i]));
+            break;
+#endif
+
+        case 'w':
+            reportWarnings = JS_TRUE;
+            break;
+
+        case 'W':
+            reportWarnings = JS_FALSE;
+            break;
+
+        case 's':
+            JS_ToggleOptions(cx, JSOPTION_STRICT);
+            break;
+
+        case 'E':
+            JS_ToggleOptions(cx, JSOPTION_RELIMIT);
+            break;
+
+        case 'x':
+            JS_ToggleOptions(cx, JSOPTION_XML);
+            break;
+
+        case 'j':
+            JS_ToggleOptions(cx, JSOPTION_JIT);
+#if defined(JS_TRACER) && defined(DEBUG)
+extern struct JSClass jitstats_class;
+extern void js_InitJITStatsClass(JSContext *cx, JSObject *glob);
+            js_InitJITStatsClass(cx, JS_GetGlobalObject(cx));
+            JS_DefineObject(cx, JS_GetGlobalObject(cx), "tracemonkey",
+                            &jitstats_class, NULL, 0);
+#endif
+            break;
+
+        case 'o':
+          {
+            if (++i == argc)
+                return usage();
+
+            uint32 flag = MapContextOptionNameToFlag(cx, argv[i]);
+            if (flag == 0)
+                return gExitCode;
+            JS_ToggleOptions(cx, flag);
+            break;
+          }
+        case 'P':
+            if (JS_GET_CLASS(cx, JS_GetPrototype(cx, obj)) != &global_class) {
+                JSObject *gobj;
+
+                if (!JS_SealObject(cx, obj, JS_TRUE))
+                    return JS_FALSE;
+                gobj = JS_NewObject(cx, &global_class, NULL, NULL);
+                if (!gobj)
+                    return JS_FALSE;
+                if (!JS_SetPrototype(cx, gobj, obj))
+                    return JS_FALSE;
+                JS_SetParent(cx, gobj, NULL);
+                JS_SetGlobalObject(cx, gobj);
+                obj = gobj;
+            }
+            break;
+
+        case 'b':
+            if (++i == argc)
+                return usage();
+
+            gBranchLimit = atoi(argv[i]);
+            gEnableBranchCallback = (gBranchLimit != 0);
+            break;
+
+        case 'c':
+            /* set stack chunk size */
+            gStackChunkSize = atoi(argv[++i]);
+            break;
+
+        case 'f':
+            if (++i == argc)
+                return usage();
+
+            Process(cx, obj, argv[i], JS_FALSE);
+
+            /*
+             * XXX: js -f foo.js should interpret foo.js and then
+             * drop into interactive mode, but that breaks the test
+             * harness. Just execute foo.js for now.
+             */
+            isInteractive = JS_FALSE;
+            break;
+
+        case 'e':
+        {
+            jsval rval;
+
+            if (++i == argc)
+                return usage();
+
+            /* Pass a filename of -e to imitate PERL */
+            JS_EvaluateScript(cx, obj, argv[i], strlen(argv[i]),
+                              "-e", 1, &rval);
+
+            isInteractive = JS_FALSE;
+            break;
+
+        }
+        case 'C':
+            compileOnly = JS_TRUE;
+            isInteractive = JS_FALSE;
+            break;
+
+        case 'i':
+            isInteractive = forceTTY = JS_TRUE;
+            break;
+
+        case 'S':
+            if (++i == argc)
+                return usage();
+
+            /* Set maximum stack size. */
+            gMaxStackSize = atoi(argv[i]);
+            break;
+
+        case 'z':
+            obj = split_setup(cx);
+            if (!obj)
+                return gExitCode;
+            break;
+#ifdef MOZ_SHARK
+        case 'k':
+            JS_ConnectShark();
+            break;
+#endif
+        default:
+            return usage();
+        }
+    }
+
+    if (filename || isInteractive)
+        Process(cx, obj, filename, forceTTY);
+    return gExitCode;
+}
+
+static JSBool
+Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    if (argc > 0 && JSVAL_IS_INT(argv[0]))
+        *rval = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0])));
+    else
+        *rval = INT_TO_JSVAL(JS_GetVersion(cx));
+    return JS_TRUE;
+}
+
+static JSBool
+Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    uint32 optset, flag;
+    JSString *str;
+    const char *opt;
+    char *names;
+    JSBool found;
+
+    optset = 0;
+    for (uintN i = 0; i < argc; i++) {
+        str = JS_ValueToString(cx, argv[i]);
+        if (!str)
+            return JS_FALSE;
+        argv[i] = STRING_TO_JSVAL(str);
+        opt = JS_GetStringBytes(str);
+        if (!opt)
+            return JS_FALSE;
+        flag = MapContextOptionNameToFlag(cx,  opt);
+        if (!flag)
+            return JS_FALSE;
+        optset |= flag;
+    }
+    optset = JS_ToggleOptions(cx, optset);
+
+    names = NULL;
+    found = JS_FALSE;
+    for (size_t i = 0; i != JS_ARRAY_LENGTH(js_options); i++) {
+        if (js_options[i].flag & optset) {
+            found = JS_TRUE;
+            names = JS_sprintf_append(names, "%s%s",
+                                      names ? "," : "", js_options[i].name);
+            if (!names)
+                break;
+        }
+    }
+    if (!found)
+        names = strdup("");
+    if (!names) {
+        JS_ReportOutOfMemory(cx);
+        return JS_FALSE;
+    }
+    str = JS_NewString(cx, names, strlen(names));
+    if (!str) {
+        free(names);
+        return JS_FALSE;
+    }
+    *rval = STRING_TO_JSVAL(str);
+    return JS_TRUE;
+}
+
+static JSBool
+Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    uintN i;
+    JSString *str;
+    const char *filename;
+    JSScript *script;
+    JSBool ok;
+    uint32 oldopts;
+
+    for (i = 0; i < argc; i++) {
+        str = JS_ValueToString(cx, argv[i]);
+        if (!str)
+            return JS_FALSE;
+        argv[i] = STRING_TO_JSVAL(str);
+        filename = JS_GetStringBytes(str);
+        errno = 0;
+        oldopts = JS_GetOptions(cx);
+        JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+        script = JS_CompileFile(cx, obj, filename);
+        JS_SetOptions(cx, oldopts);
+        if (!script) {
+            ok = JS_FALSE;
+        } else {
+            ok = !compileOnly
+                 ? JS_ExecuteScript(cx, obj, script, NULL)
+                 : JS_TRUE;
+            JS_DestroyScript(cx, script);
+        }
+        if (!ok)
+            return JS_FALSE;
+    }
+
+    return JS_TRUE;
+}
+
+/*
+ * function readline()
+ * Provides a hook for scripts to read a line from stdin.
+ */
+static JSBool
+ReadLine(JSContext *cx, uintN argc, jsval *vp)
+{
+#define BUFSIZE 256
+    FILE *from;
+    char *buf, *tmp;
+    size_t bufsize, buflength, gotlength;
+    JSBool sawNewline;
+    JSString *str;
+
+    from = stdin;
+    buflength = 0;
+    bufsize = BUFSIZE;
+    buf = (char *) JS_malloc(cx, bufsize);
+    if (!buf)
+        return JS_FALSE;
+
+    sawNewline = JS_FALSE;
+    while ((gotlength =
+            js_fgets(buf + buflength, bufsize - buflength, from)) > 0) {
+        buflength += gotlength;
+
+        /* Are we done? */
+        if (buf[buflength - 1] == '\n') {
+            buf[buflength - 1] = '\0';
+            sawNewline = JS_TRUE;
+            break;
+        } else if (buflength < bufsize - 1) {
+            break;
+        }
+
+        /* Else, grow our buffer for another pass. */
+        bufsize *= 2;
+        if (bufsize > buflength) {
+            tmp = (char *) JS_realloc(cx, buf, bufsize);
+        } else {
+            JS_ReportOutOfMemory(cx);
+            tmp = NULL;
+        }
+
+        if (!tmp) {
+            JS_free(cx, buf);
+            return JS_FALSE;
+        }
+
+        buf = tmp;
+    }
+
+    /* Treat the empty string specially. */
+    if (buflength == 0) {
+        *vp = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx);
+        JS_free(cx, buf);
+        return JS_TRUE;
+    }
+
+    /* Shrink the buffer to the real size. */
+    tmp = (char *) JS_realloc(cx, buf, buflength);
+    if (!tmp) {
+        JS_free(cx, buf);
+        return JS_FALSE;
+    }
+
+    buf = tmp;
+
+    /*
+     * Turn buf into a JSString. Note that buflength includes the trailing null
+     * character.
+     */
+    str = JS_NewString(cx, buf, sawNewline ? buflength - 1 : buflength);
+    if (!str) {
+        JS_free(cx, buf);
+        return JS_FALSE;
+    }
+
+    *vp = STRING_TO_JSVAL(str);
+    return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static jsval JS_FASTCALL
+Print_tn(JSContext *cx, JSString *str)
+{
+    char *bytes = JS_EncodeString(cx, str);
+    if (!bytes)
+        return JSVAL_ERROR_COOKIE;
+    fprintf(gOutFile, "%s\n", bytes);
+    JS_free(cx, bytes);
+    fflush(gOutFile);
+    return JSVAL_VOID;
+}
+#endif
+
+static JSBool
+Print(JSContext *cx, uintN argc, jsval *vp)
+{
+    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);
+        JS_free(cx, bytes);
+    }
+
+    fputc('\n', gOutFile);
+    fflush(gOutFile);
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+static JSBool
+Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+static JSBool
+Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+#ifdef LIVECONNECT
+    JSJ_SimpleShutdown();
+#endif
+
+    JS_ConvertArguments(cx, argc, argv,"/ i", &gExitCode);
+
+    gQuitting = JS_TRUE;
+    return JS_FALSE;
+}
+
+static JSBool
+GC(JSContext *cx, uintN argc, jsval *vp)
+{
+    JSRuntime *rt;
+    uint32 preBytes;
+
+    rt = cx->runtime;
+    preBytes = rt->gcBytes;
+    JS_GC(cx);
+
+    fprintf(gOutFile, "before %lu, after %lu, break %08lx\n",
+            (unsigned long)preBytes, (unsigned long)rt->gcBytes,
+#ifdef XP_UNIX
+            (unsigned long)sbrk(0)
+#else
+            0
+#endif
+            );
+#ifdef JS_GCMETER
+    js_DumpGCStats(rt, stdout);
+#endif
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+static JSBool
+GCParameter(JSContext *cx, uintN argc, jsval *vp)
+{
+    JSString *str;
+    const char *paramName;
+    JSGCParamKey param;
+    uint32 value;
+
+    if (argc == 0) {
+        str = JS_ValueToString(cx, JSVAL_VOID);
+        JS_ASSERT(str);
+    } else {
+        str = JS_ValueToString(cx, vp[2]);
+        if (!str)
+            return JS_FALSE;
+        vp[2] = STRING_TO_JSVAL(str);
+    }
+    paramName = JS_GetStringBytes(str);
+    if (!paramName)
+        return JS_FALSE;
+    if (strcmp(paramName, "maxBytes") == 0) {
+        param = JSGC_MAX_BYTES;
+    } else if (strcmp(paramName, "maxMallocBytes") == 0) {
+        param = JSGC_MAX_MALLOC_BYTES;
+    } else {
+        JS_ReportError(cx,
+                       "the first argument argument must be either maxBytes "
+                       "or maxMallocBytes");
+        return JS_FALSE;
+    }
+
+    if (!JS_ValueToECMAUint32(cx, argc < 2 ? JSVAL_VOID : vp[3], &value))
+        return JS_FALSE;
+    if (value == 0) {
+        JS_ReportError(cx,
+                       "the second argument must be convertable to uint32 with "
+                       "non-zero value");
+        return JS_FALSE;
+    }
+    JS_SetGCParameter(cx->runtime, param, value);
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+#ifdef JS_GC_ZEAL
+static JSBool
+GCZeal(JSContext *cx, uintN argc, jsval *vp)
+{
+    uint32 zeal;
+
+    if (!JS_ValueToECMAUint32(cx, argc == 0 ? JSVAL_VOID : vp[2], &zeal))
+        return JS_FALSE;
+    JS_SetGCZeal(cx, (uint8)zeal);
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+#endif /* JS_GC_ZEAL */
+
+typedef struct JSCountHeapNode JSCountHeapNode;
+
+struct JSCountHeapNode {
+    void                *thing;
+    int32               kind;
+    JSCountHeapNode     *next;
+};
+
+typedef struct JSCountHeapTracer {
+    JSTracer            base;
+    JSDHashTable        visited;
+    JSBool              ok;
+    JSCountHeapNode     *traceList;
+    JSCountHeapNode     *recycleList;
+} JSCountHeapTracer;
+
+static void
+CountHeapNotify(JSTracer *trc, void *thing, uint32 kind)
+{
+    JSCountHeapTracer *countTracer;
+    JSDHashEntryStub *entry;
+    JSCountHeapNode *node;
+
+    JS_ASSERT(trc->callback == CountHeapNotify);
+    countTracer = (JSCountHeapTracer *)trc;
+    if (!countTracer->ok)
+        return;
+
+    entry = (JSDHashEntryStub *)
+            JS_DHashTableOperate(&countTracer->visited, thing, JS_DHASH_ADD);
+    if (!entry) {
+        JS_ReportOutOfMemory(trc->context);
+        countTracer->ok = JS_FALSE;
+        return;
+    }
+    if (entry->key)
+        return;
+    entry->key = thing;
+
+    node = countTracer->recycleList;
+    if (node) {
+        countTracer->recycleList = node->next;
+    } else {
+        node = (JSCountHeapNode *) JS_malloc(trc->context, sizeof *node);
+        if (!node) {
+            countTracer->ok = JS_FALSE;
+            return;
+        }
+    }
+    node->thing = thing;
+    node->kind = kind;
+    node->next = countTracer->traceList;
+    countTracer->traceList = node;
+}
+
+static JSBool
+CountHeap(JSContext *cx, uintN argc, jsval *vp)
+{
+    void* startThing;
+    int32 startTraceKind;
+    jsval v;
+    int32 traceKind, i;
+    JSString *str;
+    char *bytes;
+    JSCountHeapTracer countTracer;
+    JSCountHeapNode *node;
+    size_t counter;
+
+    static const struct {
+        const char       *name;
+        int32             kind;
+    } traceKindNames[] = {
+        { "all",        -1                  },
+        { "object",     JSTRACE_OBJECT      },
+        { "double",     JSTRACE_DOUBLE      },
+        { "string",     JSTRACE_STRING      },
+#if JS_HAS_XML_SUPPORT
+        { "xml",        JSTRACE_XML         },
+#endif
+    };
+
+    startThing = NULL;
+    startTraceKind = 0;
+    if (argc > 0) {
+        v = JS_ARGV(cx, vp)[0];
+        if (JSVAL_IS_TRACEABLE(v)) {
+            startThing = JSVAL_TO_TRACEABLE(v);
+            startTraceKind = JSVAL_TRACE_KIND(v);
+        } else if (v != JSVAL_NULL) {
+            JS_ReportError(cx,
+                           "the first argument is not null or a heap-allocated "
+                           "thing");
+            return JS_FALSE;
+        }
+    }
+
+    traceKind = -1;
+    if (argc > 1) {
+        str = JS_ValueToString(cx, JS_ARGV(cx, vp)[1]);
+        if (!str)
+            return JS_FALSE;
+        bytes = JS_GetStringBytes(str);
+        if (!bytes)
+            return JS_FALSE;
+        for (i = 0; ;) {
+            if (strcmp(bytes, traceKindNames[i].name) == 0) {
+                traceKind = traceKindNames[i].kind;
+                break;
+            }
+            if (++i == JS_ARRAY_LENGTH(traceKindNames)) {
+                JS_ReportError(cx, "trace kind name '%s' is unknown", bytes);
+                return JS_FALSE;
+            }
+        }
+    }
+
+    JS_TRACER_INIT(&countTracer.base, cx, CountHeapNotify);
+    if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
+                           NULL, sizeof(JSDHashEntryStub),
+                           JS_DHASH_DEFAULT_CAPACITY(100))) {
+        JS_ReportOutOfMemory(cx);
+        return JS_FALSE;
+    }
+    countTracer.ok = JS_TRUE;
+    countTracer.traceList = NULL;
+    countTracer.recycleList = NULL;
+
+    if (!startThing) {
+        JS_TraceRuntime(&countTracer.base);
+    } else {
+        JS_SET_TRACING_NAME(&countTracer.base, "root");
+        JS_CallTracer(&countTracer.base, startThing, startTraceKind);
+    }
+
+    counter = 0;
+    while ((node = countTracer.traceList) != NULL) {
+        if (traceKind == -1 || node->kind == traceKind)
+            counter++;
+        countTracer.traceList = node->next;
+        node->next = countTracer.recycleList;
+        countTracer.recycleList = node;
+        JS_TraceChildren(&countTracer.base, node->thing, node->kind);
+    }
+    while ((node = countTracer.recycleList) != NULL) {
+        countTracer.recycleList = node->next;
+        JS_free(cx, node);
+    }
+    JS_DHashTableFinish(&countTracer.visited);
+
+    return countTracer.ok && JS_NewNumberValue(cx, (jsdouble) counter, vp);
+}
+
+static JSScript *
+ValueToScript(JSContext *cx, jsval v)
+{
+    JSScript *script;
+    JSFunction *fun;
+
+    if (!JSVAL_IS_PRIMITIVE(v) &&
+        JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass) {
+        script = (JSScript *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+    } else {
+        fun = JS_ValueToFunction(cx, v);
+        if (!fun)
+            return NULL;
+        script = FUN_SCRIPT(fun);
+    }
+
+    if (!script) {
+        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+                             JSSMSG_SCRIPTS_ONLY);
+    }
+
+    return script;
+}
+
+static JSBool
+GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
+            int32 *ip)
+{
+    jsval v;
+    uintN intarg;
+    JSScript *script;
+
+    *scriptp = JS_GetScriptedCaller(cx, NULL)->script;
+    *ip = 0;
+    if (argc != 0) {
+        v = argv[0];
+        intarg = 0;
+        if (!JSVAL_IS_PRIMITIVE(v) &&
+            (JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass ||
+             JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass)) {
+            script = ValueToScript(cx, v);
+            if (!script)
+                return JS_FALSE;
+            *scriptp = script;
+            intarg++;
+        }
+        if (argc > intarg) {
+            if (!JS_ValueToInt32(cx, argv[intarg], ip))
+                return JS_FALSE;
+        }
+    }
+    return JS_TRUE;
+}
+
+static JSTrapStatus
+TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
+            void *closure)
+{
+    JSString *str;
+    JSStackFrame *caller;
+
+    str = (JSString *) closure;
+    caller = JS_GetScriptedCaller(cx, NULL);
+    if (!JS_EvaluateScript(cx, caller->scopeChain,
+                           JS_GetStringBytes(str), JS_GetStringLength(str),
+                           caller->script->filename, caller->script->lineno,
+                           rval)) {
+        return JSTRAP_ERROR;
+    }
+    if (!JSVAL_IS_VOID(*rval))
+        return JSTRAP_RETURN;
+    return JSTRAP_CONTINUE;
+}
+
+static JSBool
+Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSString *str;
+    JSScript *script;
+    int32 i;
+
+    if (argc == 0) {
+        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TRAP_USAGE);
+        return JS_FALSE;
+    }
+    argc--;
+    str = JS_ValueToString(cx, argv[argc]);
+    if (!str)
+        return JS_FALSE;
+    argv[argc] = STRING_TO_JSVAL(str);
+    if (!GetTrapArgs(cx, argc, argv, &script, &i))
+        return JS_FALSE;
+    return JS_SetTrap(cx, script, script->code + i, TrapHandler, str);
+}
+
+static JSBool
+Untrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSScript *script;
+    int32 i;
+
+    if (!GetTrapArgs(cx, argc, argv, &script, &i))
+        return JS_FALSE;
+    JS_ClearTrap(cx, script, script->code + i, NULL, NULL);
+    return JS_TRUE;
+}
+
+static JSBool
+LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSScript *script;
+    int32 i;
+    uintN lineno;
+    jsbytecode *pc;
+
+    if (argc == 0) {
+        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_LINE2PC_USAGE);
+        return JS_FALSE;
+    }
+    script = JS_GetScriptedCaller(cx, NULL)->script;
+    if (!GetTrapArgs(cx, argc, argv, &script, &i))
+        return JS_FALSE;
+    lineno = (i == 0) ? script->lineno : (uintN)i;
+    pc = JS_LineNumberToPC(cx, script, lineno);
+    if (!pc)
+        return JS_FALSE;
+    *rval = INT_TO_JSVAL(PTRDIFF(pc, script->code, jsbytecode));
+    return JS_TRUE;
+}
+
+static JSBool
+PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSScript *script;
+    int32 i;
+    uintN lineno;
+
+    if (!GetTrapArgs(cx, argc, argv, &script, &i))
+        return JS_FALSE;
+    lineno = JS_PCToLineNumber(cx, script, script->code + i);
+    if (!lineno)
+        return JS_FALSE;
+    *rval = INT_TO_JSVAL(lineno);
+    return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+static void
+UpdateSwitchTableBounds(JSScript *script, uintN offset,
+                        uintN *start, uintN *end)
+{
+    jsbytecode *pc;
+    JSOp op;
+    ptrdiff_t jmplen;
+    jsint low, high, n;
+
+    pc = script->code + offset;
+    op = (JSOp) *pc;
+    switch (op) {
+      case JSOP_TABLESWITCHX:
+        jmplen = JUMPX_OFFSET_LEN;
+        goto jump_table;
+      case JSOP_TABLESWITCH:
+        jmplen = JUMP_OFFSET_LEN;
+      jump_table:
+        pc += jmplen;
+        low = GET_JUMP_OFFSET(pc);
+        pc += JUMP_OFFSET_LEN;
+        high = GET_JUMP_OFFSET(pc);
+        pc += JUMP_OFFSET_LEN;
+        n = high - low + 1;
+        break;
+
+      case JSOP_LOOKUPSWITCHX:
+        jmplen = JUMPX_OFFSET_LEN;
+        goto lookup_table;
+      case JSOP_LOOKUPSWITCH:
+        jmplen = JUMP_OFFSET_LEN;
+      lookup_table:
+        pc += jmplen;
+        n = GET_INDEX(pc);
+        pc += INDEX_LEN;
+        jmplen += JUMP_OFFSET_LEN;
+        break;
+
+      default:
+        /* [condswitch] switch does not have any jump or lookup tables. */
+        JS_ASSERT(op == JSOP_CONDSWITCH);
+        return;
+    }
+
+    *start = (uintN)(pc - script->code);
+    *end = *start + (uintN)(n * jmplen);
+}
+
+static void
+SrcNotes(JSContext *cx, JSScript *script)
+{
+    uintN offset, delta, caseOff, switchTableStart, switchTableEnd;
+    jssrcnote *notes, *sn;
+    JSSrcNoteType type;
+    const char *name;
+    uint32 index;
+    JSAtom *atom;
+    JSString *str;
+
+    fprintf(gOutFile, "\nSource notes:\n");
+    offset = 0;
+    notes = SCRIPT_NOTES(script);
+    switchTableEnd = switchTableStart = 0;
+    for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+        delta = SN_DELTA(sn);
+        offset += delta;
+        type = (JSSrcNoteType) SN_TYPE(sn);
+        name = js_SrcNoteSpec[type].name;
+        if (type == SRC_LABEL) {
+            /* Check if the source note is for a switch case. */
+            if (switchTableStart <= offset && offset < switchTableEnd) {
+                name = "case";
+            } else {
+                JS_ASSERT(script->code[offset] == JSOP_NOP);
+            }
+        }
+        fprintf(gOutFile, "%3u: %5u [%4u] %-8s",
+                (uintN) PTRDIFF(sn, notes, jssrcnote), offset, delta, name);
+        switch (type) {
+          case SRC_SETLINE:
+            fprintf(gOutFile, " lineno %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+            break;
+          case SRC_FOR:
+            fprintf(gOutFile, " cond %u update %u tail %u",
+                   (uintN) js_GetSrcNoteOffset(sn, 0),
+                   (uintN) js_GetSrcNoteOffset(sn, 1),
+                   (uintN) js_GetSrcNoteOffset(sn, 2));
+            break;
+          case SRC_IF_ELSE:
+            fprintf(gOutFile, " else %u elseif %u",
+                   (uintN) js_GetSrcNoteOffset(sn, 0),
+                   (uintN) js_GetSrcNoteOffset(sn, 1));
+            break;
+          case SRC_COND:
+          case SRC_WHILE:
+          case SRC_PCBASE:
+          case SRC_PCDELTA:
+          case SRC_DECL:
+          case SRC_BRACE:
+            fprintf(gOutFile, " offset %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+            break;
+          case SRC_LABEL:
+          case SRC_LABELBRACE:
+          case SRC_BREAK2LABEL:
+          case SRC_CONT2LABEL:
+            index = js_GetSrcNoteOffset(sn, 0);
+            JS_GET_SCRIPT_ATOM(script, index, atom);
+            JS_ASSERT(ATOM_IS_STRING(atom));
+            str = ATOM_TO_STRING(atom);
+            fprintf(gOutFile, " atom %u (", index);
+            js_FileEscapedString(gOutFile, str, 0);
+            putc(')', gOutFile);
+            break;
+          case SRC_FUNCDEF: {
+            const char *bytes;
+            JSObject *obj;
+            JSFunction *fun;
+
+            index = js_GetSrcNoteOffset(sn, 0);
+            JS_GET_SCRIPT_OBJECT(script, index, obj);
+            fun = (JSFunction *) JS_GetPrivate(cx, obj);
+            str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
+            bytes = str ? JS_GetStringBytes(str) : "N/A";
+            fprintf(gOutFile, " function %u (%s)", index, bytes);
+            break;
+          }
+          case SRC_SWITCH:
+            fprintf(gOutFile, " length %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+            caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
+            if (caseOff)
+                fprintf(gOutFile, " first case offset %u", caseOff);
+            UpdateSwitchTableBounds(script, offset,
+                                    &switchTableStart, &switchTableEnd);
+            break;
+          case SRC_CATCH:
+            delta = (uintN) js_GetSrcNoteOffset(sn, 0);
+            if (delta) {
+                if (script->main[offset] == JSOP_LEAVEBLOCK)
+                    fprintf(gOutFile, " stack depth %u", delta);
+                else
+                    fprintf(gOutFile, " guard delta %u", delta);
+            }
+            break;
+          default:;
+        }
+        fputc('\n', gOutFile);
+    }
+}
+
+static JSBool
+Notes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    uintN i;
+    JSScript *script;
+
+    for (i = 0; i < argc; i++) {
+        script = ValueToScript(cx, argv[i]);
+        if (!script)
+            continue;
+
+        SrcNotes(cx, script);
+    }
+    return JS_TRUE;
+}
+
+JS_STATIC_ASSERT(JSTRY_CATCH == 0);
+JS_STATIC_ASSERT(JSTRY_FINALLY == 1);
+JS_STATIC_ASSERT(JSTRY_ITER == 2);
+
+static const char* const TryNoteNames[] = { "catch", "finally", "iter" };
+
+static JSBool
+TryNotes(JSContext *cx, JSScript *script)
+{
+    JSTryNote *tn, *tnlimit;
+
+    if (script->trynotesOffset == 0)
+        return JS_TRUE;
+
+    tn = JS_SCRIPT_TRYNOTES(script)->vector;
+    tnlimit = tn + JS_SCRIPT_TRYNOTES(script)->length;
+    fprintf(gOutFile, "\nException table:\n"
+            "kind      stack    start      end\n");
+    do {
+        JS_ASSERT(tn->kind < JS_ARRAY_LENGTH(TryNoteNames));
+        fprintf(gOutFile, " %-7s %6u %8u %8u\n",
+                TryNoteNames[tn->kind], tn->stackDepth,
+                tn->start, tn->start + tn->length);
+    } while (++tn != tnlimit);
+    return JS_TRUE;
+}
+
+static JSBool
+Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSBool lines;
+    uintN i;
+    JSScript *script;
+
+    if (argc > 0 &&
+        JSVAL_IS_STRING(argv[0]) &&
+        !strcmp(JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), "-l")) {
+        lines = JS_TRUE;
+        argv++, argc--;
+    } else {
+        lines = JS_FALSE;
+    }
+    for (i = 0; i < argc; i++) {
+        script = ValueToScript(cx, argv[i]);
+        if (!script)
+            return JS_FALSE;
+        if (VALUE_IS_FUNCTION(cx, argv[i])) {
+            JSFunction *fun = JS_ValueToFunction(cx, argv[i]);
+            if (fun && (fun->flags & JSFUN_FLAGS_MASK)) {
+                uint16 flags = fun->flags;
+                fputs("flags:", stdout);
+
+#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout);
+
+                SHOW_FLAG(LAMBDA);
+                SHOW_FLAG(SETTER);
+                SHOW_FLAG(GETTER);
+                SHOW_FLAG(BOUND_METHOD);
+                SHOW_FLAG(HEAVYWEIGHT);
+                SHOW_FLAG(THISP_STRING);
+                SHOW_FLAG(THISP_NUMBER);
+                SHOW_FLAG(THISP_BOOLEAN);
+                SHOW_FLAG(EXPR_CLOSURE);
+                SHOW_FLAG(INTERPRETED);
+
+#undef SHOW_FLAG
+                putchar('\n');
+            }
+        }
+
+        if (!js_Disassemble(cx, script, lines, stdout))
+            return JS_FALSE;
+        SrcNotes(cx, script);
+        TryNotes(cx, script);
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+DisassFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSString *str;
+    const char *filename;
+    JSScript *script;
+    JSBool ok;
+    uint32 oldopts;
+
+    if (!argc)
+        return JS_TRUE;
+
+    str = JS_ValueToString(cx, argv[0]);
+    if (!str)
+        return JS_FALSE;
+    argv[0] = STRING_TO_JSVAL(str);
+
+    filename = JS_GetStringBytes(str);
+    oldopts = JS_GetOptions(cx);
+    JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+    script = JS_CompileFile(cx, obj, filename);
+    JS_SetOptions(cx, oldopts);
+    if (!script)
+        return JS_FALSE;
+
+    obj = JS_NewScriptObject(cx, script);
+    if (!obj)
+        return JS_FALSE;
+
+    *rval = OBJECT_TO_JSVAL(obj); /* I like to root it, root it. */
+    ok = Disassemble(cx, obj, 1, rval, rval); /* gross, but works! */
+    *rval = JSVAL_VOID;
+
+    return ok;
+}
+
+static JSBool
+DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+              jsval *rval)
+{
+#define LINE_BUF_LEN 512
+    uintN i, len, line1, line2, bupline;
+    JSScript *script;
+    FILE *file;
+    char linebuf[LINE_BUF_LEN];
+    jsbytecode *pc, *end;
+    JSBool ok;
+    static char sep[] = ";-------------------------";
+
+    ok = JS_TRUE;
+    for (i = 0; ok && i < argc; i++) {
+        script = ValueToScript(cx, argv[i]);
+        if (!script)
+           return JS_FALSE;
+
+        if (!script->filename) {
+            JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+                                 JSSMSG_FILE_SCRIPTS_ONLY);
+            return JS_FALSE;
+        }
+
+        file = fopen(script->filename, "r");
+        if (!file) {
+            JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+                                 JSSMSG_CANT_OPEN, script->filename,
+                                 strerror(errno));
+            return JS_FALSE;
+        }
+
+        pc = script->code;
+        end = pc + script->length;
+
+        /* burn the leading lines */
+        line2 = JS_PCToLineNumber(cx, script, pc);
+        for (line1 = 0; line1 < line2 - 1; line1++)
+            fgets(linebuf, LINE_BUF_LEN, file);
+
+        bupline = 0;
+        while (pc < end) {
+            line2 = JS_PCToLineNumber(cx, script, pc);
+
+            if (line2 < line1) {
+                if (bupline != line2) {
+                    bupline = line2;
+                    fprintf(gOutFile, "%s %3u: BACKUP\n", sep, line2);
+                }
+            } else {
+                if (bupline && line1 == line2)
+                    fprintf(gOutFile, "%s %3u: RESTORE\n", sep, line2);
+                bupline = 0;
+                while (line1 < line2) {
+                    if (!fgets(linebuf, LINE_BUF_LEN, file)) {
+                        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+                                             JSSMSG_UNEXPECTED_EOF,
+                                             script->filename);
+                        ok = JS_FALSE;
+                        goto bail;
+                    }
+                    line1++;
+                    fprintf(gOutFile, "%s %3u: %s", sep, line1, linebuf);
+                }
+            }
+
+            len = js_Disassemble1(cx, script, pc,
+                                  PTRDIFF(pc, script->code, jsbytecode),
+                                  JS_TRUE, stdout);
+            if (!len) {
+                ok = JS_FALSE;
+                goto bail;
+            }
+            pc += len;
+        }
+
+      bail:
+        fclose(file);
+    }
+    return ok;
+#undef LINE_BUF_LEN
+}
+
+static JSBool
+Tracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSBool bval;
+    JSString *str;
+
+#if JS_THREADED_INTERP
+    JS_ReportError(cx, "tracing not supported in JS_THREADED_INTERP builds");
+    return JS_FALSE;
+#else
+    if (argc == 0) {
+        *rval = BOOLEAN_TO_JSVAL(cx->tracefp != 0);
+        return JS_TRUE;
+    }
+
+    switch (JS_TypeOfValue(cx, argv[0])) {
+      case JSTYPE_NUMBER:
+        bval = JSVAL_IS_INT(argv[0])
+               ? JSVAL_TO_INT(argv[0])
+               : (jsint) *JSVAL_TO_DOUBLE(argv[0]);
+        break;
+      case JSTYPE_BOOLEAN:
+        bval = JSVAL_TO_BOOLEAN(argv[0]);
+        break;
+      default:
+        str = JS_ValueToString(cx, argv[0]);
+        if (!str)
+            return JS_FALSE;
+        JS_ReportError(cx, "tracing: illegal argument %s",
+                       JS_GetStringBytes(str));
+        return JS_FALSE;
+    }
+    cx->tracefp = bval ? stderr : NULL;
+    return JS_TRUE;
+#endif
+}
+
+static void
+DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
+{
+    uintN i;
+    JSScope *scope;
+    JSScopeProperty *sprop;
+    jsval v;
+    JSString *str;
+
+    i = 0;
+    scope = OBJ_SCOPE(obj);
+    for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+        if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
+            continue;
+        fprintf(fp, "%3u %p ", i, (void *)sprop);
+
+        v = ID_TO_VALUE(sprop->id);
+        if (JSID_IS_INT(sprop->id)) {
+            fprintf(fp, "[%ld]", (long)JSVAL_TO_INT(v));
+        } else {
+            if (JSID_IS_ATOM(sprop->id)) {
+                str = JSVAL_TO_STRING(v);
+            } else {
+                JS_ASSERT(JSID_IS_OBJECT(sprop->id));
+                str = js_ValueToString(cx, v);
+                fputs("object ", fp);
+            }
+            if (!str)
+                fputs("<error>", fp);
+            else
+                js_FileEscapedString(fp, str, '"');
+        }
+#define DUMP_ATTR(name) if (sprop->attrs & JSPROP_##name) fputs(" " #name, fp)
+        DUMP_ATTR(ENUMERATE);
+        DUMP_ATTR(READONLY);
+        DUMP_ATTR(PERMANENT);
+        DUMP_ATTR(GETTER);
+        DUMP_ATTR(SETTER);
+#undef  DUMP_ATTR
+
+        fprintf(fp, " slot %lu flags %x shortid %d\n",
+                (unsigned long)sprop->slot, sprop->flags, sprop->shortid);
+    }
+}
+
+static JSBool
+DumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    uintN i;
+    JSString *str;
+    const char *bytes;
+    jsid id;
+    JSObject *obj2;
+    JSProperty *prop;
+    jsval value;
+
+    for (i = 0; i < argc; i++) {
+        str = JS_ValueToString(cx, argv[i]);
+        if (!str)
+            return JS_FALSE;
+        argv[i] = STRING_TO_JSVAL(str);
+        bytes = JS_GetStringBytes(str);
+        if (strcmp(bytes, "arena") == 0) {
+#ifdef JS_ARENAMETER
+            JS_DumpArenaStats(stdout);
+#endif
+        } else if (strcmp(bytes, "atom") == 0) {
+            js_DumpAtoms(cx, gOutFile);
+        } else if (strcmp(bytes, "global") == 0) {
+            DumpScope(cx, cx->globalObject, stdout);
+        } else {
+            if (!JS_ValueToId(cx, STRING_TO_JSVAL(str), &id))
+                return JS_FALSE;
+            if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
+                return JS_FALSE;
+            if (prop) {
+                OBJ_DROP_PROPERTY(cx, obj2, prop);
+                if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
+                    return JS_FALSE;
+            }
+            if (!prop || !JSVAL_IS_OBJECT(value)) {
+                fprintf(gErrFile, "js: invalid stats argument %s\n",
+                        bytes);
+                continue;
+            }
+            obj = JSVAL_TO_OBJECT(value);
+            if (obj)
+                DumpScope(cx, obj, stdout);
+        }
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+DumpHeap(JSContext *cx, uintN argc, jsval *vp)
+{
+    char *fileName;
+    jsval v;
+    void* startThing;
+    uint32 startTraceKind;
+    const char *badTraceArg;
+    void *thingToFind;
+    size_t maxDepth;
+    void *thingToIgnore;
+    FILE *dumpFile;
+    JSBool ok;
+
+    fileName = NULL;
+    if (argc > 0) {
+        v = JS_ARGV(cx, vp)[0];
+        if (v != JSVAL_NULL) {
+            JSString *str;
+
+            str = JS_ValueToString(cx, v);
+            if (!str)
+                return JS_FALSE;
+            JS_ARGV(cx, vp)[0] = STRING_TO_JSVAL(str);
+            fileName = JS_GetStringBytes(str);
+        }
+    }
+
+    startThing = NULL;
+    startTraceKind = 0;
+    if (argc > 1) {
+        v = JS_ARGV(cx, vp)[1];
+        if (JSVAL_IS_TRACEABLE(v)) {
+            startThing = JSVAL_TO_TRACEABLE(v);
+            startTraceKind = JSVAL_TRACE_KIND(v);
+        } else if (v != JSVAL_NULL) {
+            badTraceArg = "start";
+            goto not_traceable_arg;
+        }
+    }
+
+    thingToFind = NULL;
+    if (argc > 2) {
+        v = JS_ARGV(cx, vp)[2];
+        if (JSVAL_IS_TRACEABLE(v)) {
+            thingToFind = JSVAL_TO_TRACEABLE(v);
+        } else if (v != JSVAL_NULL) {
+            badTraceArg = "toFind";
+            goto not_traceable_arg;
+        }
+    }
+
+    maxDepth = (size_t)-1;
+    if (argc > 3) {
+        v = JS_ARGV(cx, vp)[3];
+        if (v != JSVAL_NULL) {
+            uint32 depth;
+
+            if (!JS_ValueToECMAUint32(cx, v, &depth))
+                return JS_FALSE;
+            maxDepth = depth;
+        }
+    }
+
+    thingToIgnore = NULL;
+    if (argc > 4) {
+        v = JS_ARGV(cx, vp)[4];
+        if (JSVAL_IS_TRACEABLE(v)) {
+            thingToIgnore = JSVAL_TO_TRACEABLE(v);
+        } else if (v != JSVAL_NULL) {
+            badTraceArg = "toIgnore";
+            goto not_traceable_arg;
+        }
+    }
+
+    if (!fileName) {
+        dumpFile = stdout;
+    } else {
+        dumpFile = fopen(fileName, "w");
+        if (!dumpFile) {
+            JS_ReportError(cx, "can't open %s: %s", fileName, strerror(errno));
+            return JS_FALSE;
+        }
+    }
+
+    ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
+                     maxDepth, thingToIgnore);
+    if (dumpFile != stdout)
+        fclose(dumpFile);
+    return ok;
+
+  not_traceable_arg:
+    JS_ReportError(cx, "argument '%s' is not null or a heap-allocated thing",
+                   badTraceArg);
+    return JS_FALSE;
+}
+
+#endif /* DEBUG */
+
+#ifdef TEST_CVTARGS
+#include <ctype.h>
+
+static const char *
+EscapeWideString(jschar *w)
+{
+    static char enuf[80];
+    static char hex[] = "0123456789abcdef";
+    jschar u;
+    unsigned char b, c;
+    int i, j;
+
+    if (!w)
+        return "";
+    for (i = j = 0; i < sizeof enuf - 1; i++, j++) {
+        u = w[j];
+        if (u == 0)
+            break;
+        b = (unsigned char)(u >> 8);
+        c = (unsigned char)(u);
+        if (b) {
+            if (i >= sizeof enuf - 6)
+                break;
+            enuf[i++] = '\\';
+            enuf[i++] = 'u';
+            enuf[i++] = hex[b >> 4];
+            enuf[i++] = hex[b & 15];
+            enuf[i++] = hex[c >> 4];
+            enuf[i] = hex[c & 15];
+        } else if (!isprint(c)) {
+            if (i >= sizeof enuf - 4)
+                break;
+            enuf[i++] = '\\';
+            enuf[i++] = 'x';
+            enuf[i++] = hex[c >> 4];
+            enuf[i] = hex[c & 15];
+        } else {
+            enuf[i] = (char)c;
+        }
+    }
+    enuf[i] = 0;
+    return enuf;
+}
+
+#include <stdarg.h>
+
+static JSBool
+ZZ_formatter(JSContext *cx, const char *format, JSBool fromJS, jsval **vpp,
+             va_list *app)
+{
+    jsval *vp;
+    va_list ap;
+    jsdouble re, im;
+
+    printf("entering ZZ_formatter");
+    vp = *vpp;
+    ap = *app;
+    if (fromJS) {
+        if (!JS_ValueToNumber(cx, vp[0], &re))
+            return JS_FALSE;
+        if (!JS_ValueToNumber(cx, vp[1], &im))
+            return JS_FALSE;
+        *va_arg(ap, jsdouble *) = re;
+        *va_arg(ap, jsdouble *) = im;
+    } else {
+        re = va_arg(ap, jsdouble);
+        im = va_arg(ap, jsdouble);
+        if (!JS_NewNumberValue(cx, re, &vp[0]))
+            return JS_FALSE;
+        if (!JS_NewNumberValue(cx, im, &vp[1]))
+            return JS_FALSE;
+    }
+    *vpp = vp + 2;
+    *app = ap;
+    printf("leaving ZZ_formatter");
+    return JS_TRUE;
+}
+
+static JSBool
+ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSBool b = JS_FALSE;
+    jschar c = 0;
+    int32 i = 0, j = 0;
+    uint32 u = 0;
+    jsdouble d = 0, I = 0, re = 0, im = 0;
+    char *s = NULL;
+    JSString *str = NULL;
+    jschar *w = NULL;
+    JSObject *obj2 = NULL;
+    JSFunction *fun = NULL;
+    jsval v = JSVAL_VOID;
+    JSBool ok;
+
+    if (!JS_AddArgumentFormatter(cx, "ZZ", ZZ_formatter))
+        return JS_FALSE;;
+    ok = JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofvZZ*",
+                             &b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj2,
+                             &fun, &v, &re, &im);
+    JS_RemoveArgumentFormatter(cx, "ZZ");
+    if (!ok)
+        return JS_FALSE;
+    fprintf(gOutFile,
+            "b %u, c %x (%c), i %ld, u %lu, j %ld\n",
+            b, c, (char)c, i, u, j);
+    fprintf(gOutFile,
+            "d %g, I %g, s %s, S %s, W %s, obj %s, fun %s\n"
+            "v %s, re %g, im %g\n",
+            d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
+            JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj2))),
+            fun ? JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)) : "",
+            JS_GetStringBytes(JS_ValueToString(cx, v)), re, im);
+    return JS_TRUE;
+}
+#endif
+
+static JSBool
+BuildDate(JSContext *cx, uintN argc, jsval *vp)
+{
+    char version[20] = "\n";
+#if JS_VERSION < 150
+    sprintf(version, " for version %d\n", JS_VERSION);
+#endif
+    fprintf(gOutFile, "built on %s at %s%s", __DATE__, __TIME__, version);
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+static JSBool
+Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    if (argc != 0 && !JS_ValueToObject(cx, argv[0], &obj))
+        return JS_FALSE;
+    JS_ClearScope(cx, obj);
+    return JS_TRUE;
+}
+
+static JSBool
+Intern(JSContext *cx, uintN argc, jsval *vp)
+{
+    JSString *str;
+
+    str = JS_ValueToString(cx, argc == 0 ? JSVAL_VOID : vp[2]);
+    if (!str)
+        return JS_FALSE;
+    if (!JS_InternUCStringN(cx, JS_GetStringChars(str),
+                                JS_GetStringLength(str))) {
+        return JS_FALSE;
+    }
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+static JSBool
+Clone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSFunction *fun;
+    JSObject *funobj, *parent, *clone;
+
+    fun = JS_ValueToFunction(cx, argv[0]);
+    if (!fun)
+        return JS_FALSE;
+    funobj = JS_GetFunctionObject(fun);
+    if (argc > 1) {
+        if (!JS_ValueToObject(cx, argv[1], &parent))
+            return JS_FALSE;
+    } else {
+        parent = JS_GetParent(cx, funobj);
+    }
+    clone = JS_CloneFunctionObject(cx, funobj, parent);
+    if (!clone)
+        return JS_FALSE;
+    *rval = OBJECT_TO_JSVAL(clone);
+    return JS_TRUE;
+}
+
+static JSBool
+Seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSObject *target;
+    JSBool deep = JS_FALSE;
+
+    if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+        return JS_FALSE;
+    if (!target)
+        return JS_TRUE;
+    return JS_SealObject(cx, target, deep);
+}
+
+static JSBool
+GetPDA(JSContext *cx, uintN argc, jsval *vp)
+{
+    JSObject *vobj, *aobj, *pdobj;
+    JSBool ok;
+    JSPropertyDescArray pda;
+    JSPropertyDesc *pd;
+    uint32 i;
+    jsval v;
+
+    if (!JS_ValueToObject(cx, argc == 0 ? JSVAL_VOID : vp[2], &vobj))
+        return JS_FALSE;
+    if (!vobj)
+        return JS_TRUE;
+
+    aobj = JS_NewArrayObject(cx, 0, NULL);
+    if (!aobj)
+        return JS_FALSE;
+    *vp = OBJECT_TO_JSVAL(aobj);
+
+    ok = JS_GetPropertyDescArray(cx, vobj, &pda);
+    if (!ok)
+        return JS_FALSE;
+    pd = pda.array;
+    for (i = 0; i < pda.length; i++) {
+        pdobj = JS_NewObject(cx, NULL, NULL, NULL);
+        if (!pdobj) {
+            ok = JS_FALSE;
+            break;
+        }
+
+        /* Protect pdobj from GC by setting it as an element of aobj now */
+        v = OBJECT_TO_JSVAL(pdobj);
+        ok = JS_SetElement(cx, aobj, i, &v);
+        if (!ok)
+            break;
+
+        ok = JS_SetProperty(cx, pdobj, "id", &pd->id) &&
+             JS_SetProperty(cx, pdobj, "value", &pd->value) &&
+             (v = INT_TO_JSVAL(pd->flags),
+              JS_SetProperty(cx, pdobj, "flags", &v)) &&
+             (v = INT_TO_JSVAL(pd->slot),
+              JS_SetProperty(cx, pdobj, "slot", &v)) &&
+             JS_SetProperty(cx, pdobj, "alias", &pd->alias);
+        if (!ok)
+            break;
+    }
+    JS_PutPropertyDescArray(cx, &pda);
+    return ok;
+}
+
+static JSBool
+GetSLX(JSContext *cx, uintN argc, jsval *vp)
+{
+    JSScript *script;
+
+    script = ValueToScript(cx, argc == 0 ? JSVAL_VOID : vp[2]);
+    if (!script)
+        return JS_FALSE;
+    *vp = INT_TO_JSVAL(js_GetScriptLineExtent(script));
+    return JS_TRUE;
+}
+
+static JSBool
+ToInt32(JSContext *cx, uintN argc, jsval *vp)
+{
+    int32 i;
+
+    if (!JS_ValueToInt32(cx, argc == 0 ? JSVAL_VOID : vp[2], &i))
+        return JS_FALSE;
+    return JS_NewNumberValue(cx, i, vp);
+}
+
+static JSBool
+StringsAreUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+               jsval *rval)
+{
+    *rval = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
+    return JS_TRUE;
+}
+
+static JSBool
+StackQuota(JSContext *cx, uintN argc, jsval *vp)
+{
+    uint32 n;
+
+    if (argc == 0)
+        return JS_NewNumberValue(cx, (double) gScriptStackQuota, vp);
+    if (!JS_ValueToECMAUint32(cx, JS_ARGV(cx, vp)[0], &n))
+        return JS_FALSE;
+    gScriptStackQuota = n;
+    JS_SetScriptStackQuota(cx, gScriptStackQuota);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+static const char* badUTF8 = "...\xC0...";
+static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
+static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
+
+static JSBool
+TestUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    int32 mode = 1;
+    jschar chars[20];
+    size_t charsLength = 5;
+    char bytes[20];
+    size_t bytesLength = 20;
+    if (argc && !JS_ValueToInt32(cx, *argv, &mode))
+        return JS_FALSE;
+
+    /* The following throw errors if compiled with UTF-8. */
+    switch (mode) {
+      /* mode 1: malformed UTF-8 string. */
+      case 1:
+        JS_NewStringCopyZ(cx, badUTF8);
+        break;
+      /* mode 2: big UTF-8 character. */
+      case 2:
+        JS_NewStringCopyZ(cx, bigUTF8);
+        break;
+      /* mode 3: bad surrogate character. */
+      case 3:
+        JS_EncodeCharacters(cx, badSurrogate, 6, bytes, &bytesLength);
+        break;
+      /* mode 4: use a too small buffer. */
+      case 4:
+        JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
+        break;
+      default:
+        JS_ReportError(cx, "invalid mode parameter");
+        return JS_FALSE;
+    }
+    return !JS_IsExceptionPending (cx);
+}
+
+static JSBool
+ThrowError(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JS_ReportError(cx, "This is an error");
+    return JS_FALSE;
+}
+
+#define LAZY_STANDARD_CLASSES
+
+/* A class for easily testing the inner/outer object callbacks. */
+typedef struct ComplexObject {
+    JSBool isInner;
+    JSBool frozen;
+    JSObject *inner;
+    JSObject *outer;
+} ComplexObject;
+
+static JSObject *
+split_create_outer(JSContext *cx);
+
+static JSObject *
+split_create_inner(JSContext *cx, JSObject *outer);
+
+static ComplexObject *
+split_get_private(JSContext *cx, JSObject *obj);
+
+static JSBool
+split_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    ComplexObject *cpx;
+    jsid asId;
+
+    cpx = split_get_private(cx, obj);
+    if (!cpx)
+        return JS_TRUE;
+    if (!cpx->isInner && cpx->inner) {
+        /* Make sure to define this property on the inner object. */
+        if (!JS_ValueToId(cx, *vp, &asId))
+            return JS_FALSE;
+        return OBJ_DEFINE_PROPERTY(cx, cpx->inner, asId, *vp, NULL, NULL,
+                                   JSPROP_ENUMERATE, NULL);
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+split_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    ComplexObject *cpx;
+
+    cpx = split_get_private(cx, obj);
+    if (!cpx)
+        return JS_TRUE;
+    if (!cpx->isInner && cpx->inner) {
+        if (JSVAL_IS_STRING(id)) {
+            JSString *str;
+
+            str = JSVAL_TO_STRING(id);
+            return JS_GetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
+                                    JS_GetStringLength(str), vp);
+        }
+        if (JSVAL_IS_INT(id))
+            return JS_GetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
+        return JS_TRUE;
+    }
+
+    return JS_TRUE;
+}
+
+static JSBool
+split_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    ComplexObject *cpx;
+
+    cpx = split_get_private(cx, obj);
+    if (!cpx)
+        return JS_TRUE;
+    if (!cpx->isInner && cpx->inner) {
+        if (JSVAL_IS_STRING(id)) {
+            JSString *str;
+
+            str = JSVAL_TO_STRING(id);
+            return JS_SetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
+                                    JS_GetStringLength(str), vp);
+        }
+        if (JSVAL_IS_INT(id))
+            return JS_SetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
+        return JS_TRUE;
+    }
+
+    return JS_TRUE;
+}
+
+static JSBool
+split_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    ComplexObject *cpx;
+    jsid asId;
+
+    cpx = split_get_private(cx, obj);
+    if (!cpx)
+        return JS_TRUE;
+    if (!cpx->isInner && cpx->inner) {
+        /* Make sure to define this property on the inner object. */
+        if (!JS_ValueToId(cx, *vp, &asId))
+            return JS_FALSE;
+        return OBJ_DELETE_PROPERTY(cx, cpx->inner, asId, vp);
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+split_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+                  jsval *statep, jsid *idp)
+{
+    ComplexObject *cpx;
+    JSObject *iterator;
+
+    switch (enum_op) {
+      case JSENUMERATE_INIT:
+        cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+
+        if (!cpx->isInner && cpx->inner)
+            obj = cpx->inner;
+
+        iterator = JS_NewPropertyIterator(cx, obj);
+        if (!iterator)
+            return JS_FALSE;
+
+        *statep = OBJECT_TO_JSVAL(iterator);
+        if (idp)
+            *idp = JSVAL_ZERO;
+        break;
+
+      case JSENUMERATE_NEXT:
+        iterator = (JSObject*)JSVAL_TO_OBJECT(*statep);
+        if (!JS_NextProperty(cx, iterator, idp))
+            return JS_FALSE;
+
+        if (!JSVAL_IS_VOID(*idp))
+            break;
+        /* Fall through. */
+
+      case JSENUMERATE_DESTROY:
+        /* Let GC at our iterator object. */
+        *statep = JSVAL_NULL;
+        break;
+    }
+
+    return JS_TRUE;
+}
+
+static JSBool
+split_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+                JSObject **objp)
+{
+    ComplexObject *cpx;
+
+    cpx = split_get_private(cx, obj);
+    if (!cpx)
+        return JS_TRUE;
+    if (!cpx->isInner && cpx->inner) {
+        jsid asId;
+        JSProperty *prop;
+
+        if (!JS_ValueToId(cx, id, &asId))
+            return JS_FALSE;
+
+        if (!OBJ_LOOKUP_PROPERTY(cx, cpx->inner, asId, objp, &prop))
+            return JS_FALSE;
+        if (prop)
+            OBJ_DROP_PROPERTY(cx, cpx->inner, prop);
+
+        return JS_TRUE;
+    }
+
+#ifdef LAZY_STANDARD_CLASSES
+    if (!(flags & JSRESOLVE_ASSIGNING)) {
+        JSBool resolved;
+
+        if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+            return JS_FALSE;
+
+        if (resolved) {
+            *objp = obj;
+            return JS_TRUE;
+        }
+    }
+#endif
+
+    /* XXX For additional realism, let's resolve some random property here. */
+    return JS_TRUE;
+}
+
+static void
+split_finalize(JSContext *cx, JSObject *obj)
+{
+    JS_free(cx, JS_GetPrivate(cx, obj));
+}
+
+static uint32
+split_mark(JSContext *cx, JSObject *obj, void *arg)
+{
+    ComplexObject *cpx;
+
+    cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+
+    if (!cpx->isInner && cpx->inner) {
+        /* Mark the inner object. */
+        JS_MarkGCThing(cx, cpx->inner, "ComplexObject.inner", arg);
+    }
+
+    return 0;
+}
+
+static JSObject *
+split_outerObject(JSContext *cx, JSObject *obj)
+{
+    ComplexObject *cpx;
+
+    cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+    return cpx->isInner ? cpx->outer : obj;
+}
+
+static JSBool
+split_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+static JSObject *
+split_innerObject(JSContext *cx, JSObject *obj)
+{
+    ComplexObject *cpx;
+
+    cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+    if (cpx->frozen) {
+        JS_ASSERT(!cpx->isInner);
+        return obj;
+    }
+    return !cpx->isInner ? cpx->inner : obj;
+}
+
+static JSExtendedClass split_global_class = {
+    {"split_global",
+    JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE |
+    JSCLASS_GLOBAL_FLAGS | JSCLASS_IS_EXTENDED,
+    split_addProperty, split_delProperty,
+    split_getProperty, split_setProperty,
+    (JSEnumerateOp)split_enumerate,
+    (JSResolveOp)split_resolve,
+    JS_ConvertStub, split_finalize,
+    NULL, NULL, NULL, NULL, NULL, NULL,
+    split_mark, NULL},
+    split_equality, split_outerObject, split_innerObject,
+    NULL, NULL, NULL, NULL, NULL
+};
+
+static JSBool
+split_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+    *bp = JS_FALSE;
+    if (JSVAL_IS_PRIMITIVE(v))
+        return JS_TRUE;
+
+    JSObject *obj2 = JSVAL_TO_OBJECT(v);
+    if (JS_GET_CLASS(cx, obj2) != &split_global_class.base)
+        return JS_TRUE;
+
+    ComplexObject *cpx = (ComplexObject *) JS_GetPrivate(cx, obj2);
+    JS_ASSERT(!cpx->isInner);
+
+    ComplexObject *ourCpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+    JS_ASSERT(!ourCpx->isInner);
+
+    *bp = (cpx == ourCpx);
+    return JS_TRUE;
+}
+
+JSObject *
+split_create_outer(JSContext *cx)
+{
+    ComplexObject *cpx;
+    JSObject *obj;
+
+    cpx = (ComplexObject *) JS_malloc(cx, sizeof *obj);
+    if (!cpx)
+        return NULL;
+    cpx->isInner = JS_FALSE;
+    cpx->frozen = JS_TRUE;
+    cpx->inner = NULL;
+    cpx->outer = NULL;
+
+    obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
+    if (!obj || !JS_SetParent(cx, obj, NULL)) {
+        JS_free(cx, cpx);
+        return NULL;
+    }
+
+    if (!JS_SetPrivate(cx, obj, cpx)) {
+        JS_free(cx, cpx);
+        return NULL;
+    }
+
+    return obj;
+}
+
+static JSObject *
+split_create_inner(JSContext *cx, JSObject *outer)
+{
+    ComplexObject *cpx, *outercpx;
+    JSObject *obj;
+
+    JS_ASSERT(JS_GET_CLASS(cx, outer) == &split_global_class.base);
+
+    cpx = (ComplexObject *) JS_malloc(cx, sizeof *cpx);
+    if (!cpx)
+        return NULL;
+    cpx->isInner = JS_TRUE;
+    cpx->frozen = JS_FALSE;
+    cpx->inner = NULL;
+    cpx->outer = outer;
+
+    obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
+    if (!obj || !JS_SetParent(cx, obj, NULL) || !JS_SetPrivate(cx, obj, cpx)) {
+        JS_free(cx, cpx);
+        return NULL;
+    }
+
+    outercpx = (ComplexObject *) JS_GetPrivate(cx, outer);
+    outercpx->inner = obj;
+    outercpx->frozen = JS_FALSE;
+
+    return obj;
+}
+
+static ComplexObject *
+split_get_private(JSContext *cx, JSObject *obj)
+{
+    do {
+        if (JS_GET_CLASS(cx, obj) == &split_global_class.base)
+            return (ComplexObject *) JS_GetPrivate(cx, obj);
+        obj = JS_GetParent(cx, obj);
+    } while (obj);
+
+    return NULL;
+}
+
+static JSBool
+sandbox_enumerate(JSContext *cx, JSObject *obj)
+{
+    jsval v;
+    JSBool b;
+
+    if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
+        return JS_FALSE;
+    return !b || JS_EnumerateStandardClasses(cx, obj);
+}
+
+static JSBool
+sandbox_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+                JSObject **objp)
+{
+    jsval v;
+    JSBool b, resolved;
+
+    if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
+        return JS_FALSE;
+    if (b && (flags & JSRESOLVE_ASSIGNING) == 0) {
+        if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+            return JS_FALSE;
+        if (resolved) {
+            *objp = obj;
+            return JS_TRUE;
+        }
+    }
+    *objp = NULL;
+    return JS_TRUE;
+}
+
+static JSClass sandbox_class = {
+    "sandbox",
+    JSCLASS_NEW_RESOLVE,
+    JS_PropertyStub,   JS_PropertyStub,
+    JS_PropertyStub,   JS_PropertyStub,
+    sandbox_enumerate, (JSResolveOp)sandbox_resolve,
+    JS_ConvertStub,    JS_FinalizeStub,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+              jsval *rval)
+{
+    JSString *str;
+    JSObject *sobj;
+    JSContext *scx;
+    const jschar *src;
+    size_t srclen;
+    JSBool lazy, ok;
+    jsval v;
+    JSStackFrame *fp;
+
+    sobj = NULL;
+    if (!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sobj))
+        return JS_FALSE;
+
+    scx = JS_NewContext(JS_GetRuntime(cx), gStackChunkSize);
+    if (!scx) {
+        JS_ReportOutOfMemory(cx);
+        return JS_FALSE;
+    }
+    JS_SetOptions(scx, JS_GetOptions(cx));
+
+#ifdef JS_THREADSAFE
+    JS_BeginRequest(scx);
+#endif
+    src = JS_GetStringChars(str);
+    srclen = JS_GetStringLength(str);
+    lazy = JS_FALSE;
+    if (srclen == 4 &&
+        src[0] == 'l' && src[1] == 'a' && src[2] == 'z' && src[3] == 'y') {
+        lazy = JS_TRUE;
+        srclen = 0;
+    }
+
+    if (!sobj) {
+        sobj = JS_NewObject(scx, &sandbox_class, NULL, NULL);
+        if (!sobj || (!lazy && !JS_InitStandardClasses(scx, sobj))) {
+            ok = JS_FALSE;
+            goto out;
+        }
+        v = BOOLEAN_TO_JSVAL(lazy);
+        ok = JS_SetProperty(cx, sobj, "lazy", &v);
+        if (!ok)
+            goto out;
+    }
+
+    if (srclen == 0) {
+        *rval = OBJECT_TO_JSVAL(sobj);
+        ok = JS_TRUE;
+    } else {
+        fp = JS_GetScriptedCaller(cx, NULL);
+        JS_SetGlobalObject(scx, sobj);
+        JS_ToggleOptions(scx, JSOPTION_DONT_REPORT_UNCAUGHT);
+        ok = JS_EvaluateUCScript(scx, sobj, src, srclen,
+                                 fp->script->filename,
+                                 JS_PCToLineNumber(cx, fp->script,
+                                                   fp->regs->pc),
+                                 rval);
+        if (!ok) {
+            if (JS_GetPendingException(scx, &v))
+                JS_SetPendingException(cx, v);
+            else
+                JS_ReportOutOfMemory(cx);
+        }
+    }
+
+out:
+#ifdef JS_THREADSAFE
+    JS_EndRequest(scx);
+#endif
+    JS_DestroyContext(scx);
+    return ok;
+}
+
+static int32 JS_FASTCALL
+ShapeOf_tn(JSObject *obj)
+{
+    if (!obj)
+        return 0;
+    if (!OBJ_IS_NATIVE(obj))
+        return -1;
+    return OBJ_SHAPE(obj);
+}
+
+static JSBool
+ShapeOf(JSContext *cx, uintN argc, jsval *vp)
+{
+    jsval v = JS_ARGV(cx, vp)[0];
+    if (!JSVAL_IS_OBJECT(v)) {
+        JS_ReportError(cx, "shapeOf: object expected");
+        return JS_FALSE;
+    }
+    return JS_NewNumberValue(cx, ShapeOf_tn(JSVAL_TO_OBJECT(v)), vp);
+}
+
+#ifdef JS_THREADSAFE
+
+static JSBool
+Sleep_fn(JSContext *cx, uintN argc, jsval *vp)
+{
+    jsdouble t_secs;
+    PRUint32 t_ticks;
+    jsrefcount rc;
+
+    if (!JS_ValueToNumber(cx, argc == 0 ? JSVAL_VOID : vp[2], &t_secs))
+        return JS_FALSE;
+
+    if (t_secs < 0 || JSDOUBLE_IS_NaN(t_secs))
+        t_secs = 0;
+
+    rc = JS_SuspendRequest(cx);
+    t_ticks = (PRUint32)(PR_TicksPerSecond() * t_secs);
+    if (PR_Sleep(t_ticks) == PR_SUCCESS)
+        *vp = JSVAL_TRUE;
+    else
+        *vp = JSVAL_FALSE;
+    JS_ResumeRequest(cx, rc);
+    return JS_TRUE;
+}
+
+typedef struct ScatterThreadData ScatterThreadData;
+typedef struct ScatterData ScatterData;
+
+typedef enum ScatterStatus {
+    SCATTER_WAIT,
+    SCATTER_GO,
+    SCATTER_CANCEL
+} ScatterStatus;
+
+struct ScatterData {
+    ScatterThreadData   *threads;
+    jsval               *results;
+    PRLock              *lock;
+    PRCondVar           *cvar;
+    ScatterStatus       status;
+};
+
+struct ScatterThreadData {
+    jsint               index;
+    ScatterData         *shared;
+    PRThread            *thr;
+    JSContext           *cx;
+    jsval               fn;
+};
+
+static void
+DoScatteredWork(JSContext *cx, ScatterThreadData *td)
+{
+    jsval *rval = &td->shared->results[td->index];
+
+    if (!JS_CallFunctionValue(cx, NULL, td->fn, 0, NULL, rval)) {
+        *rval = JSVAL_VOID;
+        JS_GetPendingException(cx, rval);
+        JS_ClearPendingException(cx);
+    }
+}
+
+static void
+RunScatterThread(void *arg)
+{
+    ScatterThreadData *td;
+    ScatterStatus st;
+    JSContext *cx;
+
+    td = (ScatterThreadData *)arg;
+    cx = td->cx;
+
+    /* Wait for go signal. */
+    PR_Lock(td->shared->lock);
+    while ((st = td->shared->status) == SCATTER_WAIT)
+        PR_WaitCondVar(td->shared->cvar, PR_INTERVAL_NO_TIMEOUT);
+    PR_Unlock(td->shared->lock);
+
+    if (st == SCATTER_CANCEL)
+        return;
+
+    /* We are go. */
+    JS_SetContextThread(cx);
+    JS_SetThreadStackLimit(cx, 0);
+    JS_BeginRequest(cx);
+    DoScatteredWork(cx, td);
+    JS_EndRequest(cx);
+    JS_ClearContextThread(cx);
+}
+
+/*
+ * scatter(fnArray) - Call each function in `fnArray` without arguments, each
+ * in a different thread. When all threads have finished, return an array: the
+ * return values. Errors are not propagated; if any of the function calls
+ * fails, the corresponding element in the results array gets the exception
+ * object, if any, else (undefined).
+ */
+static JSBool
+Scatter(JSContext *cx, uintN argc, jsval *vp)
+{
+    jsuint i;
+    jsuint n;  /* number of threads */
+    JSObject *inArr;
+    JSObject *arr;
+    ScatterData sd;
+    JSBool ok;
+    jsrefcount rc;
+
+    if (!gEnableBranchCallback) {
+        /* Enable the branch callback, for periodic scope-sharing. */
+        gEnableBranchCallback = JS_TRUE;
+        JS_SetBranchCallback(cx, my_BranchCallback);
+        JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
+    }
+
+    sd.lock = NULL;
+    sd.cvar = NULL;
+    sd.results = NULL;
+    sd.threads = NULL;
+    sd.status = SCATTER_WAIT;
+
+    if (argc == 0 || JSVAL_IS_PRIMITIVE(JS_ARGV(cx, vp)[0])) {
+        JS_ReportError(cx, "the first argument must be an object");
+        goto fail;
+    }
+
+    inArr = JSVAL_TO_OBJECT(JS_ARGV(cx, vp)[0]);
+    ok = JS_GetArrayLength(cx, inArr, &n);
+    if (!ok)
+        goto out;
+    if (n == 0)
+        goto success;
+
+    sd.lock = PR_NewLock();
+    if (!sd.lock)
+        goto fail;
+
+    sd.cvar = PR_NewCondVar(sd.lock);
+    if (!sd.cvar)
+        goto fail;
+
+    sd.results = (jsval *) malloc(n * sizeof(jsval));
+    if (!sd.results)
+        goto fail;
+    for (i = 0; i < n; i++) {
+        sd.results[i] = JSVAL_VOID;
+        ok = JS_AddRoot(cx, &sd.results[i]);
+        if (!ok) {
+            while (i-- > 0)
+                JS_RemoveRoot(cx, &sd.results[i]);
+            free(sd.results);
+            sd.results = NULL;
+            goto fail;
+        }
+    }
+
+    sd.threads = (ScatterThreadData *) malloc(n * sizeof(ScatterThreadData));
+    if (!sd.threads)
+        goto fail;
+    for (i = 0; i < n; i++) {
+        sd.threads[i].index = i;
+        sd.threads[i].shared = &sd;
+        sd.threads[i].thr = NULL;
+        sd.threads[i].cx = NULL;
+        sd.threads[i].fn = JSVAL_NULL;
+
+        ok = JS_AddRoot(cx, &sd.threads[i].fn);
+        if (ok && !JS_GetElement(cx, inArr, (jsint) i, &sd.threads[i].fn)) {
+            JS_RemoveRoot(cx, &sd.threads[i].fn);
+            ok = JS_FALSE;
+        }
+        if (!ok) {
+            while (i-- > 0)
+                JS_RemoveRoot(cx, &sd.threads[i].fn);
+            free(sd.threads);
+            sd.threads = NULL;
+            goto fail;
+        }
+    }
+
+    for (i = 1; i < n; i++) {
+        JSContext *newcx = JS_NewContext(JS_GetRuntime(cx), 8192);
+        if (!newcx)
+            goto fail;
+        JS_SetGlobalObject(newcx, JS_GetGlobalObject(cx));
+        JS_ClearContextThread(newcx);
+        sd.threads[i].cx = newcx;
+    }
+
+    for (i = 1; i < n; i++) {
+        PRThread *t = PR_CreateThread(PR_USER_THREAD,
+                                      RunScatterThread,
+                                      &sd.threads[i],
+                                      PR_PRIORITY_NORMAL,
+                                      PR_GLOBAL_THREAD,
+                                      PR_JOINABLE_THREAD,
+                                      0);
+        if (!t) {
+            /* Failed to start thread. */
+            PR_Lock(sd.lock);
+            sd.status = SCATTER_CANCEL;
+            PR_NotifyAllCondVar(sd.cvar);
+            PR_Unlock(sd.lock);
+            while (i-- > 1)
+                PR_JoinThread(sd.threads[i].thr);
+            goto fail;
+        }
+
+        sd.threads[i].thr = t;
+    }
+    PR_Lock(sd.lock);
+    sd.status = SCATTER_GO;
+    PR_NotifyAllCondVar(sd.cvar);
+    PR_Unlock(sd.lock);
+
+    DoScatteredWork(cx, &sd.threads[0]);
+
+    rc = JS_SuspendRequest(cx);
+    for (i = 1; i < n; i++) {
+        PR_JoinThread(sd.threads[i].thr);
+    }
+    JS_ResumeRequest(cx, rc);
+
+success:
+    arr = JS_NewArrayObject(cx, n, sd.results);
+    if (!arr)
+        goto fail;
+    *vp = OBJECT_TO_JSVAL(arr);
+    ok = JS_TRUE;
+
+out:
+    if (sd.threads) {
+        JSContext *acx;
+
+        for (i = 0; i < n; i++) {
+            JS_RemoveRoot(cx, &sd.threads[i].fn);
+            acx = sd.threads[i].cx;
+            if (acx) {
+                JS_SetContextThread(acx);
+                JS_DestroyContext(acx);
+            }
+        }
+        free(sd.threads);
+    }
+    if (sd.results) {
+        for (i = 0; i < n; i++)
+            JS_RemoveRoot(cx, &sd.results[i]);
+        free(sd.results);
+    }
+    if (sd.cvar)
+        PR_DestroyCondVar(sd.cvar);
+    if (sd.lock)
+        PR_DestroyLock(sd.lock);
+
+    return ok;
+
+fail:
+    ok = JS_FALSE;
+    goto out;
+}
+
+#endif
+
+JS_DEFINE_TRCINFO_1(Print, (2, (static, JSVAL_FAIL, Print_tn, CONTEXT, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(ShapeOf, (1, (static, INT32, ShapeOf_tn, OBJECT, 0, 0)))
+
+/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
+static JSFunctionSpec shell_functions[] = {
+    JS_FS("version",        Version,        0,0,0),
+    JS_FS("options",        Options,        0,0,0),
+    JS_FS("load",           Load,           1,0,0),
+    JS_FN("readline",       ReadLine,       0,0),
+    JS_TN("print",          Print,          0,0, Print_trcinfo),
+    JS_FS("help",           Help,           0,0,0),
+    JS_FS("quit",           Quit,           0,0,0),
+    JS_FN("gc",             GC,             0,0),
+    JS_FN("gcparam",        GCParameter,    2,0),
+    JS_FN("countHeap",      CountHeap,      0,0),
+#ifdef JS_GC_ZEAL
+    JS_FN("gczeal",         GCZeal,         1,0),
+#endif
+    JS_FS("trap",           Trap,           3,0,0),
+    JS_FS("untrap",         Untrap,         2,0,0),
+    JS_FS("line2pc",        LineToPC,       0,0,0),
+    JS_FS("pc2line",        PCToLine,       0,0,0),
+    JS_FN("stackQuota",     StackQuota,     0,0),
+    JS_FS("stringsAreUTF8", StringsAreUTF8, 0,0,0),
+    JS_FS("testUTF8",       TestUTF8,       1,0,0),
+    JS_FS("throwError",     ThrowError,     0,0,0),
+#ifdef DEBUG
+    JS_FS("dis",            Disassemble,    1,0,0),
+    JS_FS("disfile",        DisassFile,     1,0,0),
+    JS_FS("dissrc",         DisassWithSrc,  1,0,0),
+    JS_FN("dumpHeap",       DumpHeap,       0,0),
+    JS_FS("notes",          Notes,          1,0,0),
+    JS_FS("tracing",        Tracing,        0,0,0),
+    JS_FS("stats",          DumpStats,      1,0,0),
+#endif
+#ifdef TEST_CVTARGS
+    JS_FS("cvtargs",        ConvertArgs,    0,0,12),
+#endif
+    JS_FN("build",          BuildDate,      0,0),
+    JS_FS("clear",          Clear,          0,0,0),
+    JS_FN("intern",         Intern,         1,0),
+    JS_FS("clone",          Clone,          1,0,0),
+    JS_FS("seal",           Seal,           1,0,1),
+    JS_FN("getpda",         GetPDA,         1,0),
+    JS_FN("getslx",         GetSLX,         1,0),
+    JS_FN("toint32",        ToInt32,        1,0),
+    JS_FS("evalcx",         EvalInContext,  1,0,0),
+    JS_TN("shapeOf",        ShapeOf,        1,0, ShapeOf_trcinfo),
+#ifdef MOZ_SHARK
+    JS_FS("startShark",      js_StartShark,      0,0,0),
+    JS_FS("stopShark",       js_StopShark,       0,0,0),
+    JS_FS("connectShark",    js_ConnectShark,    0,0,0),
+    JS_FS("disconnectShark", js_DisconnectShark, 0,0,0),
+#endif
+#ifdef MOZ_CALLGRIND
+    JS_FS("startCallgrind",  js_StartCallgrind,  0,0,0),
+    JS_FS("stopCallgrind",   js_StopCallgrind,   0,0,0),
+    JS_FS("dumpCallgrind",   js_DumpCallgrind,   1,0,0),
+#endif
+#ifdef MOZ_VTUNE
+    JS_FS("startVtune",      js_StartVtune,    1,0,0),
+    JS_FS("stopVtune",       js_StopVtune,     0,0,0),
+    JS_FS("pauseVtune",      js_PauseVtune,    0,0,0),
+    JS_FS("resumeVtune",     js_ResumeVtune,   0,0,0),
+#endif
+#ifdef DEBUG_ARRAYS
+    JS_FS("arrayInfo",       js_ArrayInfo,       1,0,0),
+#endif
+#ifdef JS_THREADSAFE
+    JS_FN("sleep",          Sleep_fn,       1,0),
+    JS_FN("scatter",        Scatter,        1,0),
+#endif
+    JS_FS_END
+};
+
+static const char shell_help_header[] =
+"Command                  Description\n"
+"=======                  ===========\n";
+
+static const char *const shell_help_messages[] = {
+"version([number])        Get or set JavaScript version number",
+"options([option ...])    Get or toggle JavaScript options",
+"load(['foo.js' ...])     Load files named by string arguments",
+"readline()               Read a single line from stdin",
+"print([exp ...])         Evaluate and print expressions",
+"help([name ...])         Display usage and help messages",
+"quit()                   Quit the shell",
+"gc()                     Run the garbage collector",
+"gcparam(name, value)\n"
+"  Wrapper for JS_SetGCParameter. The name must be either 'maxBytes' or\n"
+"  'maxMallocBytes' and the value must be convertable to a positive uint32",
+"countHeap([start[, kind]])\n"
+"  Count the number of live GC things in the heap or things reachable from\n"
+"  start when it is given and is not null. kind is either 'all' (default) to\n"
+"  count all things or one of 'object', 'double', 'string', 'function',\n"
+"  'qname', 'namespace', 'xml' to count only things of that kind",
+#ifdef JS_GC_ZEAL
+"gczeal(level)            How zealous the garbage collector should be",
+#endif
+"trap([fun, [pc,]] exp)   Trap bytecode execution",
+"untrap(fun[, pc])        Remove a trap",
+"line2pc([fun,] line)     Map line number to PC",
+"pc2line(fun[, pc])       Map PC to line number",
+"stackQuota([number])     Query/set script stack quota",
+"stringsAreUTF8()         Check if strings are UTF-8 encoded",
+"testUTF8(mode)           Perform UTF-8 tests (modes are 1 to 4)",
+"throwError()             Throw an error from JS_ReportError",
+#ifdef DEBUG
+"dis([fun])               Disassemble functions into bytecodes",
+"disfile('foo.js')        Disassemble script file into bytecodes",
+"dissrc([fun])            Disassemble functions with source lines",
+"dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])\n"
+"  Interface to JS_DumpHeap with output sent to file",
+"notes([fun])             Show source notes for functions",
+"tracing([toggle])        Turn tracing on or off",
+"stats([string ...])      Dump 'arena', 'atom', 'global' stats",
+#endif
+#ifdef TEST_CVTARGS
+"cvtargs(arg1..., arg12)  Test argument formatter",
+#endif
+"build()                  Show build date and time",
+"clear([obj])             Clear properties of object",
+"intern(str)              Internalize str in the atom table",
+"clone(fun[, scope])      Clone function object",
+"seal(obj[, deep])        Seal object, or object graph if deep",
+"getpda(obj)              Get the property descriptors for obj",
+"getslx(obj)              Get script line extent",
+"toint32(n)               Testing hook for JS_ValueToInt32",
+"evalcx(s[, o])\n"
+"  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",
+"shapeOf(obj)             Get the shape of obj (an implementation detail)",
+#ifdef MOZ_SHARK
+"startShark()             Start a Shark session.\n"
+"                         Shark must be running with programatic sampling.",
+"stopShark()              Stop a running Shark session.",
+"connectShark()           Connect to Shark.\n"
+"                         The -k switch does this automatically.",
+"disconnectShark()        Disconnect from Shark.",
+#endif
+#ifdef MOZ_CALLGRIND
+"startCallgrind()         Start callgrind instrumentation.\n",
+"stopCallgrind()          Stop callgrind instumentation.",
+"dumpCallgrind([name])    Dump callgrind counters.\n",
+#endif
+#ifdef MOZ_VTUNE
+"startVtune([filename])   Start vtune instrumentation.\n",
+"stopVtune()              Stop vtune instumentation.",
+"pauseVtune()             Pause vtune collection.\n",
+"resumeVtune()            Resume vtune collection.\n",
+#endif
+#ifdef DEBUG_ARRAYS
+"arrayInfo(a1, a2, ...)   Report statistics about arrays.",
+#endif
+#ifdef JS_THREADSAFE
+"sleep(dt)                Sleep for dt seconds",
+"scatter(fns)             Call functions concurrently (ignoring errors)",
+#endif
+};
+
+/* Help messages must match shell functions. */
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
+                 JS_ARRAY_LENGTH(shell_functions));
+
+#ifdef DEBUG
+static void
+CheckHelpMessages()
+{
+    const char *const *m;
+    const char *lp;
+
+    /* Each message must begin with "function_name(" prefix. */
+    for (m = shell_help_messages; m != JS_ARRAY_END(shell_help_messages); ++m) {
+        lp = strchr(*m, '(');
+        JS_ASSERT(lp);
+        JS_ASSERT(memcmp(shell_functions[m - shell_help_messages].name,
+                         *m, lp - *m) == 0);
+    }
+}
+#else
+# define CheckHelpMessages() ((void) 0)
+#endif
+
+static JSBool
+Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    uintN i, j;
+    int did_header, did_something;
+    JSType type;
+    JSFunction *fun;
+    JSString *str;
+    const char *bytes;
+
+    fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
+    if (argc == 0) {
+        fputs(shell_help_header, gOutFile);
+        for (i = 0; shell_functions[i].name; i++)
+            fprintf(gOutFile, "%s\n", shell_help_messages[i]);
+    } else {
+        did_header = 0;
+        for (i = 0; i < argc; i++) {
+            did_something = 0;
+            type = JS_TypeOfValue(cx, argv[i]);
+            if (type == JSTYPE_FUNCTION) {
+                fun = JS_ValueToFunction(cx, argv[i]);
+                str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
+            } else if (type == JSTYPE_STRING) {
+                str = JSVAL_TO_STRING(argv[i]);
+            } else {
+                str = NULL;
+            }
+            if (str) {
+                bytes = JS_GetStringBytes(str);
+                for (j = 0; shell_functions[j].name; j++) {
+                    if (!strcmp(bytes, shell_functions[j].name)) {
+                        if (!did_header) {
+                            did_header = 1;
+                            fputs(shell_help_header, gOutFile);
+                        }
+                        did_something = 1;
+                        fprintf(gOutFile, "%s\n", shell_help_messages[j]);
+                        break;
+                    }
+                }
+            }
+            if (!did_something) {
+                str = JS_ValueToString(cx, argv[i]);
+                if (!str)
+                    return JS_FALSE;
+                fprintf(gErrFile, "Sorry, no help for %s\n",
+                        JS_GetStringBytes(str));
+            }
+        }
+    }
+    return JS_TRUE;
+}
+
+static JSObject *
+split_setup(JSContext *cx)
+{
+    JSObject *outer, *inner, *arguments;
+
+    outer = split_create_outer(cx);
+    if (!outer)
+        return NULL;
+    JS_SetGlobalObject(cx, outer);
+
+    inner = split_create_inner(cx, outer);
+    if (!inner)
+        return NULL;
+
+    if (!JS_DefineFunctions(cx, inner, shell_functions))
+        return NULL;
+    JS_ClearScope(cx, outer);
+
+    /* Create a dummy arguments object. */
+    arguments = JS_NewArrayObject(cx, 0, NULL);
+    if (!arguments ||
+        !JS_DefineProperty(cx, inner, "arguments", OBJECT_TO_JSVAL(arguments),
+                           NULL, NULL, 0)) {
+        return NULL;
+    }
+
+#ifndef LAZY_STANDARD_CLASSES
+    if (!JS_InitStandardClasses(cx, inner))
+        return NULL;
+#endif
+
+    return inner;
+}
+
+/*
+ * Define a JS object called "it".  Give it class operations that printf why
+ * they're being called for tutorial purposes.
+ */
+enum its_tinyid {
+    ITS_COLOR, ITS_HEIGHT, ITS_WIDTH, ITS_FUNNY, ITS_ARRAY, ITS_RDONLY
+};
+
+static JSPropertySpec its_props[] = {
+    {"color",           ITS_COLOR,      JSPROP_ENUMERATE,       NULL, NULL},
+    {"height",          ITS_HEIGHT,     JSPROP_ENUMERATE,       NULL, NULL},
+    {"width",           ITS_WIDTH,      JSPROP_ENUMERATE,       NULL, NULL},
+    {"funny",           ITS_FUNNY,      JSPROP_ENUMERATE,       NULL, NULL},
+    {"array",           ITS_ARRAY,      JSPROP_ENUMERATE,       NULL, NULL},
+    {"rdonly",          ITS_RDONLY,     JSPROP_READONLY,        NULL, NULL},
+    {NULL,0,0,NULL,NULL}
+};
+
+static JSBool
+its_item(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    *rval = OBJECT_TO_JSVAL(obj);
+    if (argc != 0)
+        JS_SetCallReturnValue2(cx, argv[0]);
+    return JS_TRUE;
+}
+
+static JSBool
+its_bindMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+               jsval *rval)
+{
+    char *name;
+    JSObject *method;
+
+    if (!JS_ConvertArguments(cx, argc, argv, "so", &name, &method))
+        return JS_FALSE;
+
+    *rval = OBJECT_TO_JSVAL(method);
+
+    if (JS_TypeOfValue(cx, *rval) != JSTYPE_FUNCTION) {
+        JSString *valstr = JS_ValueToString(cx, *rval);
+        if (valstr) {
+            JS_ReportError(cx, "can't bind method %s to non-callable object %s",
+                           name, JS_GetStringBytes(valstr));
+        }
+        return JS_FALSE;
+    }
+
+    if (!JS_DefineProperty(cx, obj, name, *rval, NULL, NULL, JSPROP_ENUMERATE))
+        return JS_FALSE;
+
+    return JS_SetParent(cx, method, obj);
+}
+
+static JSFunctionSpec its_methods[] = {
+    {"item",            its_item,       0,0,0},
+    {"bindMethod",      its_bindMethod, 2,0,0},
+    {NULL,NULL,0,0,0}
+};
+
+#ifdef JSD_LOWLEVEL_SOURCE
+/*
+ * This facilitates sending source to JSD (the debugger system) in the shell
+ * where the source is loaded using the JSFILE hack in jsscan. The function
+ * below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
+ * A more normal embedding (e.g. mozilla) loads source itself and can send
+ * source directly to JSD without using this hook scheme.
+ */
+static void
+SendSourceToJSDebugger(const char *filename, uintN lineno,
+                       jschar *str, size_t length,
+                       void **listenerTSData, JSDContext* jsdc)
+{
+    JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
+
+    if (!jsdsrc) {
+        if (!filename)
+            filename = "typein";
+        if (1 == lineno) {
+            jsdsrc = JSD_NewSourceText(jsdc, filename);
+        } else {
+            jsdsrc = JSD_FindSourceForURL(jsdc, filename);
+            if (jsdsrc && JSD_SOURCE_PARTIAL !=
+                JSD_GetSourceStatus(jsdc, jsdsrc)) {
+                jsdsrc = NULL;
+            }
+        }
+    }
+    if (jsdsrc) {
+        jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
+                                        JSD_SOURCE_PARTIAL);
+    }
+    *listenerTSData = jsdsrc;
+}
+#endif /* JSD_LOWLEVEL_SOURCE */
+
+static JSBool its_noisy;    /* whether to be noisy when finalizing it */
+static JSBool its_enum_fail;/* whether to fail when enumerating it */
+
+static JSBool
+its_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    if (its_noisy) {
+        fprintf(gOutFile, "adding its property %s,",
+               JS_GetStringBytes(JS_ValueToString(cx, id)));
+        fprintf(gOutFile, " initial value %s\n",
+               JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+its_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    if (its_noisy) {
+        fprintf(gOutFile, "deleting its property %s,",
+               JS_GetStringBytes(JS_ValueToString(cx, id)));
+        fprintf(gOutFile, " current value %s\n",
+               JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+its_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    if (its_noisy) {
+        fprintf(gOutFile, "getting its property %s,",
+               JS_GetStringBytes(JS_ValueToString(cx, id)));
+        fprintf(gOutFile, " current value %s\n",
+               JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+its_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    char *str;
+    if (its_noisy) {
+        fprintf(gOutFile, "setting its property %s,",
+               JS_GetStringBytes(JS_ValueToString(cx, id)));
+        fprintf(gOutFile, " new value %s\n",
+               JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+    }
+
+    if (!JSVAL_IS_STRING(id))
+        return JS_TRUE;
+
+    str = JS_GetStringBytes(JSVAL_TO_STRING(id));
+    if (!strcmp(str, "noisy"))
+        return JS_ValueToBoolean(cx, *vp, &its_noisy);
+    else if (!strcmp(str, "enum_fail"))
+        return JS_ValueToBoolean(cx, *vp, &its_enum_fail);
+
+    return JS_TRUE;
+}
+
+/*
+ * Its enumerator, implemented using the "new" enumerate API,
+ * see class flags.
+ */
+static JSBool
+its_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+              jsval *statep, jsid *idp)
+{
+    JSObject *iterator;
+
+    switch (enum_op) {
+      case JSENUMERATE_INIT:
+        if (its_noisy)
+            fprintf(gOutFile, "enumerate its properties\n");
+
+        iterator = JS_NewPropertyIterator(cx, obj);
+        if (!iterator)
+            return JS_FALSE;
+
+        *statep = OBJECT_TO_JSVAL(iterator);
+        if (idp)
+            *idp = JSVAL_ZERO;
+        break;
+
+      case JSENUMERATE_NEXT:
+        if (its_enum_fail) {
+            JS_ReportError(cx, "its enumeration failed");
+            return JS_FALSE;
+        }
+
+        iterator = (JSObject *) JSVAL_TO_OBJECT(*statep);
+        if (!JS_NextProperty(cx, iterator, idp))
+            return JS_FALSE;
+
+        if (!JSVAL_IS_VOID(*idp))
+            break;
+        /* Fall through. */
+
+      case JSENUMERATE_DESTROY:
+        /* Allow our iterator object to be GC'd. */
+        *statep = JSVAL_NULL;
+        break;
+    }
+
+    return JS_TRUE;
+}
+
+static JSBool
+its_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+            JSObject **objp)
+{
+    if (its_noisy) {
+        fprintf(gOutFile, "resolving its property %s, flags {%s,%s,%s}\n",
+               JS_GetStringBytes(JS_ValueToString(cx, id)),
+               (flags & JSRESOLVE_QUALIFIED) ? "qualified" : "",
+               (flags & JSRESOLVE_ASSIGNING) ? "assigning" : "",
+               (flags & JSRESOLVE_DETECTING) ? "detecting" : "");
+    }
+    return JS_TRUE;
+}
+
+static JSBool
+its_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+    if (its_noisy)
+        fprintf(gOutFile, "converting it to %s type\n", JS_GetTypeName(cx, type));
+    return JS_TRUE;
+}
+
+static void
+its_finalize(JSContext *cx, JSObject *obj)
+{
+    if (its_noisy)
+        fprintf(gOutFile, "finalizing it\n");
+}
+
+static JSClass its_class = {
+    "It", JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
+    its_addProperty,  its_delProperty,  its_getProperty,  its_setProperty,
+    (JSEnumerateOp)its_enumerate, (JSResolveOp)its_resolve,
+    its_convert,      its_finalize,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+JSErrorFormatString jsShell_ErrorFormatString[JSErr_Limit] = {
+#define MSG_DEF(name, number, count, exception, format) \
+    { format, count, JSEXN_ERR } ,
+#include "jsshell.msg"
+#undef MSG_DEF
+};
+
+static const JSErrorFormatString *
+my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
+{
+    if ((errorNumber > 0) && (errorNumber < JSShellErr_Limit))
+        return &jsShell_ErrorFormatString[errorNumber];
+    return NULL;
+}
+
+static void
+my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
+{
+    int i, j, k, n;
+    char *prefix, *tmp;
+    const char *ctmp;
+
+    if (!report) {
+        fprintf(gErrFile, "%s\n", message);
+        return;
+    }
+
+    /* Conditionally ignore reported warnings. */
+    if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
+        return;
+
+    prefix = NULL;
+    if (report->filename)
+        prefix = JS_smprintf("%s:", report->filename);
+    if (report->lineno) {
+        tmp = prefix;
+        prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
+        JS_free(cx, tmp);
+    }
+    if (JSREPORT_IS_WARNING(report->flags)) {
+        tmp = prefix;
+        prefix = JS_smprintf("%s%swarning: ",
+                             tmp ? tmp : "",
+                             JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
+        JS_free(cx, tmp);
+    }
+
+    /* embedded newlines -- argh! */
+    while ((ctmp = strchr(message, '\n')) != 0) {
+        ctmp++;
+        if (prefix)
+            fputs(prefix, gErrFile);
+        fwrite(message, 1, ctmp - message, gErrFile);
+        message = ctmp;
+    }
+
+    /* If there were no filename or lineno, the prefix might be empty */
+    if (prefix)
+        fputs(prefix, gErrFile);
+    fputs(message, gErrFile);
+
+    if (!report->linebuf) {
+        fputc('\n', gErrFile);
+        goto out;
+    }
+
+    /* report->linebuf usually ends with a newline. */
+    n = strlen(report->linebuf);
+    fprintf(gErrFile, ":\n%s%s%s%s",
+            prefix,
+            report->linebuf,
+            (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n",
+            prefix);
+    n = PTRDIFF(report->tokenptr, report->linebuf, char);
+    for (i = j = 0; i < n; i++) {
+        if (report->linebuf[i] == '\t') {
+            for (k = (j + 8) & ~7; j < k; j++) {
+                fputc('.', gErrFile);
+            }
+            continue;
+        }
+        fputc('.', gErrFile);
+        j++;
+    }
+    fputs("^\n", gErrFile);
+ out:
+    if (!JSREPORT_IS_WARNING(report->flags)) {
+        if (report->errorNumber == JSMSG_OUT_OF_MEMORY) {
+            gExitCode = EXITCODE_OUT_OF_MEMORY;
+        } else {
+            gExitCode = EXITCODE_RUNTIME_ERROR;
+        }
+    }
+    JS_free(cx, prefix);
+}
+
+#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
+static JSBool
+Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSFunction *fun;
+    const char *name, **nargv;
+    uintN i, nargc;
+    JSString *str;
+    pid_t pid;
+    int status;
+
+    fun = JS_ValueToFunction(cx, argv[-2]);
+    if (!fun)
+        return JS_FALSE;
+    if (!fun->atom)
+        return JS_TRUE;
+    name = JS_GetStringBytes(ATOM_TO_STRING(fun->atom));
+    nargc = 1 + argc;
+    nargv = JS_malloc(cx, (nargc + 1) * sizeof(char *));
+    if (!nargv)
+        return JS_FALSE;
+    nargv[0] = name;
+    for (i = 1; i < nargc; i++) {
+        str = JS_ValueToString(cx, argv[i-1]);
+        if (!str) {
+            JS_free(cx, nargv);
+            return JS_FALSE;
+        }
+        nargv[i] = JS_GetStringBytes(str);
+    }
+    nargv[nargc] = 0;
+    pid = fork();
+    switch (pid) {
+      case -1:
+        perror("js");
+        break;
+      case 0:
+        (void) execvp(name, (char **)nargv);
+        perror("js");
+        exit(127);
+      default:
+        while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
+            continue;
+        break;
+    }
+    JS_free(cx, nargv);
+    return JS_TRUE;
+}
+#endif
+
+static JSBool
+global_enumerate(JSContext *cx, JSObject *obj)
+{
+#ifdef LAZY_STANDARD_CLASSES
+    return JS_EnumerateStandardClasses(cx, obj);
+#else
+    return JS_TRUE;
+#endif
+}
+
+static JSBool
+global_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+               JSObject **objp)
+{
+#ifdef LAZY_STANDARD_CLASSES
+    if ((flags & JSRESOLVE_ASSIGNING) == 0) {
+        JSBool resolved;
+
+        if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+            return JS_FALSE;
+        if (resolved) {
+            *objp = obj;
+            return JS_TRUE;
+        }
+    }
+#endif
+
+#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
+    if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) {
+        /*
+         * Do this expensive hack only for unoptimized Unix builds, which are
+         * not used for benchmarking.
+         */
+        char *path, *comp, *full;
+        const char *name;
+        JSBool ok, found;
+        JSFunction *fun;
+
+        if (!JSVAL_IS_STRING(id))
+            return JS_TRUE;
+        path = getenv("PATH");
+        if (!path)
+            return JS_TRUE;
+        path = JS_strdup(cx, path);
+        if (!path)
+            return JS_FALSE;
+        name = JS_GetStringBytes(JSVAL_TO_STRING(id));
+        ok = JS_TRUE;
+        for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) {
+            if (*comp != '\0') {
+                full = JS_smprintf("%s/%s", comp, name);
+                if (!full) {
+                    JS_ReportOutOfMemory(cx);
+                    ok = JS_FALSE;
+                    break;
+                }
+            } else {
+                full = (char *)name;
+            }
+            found = (access(full, X_OK) == 0);
+            if (*comp != '\0')
+                free(full);
+            if (found) {
+                fun = JS_DefineFunction(cx, obj, name, Exec, 0,
+                                        JSPROP_ENUMERATE);
+                ok = (fun != NULL);
+                if (ok)
+                    *objp = obj;
+                break;
+            }
+        }
+        JS_free(cx, path);
+        return ok;
+    }
+#else
+    return JS_TRUE;
+#endif
+}
+
+JSClass global_class = {
+    "global", JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,
+    JS_PropertyStub,  JS_PropertyStub,
+    JS_PropertyStub,  JS_PropertyStub,
+    global_enumerate, (JSResolveOp) global_resolve,
+    JS_ConvertStub,   JS_FinalizeStub,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+env_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+/* XXX porting may be easy, but these don't seem to supply setenv by default */
+#if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
+    JSString *idstr, *valstr;
+    const char *name, *value;
+    int rv;
+
+    idstr = JS_ValueToString(cx, id);
+    valstr = JS_ValueToString(cx, *vp);
+    if (!idstr || !valstr)
+        return JS_FALSE;
+    name = JS_GetStringBytes(idstr);
+    value = JS_GetStringBytes(valstr);
+#if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX
+    {
+        char *waste = JS_smprintf("%s=%s", name, value);
+        if (!waste) {
+            JS_ReportOutOfMemory(cx);
+            return JS_FALSE;
+        }
+        rv = putenv(waste);
+#ifdef XP_WIN
+        /*
+         * HPUX9 at least still has the bad old non-copying putenv.
+         *
+         * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
+         * that will crash if you pass it an auto char array (so it must place
+         * its argument directly in the char *environ[] array).
+         */
+        free(waste);
+#endif
+    }
+#else
+    rv = setenv(name, value, 1);
+#endif
+    if (rv < 0) {
+        JS_ReportError(cx, "can't set envariable %s to %s", name, value);
+        return JS_FALSE;
+    }
+    *vp = STRING_TO_JSVAL(valstr);
+#endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
+    return JS_TRUE;
+}
+
+static JSBool
+env_enumerate(JSContext *cx, JSObject *obj)
+{
+    static JSBool reflected;
+    char **evp, *name, *value;
+    JSString *valstr;
+    JSBool ok;
+
+    if (reflected)
+        return JS_TRUE;
+
+    for (evp = (char **)JS_GetPrivate(cx, obj); (name = *evp) != NULL; evp++) {
+        value = strchr(name, '=');
+        if (!value)
+            continue;
+        *value++ = '\0';
+        valstr = JS_NewStringCopyZ(cx, value);
+        if (!valstr) {
+            ok = JS_FALSE;
+        } else {
+            ok = JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
+                                   NULL, NULL, JSPROP_ENUMERATE);
+        }
+        value[-1] = '=';
+        if (!ok)
+            return JS_FALSE;
+    }
+
+    reflected = JS_TRUE;
+    return JS_TRUE;
+}
+
+static JSBool
+env_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+            JSObject **objp)
+{
+    JSString *idstr, *valstr;
+    const char *name, *value;
+
+    if (flags & JSRESOLVE_ASSIGNING)
+        return JS_TRUE;
+
+    idstr = JS_ValueToString(cx, id);
+    if (!idstr)
+        return JS_FALSE;
+    name = JS_GetStringBytes(idstr);
+    value = getenv(name);
+    if (value) {
+        valstr = JS_NewStringCopyZ(cx, value);
+        if (!valstr)
+            return JS_FALSE;
+        if (!JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
+                               NULL, NULL, JSPROP_ENUMERATE)) {
+            return JS_FALSE;
+        }
+        *objp = obj;
+    }
+    return JS_TRUE;
+}
+
+static JSClass env_class = {
+    "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
+    JS_PropertyStub,  JS_PropertyStub,
+    JS_PropertyStub,  env_setProperty,
+    env_enumerate, (JSResolveOp) env_resolve,
+    JS_ConvertStub,   JS_FinalizeStub,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#ifdef NARCISSUS
+
+static JSBool
+defineProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+               jsval *rval)
+{
+    JSString *str;
+    jsval value;
+    JSBool dontDelete, readOnly, dontEnum;
+    const jschar *chars;
+    size_t length;
+    uintN attrs;
+
+    dontDelete = readOnly = dontEnum = JS_FALSE;
+    if (!JS_ConvertArguments(cx, argc, argv, "Sv/bbb",
+                             &str, &value, &dontDelete, &readOnly, &dontEnum)) {
+        return JS_FALSE;
+    }
+    chars = JS_GetStringChars(str);
+    length = JS_GetStringLength(str);
+    attrs = dontEnum ? 0 : JSPROP_ENUMERATE;
+    if (dontDelete)
+        attrs |= JSPROP_PERMANENT;
+    if (readOnly)
+        attrs |= JSPROP_READONLY;
+    return JS_DefineUCProperty(cx, obj, chars, length, value, NULL, NULL,
+                               attrs);
+}
+
+static JSBool
+Evaluate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    /* function evaluate(source, filename, lineno) { ... } */
+    JSString *source;
+    const char *filename = "";
+    jsuint lineno = 0;
+    uint32 oldopts;
+    JSBool ok;
+
+    if (argc == 0) {
+        *rval = JSVAL_VOID;
+        return JS_TRUE;
+    }
+
+    if (!JS_ConvertArguments(cx, argc, argv, "S/su",
+                             &source, &filename, &lineno)) {
+        return JS_FALSE;
+    }
+
+    oldopts = JS_GetOptions(cx);
+    JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO);
+    ok = JS_EvaluateUCScript(cx, obj, JS_GetStringChars(source),
+                             JS_GetStringLength(source), filename,
+                             lineno, rval);
+    JS_SetOptions(cx, oldopts);
+
+    return ok;
+}
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/*
+ * Returns a JS_malloc'd string (that the caller needs to JS_free)
+ * containing the directory (non-leaf) part of |from| prepended to |leaf|.
+ * If |from| is empty or a leaf, MakeAbsolutePathname returns a copy of leaf.
+ * Returns NULL to indicate an error.
+ */
+static char *
+MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf)
+{
+    size_t dirlen;
+    char *dir;
+    const char *slash = NULL, *cp;
+
+    cp = from;
+    while (*cp) {
+        if (*cp == '/'
+#ifdef XP_WIN
+            || *cp == '\\'
+#endif
+           ) {
+            slash = cp;
+        }
+
+        ++cp;
+    }
+
+    if (!slash) {
+        /* We were given a leaf or |from| was empty. */
+        return JS_strdup(cx, leaf);
+    }
+
+    /* Else, we were given a real pathname, return that + the leaf. */
+    dirlen = slash - from + 1;
+    dir = (char*) JS_malloc(cx, dirlen + strlen(leaf) + 1);
+    if (!dir)
+        return NULL;
+
+    strncpy(dir, from, dirlen);
+    strcpy(dir + dirlen, leaf); /* Note: we can't use strcat here. */
+
+    return dir;
+}
+
+static JSBool
+snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSString *str;
+    const char *filename;
+    char *pathname;
+    JSStackFrame *fp;
+    JSBool ok;
+    off_t cc, len;
+    char *buf;
+    FILE *file;
+
+    str = JS_ValueToString(cx, argv[0]);
+    if (!str)
+        return JS_FALSE;
+    filename = JS_GetStringBytes(str);
+
+    /* Get the currently executing script's name. */
+    fp = JS_GetScriptedCaller(cx, NULL);
+    JS_ASSERT(fp && fp->script->filename);
+    pathname = MakeAbsolutePathname(cx, fp->script->filename, filename);
+    if (!pathname)
+        return JS_FALSE;
+
+    ok = JS_FALSE;
+    len = 0;
+    buf = NULL;
+    file = fopen(pathname, "rb");
+    if (!file) {
+        JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
+    } else {
+        if (fseek(file, 0, SEEK_END) == EOF) {
+            JS_ReportError(cx, "can't seek end of %s", pathname);
+        } else {
+            len = ftell(file);
+            if (len == -1 || fseek(file, 0, SEEK_SET) == EOF) {
+                JS_ReportError(cx, "can't seek start of %s", pathname);
+            } else {
+                buf = (char*) JS_malloc(cx, len + 1);
+                if (buf) {
+                    cc = fread(buf, 1, len, file);
+                    if (cc != len) {
+                        JS_free(cx, buf);
+                        JS_ReportError(cx, "can't read %s: %s", pathname,
+                                       (cc < 0) ? strerror(errno)
+                                                : "short read");
+                    } else {
+                        len = (size_t)cc;
+                        ok = JS_TRUE;
+                    }
+                }
+            }
+        }
+        fclose(file);
+    }
+    JS_free(cx, pathname);
+    if (!ok) {
+        JS_free(cx, buf);
+        return ok;
+    }
+
+    buf[len] = '\0';
+    str = JS_NewString(cx, buf, len);
+    if (!str) {
+        JS_free(cx, buf);
+        return JS_FALSE;
+    }
+    *rval = STRING_TO_JSVAL(str);
+    return JS_TRUE;
+}
+
+#endif /* NARCISSUS */
+
+static JSBool
+ContextCallback(JSContext *cx, uintN contextOp)
+{
+    if (contextOp == JSCONTEXT_NEW) {
+        JS_SetErrorReporter(cx, my_ErrorReporter);
+        JS_SetVersion(cx, JSVERSION_LATEST);
+        SetContextOptions(cx);
+    }
+    return JS_TRUE;
+}
+
+int
+main(int argc, char **argv, char **envp)
+{
+    int stackDummy;
+    JSRuntime *rt;
+    JSContext *cx;
+    JSObject *glob, *it, *envobj;
+    int result;
+#ifdef LIVECONNECT
+    JavaVM *java_vm = NULL;
+#endif
+#ifdef JSDEBUGGER
+    JSDContext *jsdc;
+#ifdef JSDEBUGGER_JAVA_UI
+    JNIEnv *java_env;
+    JSDJContext *jsdjc;
+#endif
+#ifdef JSDEBUGGER_C_UI
+    JSBool jsdbc;
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+    CheckHelpMessages();
+#ifdef HAVE_SETLOCALE
+    setlocale(LC_ALL, "");
+#endif
+    gStackBase = (jsuword)&stackDummy;
+
+#ifdef XP_OS2
+   /* these streams are normally line buffered on OS/2 and need a \n, *
+    * so we need to unbuffer then to get a reasonable prompt          */
+    setbuf(stdout,0);
+    setbuf(stderr,0);
+#endif
+
+    gErrFile = stderr;
+    gOutFile = stdout;
+
+    argc--;
+    argv++;
+
+    rt = JS_NewRuntime(64L * 1024L * 1024L);
+    if (!rt)
+        return 1;
+    JS_SetContextCallback(rt, ContextCallback);
+
+    cx = JS_NewContext(rt, gStackChunkSize);
+    if (!cx)
+        return 1;
+
+#ifdef JS_THREADSAFE
+    JS_BeginRequest(cx);
+#endif
+
+    glob = JS_NewObject(cx, &global_class, NULL, NULL);
+    if (!glob)
+        return 1;
+#ifdef LAZY_STANDARD_CLASSES
+    JS_SetGlobalObject(cx, glob);
+#else
+    if (!JS_InitStandardClasses(cx, glob))
+        return 1;
+#endif
+    if (!JS_DefineFunctions(cx, glob, shell_functions))
+        return 1;
+
+    it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
+    if (!it)
+        return 1;
+    if (!JS_DefineProperties(cx, it, its_props))
+        return 1;
+    if (!JS_DefineFunctions(cx, it, its_methods))
+        return 1;
+
+#ifdef JSDEBUGGER
+    /*
+    * XXX A command line option to enable debugging (or not) would be good
+    */
+    jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL);
+    if (!jsdc)
+        return 1;
+    JSD_JSContextInUse(jsdc, cx);
+#ifdef JSD_LOWLEVEL_SOURCE
+    JS_SetSourceHandler(rt, SendSourceToJSDebugger, jsdc);
+#endif /* JSD_LOWLEVEL_SOURCE */
+#ifdef JSDEBUGGER_JAVA_UI
+    jsdjc = JSDJ_CreateContext();
+    if (! jsdjc)
+        return 1;
+    JSDJ_SetJSDContext(jsdjc, jsdc);
+    java_env = JSDJ_CreateJavaVMAndStartDebugger(jsdjc);
+#ifdef LIVECONNECT
+    if (java_env)
+        (*java_env)->GetJavaVM(java_env, &java_vm);
+#endif
+    /*
+    * XXX This would be the place to wait for the debugger to start.
+    * Waiting would be nice in general, but especially when a js file
+    * is passed on the cmd line.
+    */
+#endif /* JSDEBUGGER_JAVA_UI */
+#ifdef JSDEBUGGER_C_UI
+    jsdbc = JSDB_InitDebugger(rt, jsdc, 0);
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+#ifdef LIVECONNECT
+    if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH")))
+        return 1;
+#endif
+
+    envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
+    if (!envobj || !JS_SetPrivate(cx, envobj, envp))
+        return 1;
+
+#ifdef NARCISSUS
+    {
+        jsval v;
+        static const char Object_prototype[] = "Object.prototype";
+
+        if (!JS_DefineFunction(cx, glob, "snarf", snarf, 1, 0))
+            return 1;
+        if (!JS_DefineFunction(cx, glob, "evaluate", Evaluate, 3, 0))
+            return 1;
+
+        if (!JS_EvaluateScript(cx, glob,
+                               Object_prototype, sizeof Object_prototype - 1,
+                               NULL, 0, &v)) {
+            return 1;
+        }
+        if (!JS_DefineFunction(cx, JSVAL_TO_OBJECT(v), "__defineProperty__",
+                               defineProperty, 5, 0)) {
+            return 1;
+        }
+    }
+#endif
+
+    result = ProcessArgs(cx, glob, argv, argc);
+
+#ifdef JSDEBUGGER
+    if (jsdc) {
+#ifdef JSDEBUGGER_C_UI
+        if (jsdbc)
+            JSDB_TermDebugger(jsdc);
+#endif /* JSDEBUGGER_C_UI */
+        JSD_DebuggerOff(jsdc);
+    }
+#endif  /* JSDEBUGGER */
+
+#ifdef JS_THREADSAFE
+    JS_EndRequest(cx);
+#endif
+
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+    return result;
+}
deleted file mode 100644
--- a/js/src/shell/Makefile.in
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- Mode: makefile -*-
-#
-# ***** 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 Spidermonkey build system.
-#
-# The Initial Developer of the Original Code is
-# The Mozilla Foundation.
-# Portions created by the Initial Developer are Copyright (C) 2008
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-# Ted Mielczarek <ted.mielczarek@gmail.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of 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 *****
-
-DEPTH		= ..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-PROGRAM         = js$(BIN_SUFFIX)
-CPPSRCS		= js.cpp
-
-DEFINES         += -DEXPORT_JS_API
-
-LIBS      = $(NSPR_LIBS) $(EDITLINE_LIBS) $(DEPTH)/$(LIB_PREFIX)js_static.$(LIB_SUFFIX)
-
-LOCAL_INCLUDES += -I$(topsrcdir) -I..
-
-include $(topsrcdir)/config/rules.mk
-
-# People expect the js shell to wind up in the top-level JS dir.
-libs::
-	$(INSTALL) $(IFLAGS2) $(PROGRAM) $(DEPTH)
deleted file mode 100644
--- a/js/src/shell/js.cpp
+++ /dev/null
@@ -1,4125 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sw=4 et tw=99:
- *
- * ***** 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 Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of 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 ***** */
-
-/*
- * JS shell.
- */
-#include "jsstddef.h"
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <locale.h>
-#include "jstypes.h"
-#include "jsarena.h"
-#include "jsutil.h"
-#include "jsprf.h"
-#include "jsapi.h"
-#include "jsarray.h"
-#include "jsatom.h"
-#include "jsbuiltins.h"
-#include "jscntxt.h"
-#include "jsdbgapi.h"
-#include "jsemit.h"
-#include "jsfun.h"
-#include "jsgc.h"
-#include "jslock.h"
-#include "jsnum.h"
-#include "jsobj.h"
-#include "jsparse.h"
-#include "jsscope.h"
-#include "jsscript.h"
-
-#ifdef LIVECONNECT
-#include "jsjava.h"
-#endif
-
-#ifdef JSDEBUGGER
-#include "jsdebug.h"
-#ifdef JSDEBUGGER_JAVA_UI
-#include "jsdjava.h"
-#endif /* JSDEBUGGER_JAVA_UI */
-#ifdef JSDEBUGGER_C_UI
-#include "jsdb.h"
-#endif /* JSDEBUGGER_C_UI */
-#endif /* JSDEBUGGER */
-
-#ifdef XP_UNIX
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#endif
-
-#if defined(XP_WIN) || defined(XP_OS2)
-#include <io.h>     /* for isatty() */
-#endif
-
-typedef enum JSShellExitCode {
-    EXITCODE_RUNTIME_ERROR      = 3,
-    EXITCODE_FILE_NOT_FOUND     = 4,
-    EXITCODE_OUT_OF_MEMORY      = 5
-} JSShellExitCode;
-
-size_t gStackChunkSize = 8192;
-
-/* Assume that we can not use more than 5e5 bytes of C stack by default. */
-static size_t gMaxStackSize = 500000;
-static jsuword gStackBase;
-
-static size_t gScriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
-
-static JSBool gEnableBranchCallback = JS_FALSE;
-static uint32 gBranchCount;
-static uint32 gBranchLimit;
-
-int gExitCode = 0;
-JSBool gQuitting = JS_FALSE;
-FILE *gErrFile = NULL;
-FILE *gOutFile = NULL;
-
-static JSBool reportWarnings = JS_TRUE;
-static JSBool compileOnly = JS_FALSE;
-
-typedef enum JSShellErrNum {
-#define MSG_DEF(name, number, count, exception, format) \
-    name = number,
-#include "jsshell.msg"
-#undef MSG_DEF
-    JSShellErr_Limit
-#undef MSGDEF
-} JSShellErrNum;
-
-static const JSErrorFormatString *
-my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
-static JSObject *
-split_setup(JSContext *cx);
-
-#ifdef EDITLINE
-JS_BEGIN_EXTERN_C
-extern char     *readline(const char *prompt);
-extern void     add_history(char *line);
-JS_END_EXTERN_C
-#endif
-
-static JSBool
-GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
-#ifdef EDITLINE
-    /*
-     * Use readline only if file is stdin, because there's no way to specify
-     * another handle.  Are other filehandles interactive?
-     */
-    if (file == stdin) {
-        char *linep = readline(prompt);
-        if (!linep)
-            return JS_FALSE;
-        if (linep[0] != '\0')
-            add_history(linep);
-        strcpy(bufp, linep);
-        JS_free(cx, linep);
-        bufp += strlen(bufp);
-        *bufp++ = '\n';
-        *bufp = '\0';
-    } else
-#endif
-    {
-        char line[256];
-        fprintf(gOutFile, prompt);
-        fflush(gOutFile);
-        if (!fgets(line, sizeof line, file))
-            return JS_FALSE;
-        strcpy(bufp, line);
-    }
-    return JS_TRUE;
-}
-
-static JSBool
-my_BranchCallback(JSContext *cx, JSScript *script)
-{
-    if (++gBranchCount == gBranchLimit) {
-        if (script) {
-            if (script->filename)
-                fprintf(gErrFile, "%s:", script->filename);
-            fprintf(gErrFile, "%u: script branch callback (%u callbacks)\n",
-                    script->lineno, gBranchLimit);
-        } else {
-            fprintf(gErrFile, "native branch callback (%u callbacks)\n",
-                    gBranchLimit);
-        }
-        gBranchCount = 0;
-        return JS_FALSE;
-    }
-#ifdef JS_THREADSAFE
-    if ((gBranchCount & 0xff) == 1) {
-#endif
-        if ((gBranchCount & 0x3fff) == 1)
-            JS_MaybeGC(cx);
-#ifdef JS_THREADSAFE
-        else
-            JS_YieldRequest(cx);
-    }
-#endif
-    return JS_TRUE;