Merge last green changeset from mozilla-inbound to mozilla-central
authorMarco Bonardo <mbonardo@mozilla.com>
Wed, 27 Jul 2011 12:12:25 +0200
changeset 74182 e4c8a1e7b373742e7cafbf2d55b0e45a6ba60e26
parent 74148 42b1ad712868d18ff250815354692e549adf92d3 (current diff)
parent 74181 685b3762558c91d19580dc295e54c43a7138f911 (diff)
child 74183 35f95308fa08d107745783d58bd552c09daf8418
child 74192 6c9c2e013decc70308333fae23caed5a8ead945f
push id235
push userbzbarsky@mozilla.com
push dateTue, 27 Sep 2011 17:13:04 +0000
treeherdermozilla-beta@2d1e082d176a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone8.0a1
first release with
nightly linux32
e4c8a1e7b373 / 8.0a1 / 20110727081800 / files
nightly linux64
e4c8a1e7b373 / 8.0a1 / 20110727081800 / files
nightly mac
e4c8a1e7b373 / 8.0a1 / 20110727081800 / files
nightly win32
e4c8a1e7b373 / 8.0a1 / 20110727081800 / files
nightly win64
e4c8a1e7b373 / 8.0a1 / 20110727081800 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last green changeset from mozilla-inbound to mozilla-central
browser/base/content/browser-places.js
content/html/content/test/test_bug557628.html
dom/plugins/ipc/PluginModuleChild.cpp
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -838,16 +838,17 @@ var BookmarksEventHandler = {
 };
 
 
 // Handles special drag and drop functionality for Places menus that are not
 // part of a Places view (e.g. the bookmarks menu in the menubar).
 var PlacesMenuDNDHandler = {
   _springLoadDelay: 350, // milliseconds
   _loadTimer: null,
+  _closerTimer: null,
 
   /**
    * Called when the user enters the <menu> element during a drag.
    * @param   event
    *          The DragEnter event that spawned the opening. 
    */
   onDragEnter: function PMDH_onDragEnter(event) {
     // Opening menus in a Places popup is handled by the view itself.
@@ -878,18 +879,19 @@ var PlacesMenuDNDHandler = {
     // Closing menus in a Places popup is handled by the view itself.
     if (!this._isStaticContainer(event.target))
       return;
 
     if (this._loadTimer) {
       this._loadTimer.cancel();
       this._loadTimer = null;
     }
-    let closeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-    closeTimer.initWithCallback(function() {
+    this._closeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+    this._closeTimer.initWithCallback(function() {
+      this._closeTimer = null;
       let node = PlacesControllerDragHelper.currentDropTarget;
       let inHierarchy = false;
       while (node && !inHierarchy) {
         inHierarchy = node == event.target;
         node = node.parentNode;
       }
       if (!inHierarchy && event.target.lastChild &&
           event.target.lastChild.hasAttribute("autoopened")) {
--- a/browser/themes/pinstripe/browser/places/organizer.css
+++ b/browser/themes/pinstripe/browser/places/organizer.css
@@ -90,16 +90,25 @@
 
 #placesToolbar > toolbarbutton:not([disabled="true"]):active:hover,
 #placesToolbar > toolbarbutton[open="true"] {
   background: @toolbarbuttonPressedBackgroundColor@;
   text-shadow: @loweredShadow@;
   box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
 }
 
+#placesToolbar > toolbarbutton:-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorAqua@;
+  box-shadow: @focusRingShadow@;
+}
+
+#placesToolbar > toolbarbutton:-moz-system-metric(mac-graphite-theme):-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorGraphite@;
+}
+
 #placesToolbar > toolbarbutton:-moz-window-inactive {
   border-color: @toolbarbuttonInactiveBorderColor@;
   background-image: @toolbarbuttonInactiveBackgroundImage@;
 }
 
 #placesToolbar > toolbarbutton[disabled="true"] > .toolbarbutton-icon {
   opacity: 0.5;
 }
--- a/configure.in
+++ b/configure.in
@@ -9410,16 +9410,21 @@ fi
   sort confdefs.h | egrep -v "$_EGREP_PATTERN" >> $_CONFIG_TMP
 
   if test "$?" != 0; then
     AC_MSG_ERROR([Error outputting config definitions])
   fi
 
   cat >> $_CONFIG_TMP <<\EOF
 
+/* The c99 defining the limit macros (UINT32_MAX for example), says:
+ * C++ implementations should define these macros only when __STDC_LIMIT_MACROS
+ * is defined before <stdint.h> is included. */
+#define __STDC_LIMIT_MACROS
+
 #endif /* _MOZILLA_CONFIG_H_ */
 
 EOF
 
   # Only write mozilla-config.h when something changes (or it doesn't exist)
   if cmp -s $_CONFIG_TMP $_CONFIG_DEFS_H; then
     rm $_CONFIG_TMP
   else
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1719,16 +1719,23 @@ public:
   static PRBool IsPatternMatching(nsAString& aValue, nsAString& aPattern,
                                   nsIDocument* aDocument);
 
   /**
    * Calling this adds support for
    * ontouch* event handler DOM attributes.
    */
   static void InitializeTouchEventTable();
+
+  static nsresult Btoa(const nsAString& aBinaryData,
+                       nsAString& aAsciiBase64String);
+
+  static nsresult Atob(const nsAString& aAsciiString,
+                       nsAString& aBinaryData);
+  
 private:
   static PRBool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
   static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
--- a/content/base/public/nsIFrameMessageManager.idl
+++ b/content/base/public/nsIFrameMessageManager.idl
@@ -76,17 +76,17 @@ interface nsIFrameMessageManager : nsISu
 interface nsISyncMessageSender : nsIFrameMessageManager
 {
   /**
    * Returns an array of JSON objects.
    */
   void sendSyncMessage(/*in messageName, in JSON*/);
 };
 
-[scriptable, uuid(c56e85b8-6736-4ae2-ae90-66bcef952a82)]
+[scriptable, uuid(6f23339f-2b5c-4f22-a03f-bb7ec101f83d)]
 interface nsIContentFrameMessageManager : nsISyncMessageSender
 {
   /**
    * The current top level window in the frame or null.
    */
   readonly attribute nsIDOMWindow content;
 
   /**
@@ -99,16 +99,22 @@ interface nsIContentFrameMessageManager 
    */
   void dump(in DOMString aStr);
 
   /**
    * If leak detection is enabled, print a note to the leak log that this
    * process will intentionally crash.
    */
   void privateNoteIntentionalCrash();
+
+   /**
+    * Ascii base64 data to binary data and vice versa
+    */
+   DOMString atob(in DOMString aAsciiString);
+   DOMString btoa(in DOMString aBase64Data);
 };
 
 [uuid(9c48d557-92fe-4edb-95fc-bfe97e77bdc3)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
 };
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -629,16 +629,71 @@ nsContentUtils::InitializeTouchEventTabl
         delete sStringEventTable;
         sStringEventTable = nsnull;
         return;
       }
     }
   }
 }
 
+static PRBool
+Is8bit(const nsAString& aString)
+{
+  static const PRUnichar EIGHT_BIT = PRUnichar(~0x00FF);
+
+  nsAString::const_iterator done_reading;
+  aString.EndReading(done_reading);
+
+  // for each chunk of |aString|...
+  PRUint32 fragmentLength = 0;
+  nsAString::const_iterator iter;
+  for (aString.BeginReading(iter); iter != done_reading;
+       iter.advance(PRInt32(fragmentLength))) {
+    fragmentLength = PRUint32(iter.size_forward());
+    const PRUnichar* c = iter.get();
+    const PRUnichar* fragmentEnd = c + fragmentLength;
+
+    // for each character in this chunk...
+    while (c < fragmentEnd) {
+      if (*c++ & EIGHT_BIT) {
+        return PR_FALSE;
+      }
+    }
+  }
+
+  return PR_TRUE;
+}
+
+nsresult
+nsContentUtils::Btoa(const nsAString& aBinaryData,
+                     nsAString& aAsciiBase64String)
+{
+  if (!Is8bit(aBinaryData)) {
+    aAsciiBase64String.Truncate();
+    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
+  }
+
+  return nsXPConnect::Base64Encode(aBinaryData, aAsciiBase64String);
+}
+
+nsresult
+nsContentUtils::Atob(const nsAString& aAsciiBase64String,
+                     nsAString& aBinaryData)
+{
+  if (!Is8bit(aAsciiBase64String)) {
+    aBinaryData.Truncate();
+    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
+  }
+
+  nsresult rv = nsXPConnect::Base64Decode(aAsciiBase64String, aBinaryData);
+  if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
+    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
+  }
+  return rv;
+}
 
 /**
  * Access a cached parser service. Don't addref. We need only one
  * reference to it and this class has that one.
  */
 /* static */
 nsIParserService*
 nsContentUtils::GetParserService()
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -318,16 +318,30 @@ nsFrameMessageManager::GetContent(nsIDOM
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
 {
   *aDocShell = nsnull;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
+                            nsAString& aAsciiBase64String)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFrameMessageManager::Atob(const nsAString& aAsciiString,
+                            nsAString& aBinaryData)
+{
+  return NS_OK;
+}
+
 nsresult
 nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
                                       const nsAString& aMessage,
                                       PRBool aSync, const nsAString& aJSON,
                                       JSObject* aObjectsArray,
                                       InfallibleTArray<nsString>* aJSONRetVal,
                                       JSContext* aContext)
 {
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -184,16 +184,31 @@ nsInProcessTabChildGlobal::GetContent(ns
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
 {
   NS_IF_ADDREF(*aDocShell = mDocShell);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsInProcessTabChildGlobal::Btoa(const nsAString& aBinaryData,
+                            nsAString& aAsciiBase64String)
+{
+  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
+}
+
+NS_IMETHODIMP
+nsInProcessTabChildGlobal::Atob(const nsAString& aAsciiString,
+                            nsAString& aBinaryData)
+{
+  return nsContentUtils::Atob(aAsciiString, aBinaryData);
+}
+
+
+NS_IMETHODIMP
 nsInProcessTabChildGlobal::PrivateNoteIntentionalCrash()
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 void
 nsInProcessTabChildGlobal::Disconnect()
 {
--- a/content/base/src/nsInProcessTabChildGlobal.h
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -73,16 +73,21 @@ public:
   }
   NS_IMETHOD GetContent(nsIDOMWindow** aContent);
   NS_IMETHOD GetDocShell(nsIDocShell** aDocShell);
   NS_IMETHOD Dump(const nsAString& aStr)
   {
     return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
   }
   NS_IMETHOD PrivateNoteIntentionalCrash();
+  NS_IMETHOD Btoa(const nsAString& aBinaryData,
+                  nsAString& aAsciiBase64String);
+  NS_IMETHOD Atob(const nsAString& aAsciiString,
+                  nsAString& aBinaryData);
+
   NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               PRBool aUseCapture)
   {
     // By default add listeners only for trusted events!
--- a/content/media/VideoUtils.h
+++ b/content/media/VideoUtils.h
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef VideoUtils_h
 #define VideoUtils_h
 
 #include "mozilla/ReentrantMonitor.h"
 
 #include "nsRect.h"
+#include "nsIThreadManager.h"
 
 // This file contains stuff we'd rather put elsewhere, but which is
 // dependent on other changes which we don't want to wait for. We plan to
 // remove this file in the near future.
 
 
 // This belongs in prtypes.h
 /************************************************************************
@@ -152,9 +153,17 @@ PRBool UsecsToSamples(PRInt64 aUsecs, PR
 #define MAX_VIDEO_WIDTH  4000
 #define MAX_VIDEO_HEIGHT 3000
 
 // Scales the display rect aDisplay by aspect ratio aAspectRatio.
 // Note that aDisplay must be validated by nsVideoInfo::ValidateVideoRegion()
 // before being used!
 void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio);
 
+// The amount of virtual memory reserved for thread stacks.
+#if defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)
+#define MEDIA_THREAD_STACK_SIZE (128 * 1024)
+#else
+// All other platforms use their system defaults.
+#define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE
 #endif
+
+#endif
--- a/content/media/nsAudioStream.cpp
+++ b/content/media/nsAudioStream.cpp
@@ -355,17 +355,19 @@ void nsAudioStream::ShutdownLibrary()
   delete gVolumeScaleLock;
   gVolumeScaleLock = nsnull;
 }
 
 nsIThread *
 nsAudioStream::GetThread()
 {
   if (!mAudioPlaybackThread) {
-    NS_NewThread(getter_AddRefs(mAudioPlaybackThread));
+    NS_NewThread(getter_AddRefs(mAudioPlaybackThread),
+                 nsnull,
+                 MEDIA_THREAD_STACK_SIZE);
   }
   return mAudioPlaybackThread;
 }
 
 nsAudioStream* nsAudioStream::AllocateStream()
 {
 #if defined(REMOTE_AUDIO)
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -221,17 +221,19 @@ nsBuiltinDecoderStateMachine::nsBuiltinD
   mRunAgain(PR_FALSE),
   mDispatchedRunEvent(PR_FALSE),
   mDecodeThreadWaiting(PR_FALSE)
 {
   MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (gStateMachineCount == 0) {
     NS_ASSERTION(!gStateMachineThread, "Should have null state machine thread!");
-    nsresult res = NS_NewThread(&gStateMachineThread);
+    nsresult res = NS_NewThread(&gStateMachineThread,
+                                nsnull,
+                                MEDIA_THREAD_STACK_SIZE);
     NS_ABORT_IF_FALSE(NS_SUCCEEDED(res), "Can't create media state machine thread");
   }
   gStateMachineCount++;
 }
 
 nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
@@ -1047,17 +1049,19 @@ nsBuiltinDecoderStateMachine::StartDecod
 {
   NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mStopDecodeThread = PR_FALSE;
   if ((mDecodeThread && !mDecodeThreadIdle) || mState >= DECODER_STATE_COMPLETED)
     return NS_OK;
 
   if (!mDecodeThread) {
-    nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread));
+    nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
+                               nsnull,
+                               MEDIA_THREAD_STACK_SIZE);
     if (NS_FAILED(rv)) {
       mState = DECODER_STATE_SHUTDOWN;
       return rv;
     }
   }
   nsCOMPtr<nsIRunnable> event =
     NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
   mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
@@ -1068,17 +1072,19 @@ nsBuiltinDecoderStateMachine::StartDecod
 nsresult
 nsBuiltinDecoderStateMachine::StartAudioThread()
 {
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mStopAudioThread = PR_FALSE;
   if (HasAudio() && !mAudioThread) {
-    nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread));
+    nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread),
+                               nsnull,
+                               MEDIA_THREAD_STACK_SIZE);
     if (NS_FAILED(rv)) {
       mState = DECODER_STATE_SHUTDOWN;
       return rv;
     }
     nsCOMPtr<nsIRunnable> event =
       NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::AudioLoop);
     mAudioThread->Dispatch(event, NS_DISPATCH_NORMAL);
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7164,68 +7164,28 @@ nsGlobalWindow::Find(const nsAString& aS
     // Launch the search with the passed in search string
     rv = finder->FindNext(aDidFind);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return rv;
 }
 
-static PRBool
-Is8bit(const nsAString& aString)
-{
-  static const PRUnichar EIGHT_BIT = PRUnichar(~0x00FF);
-
-  nsAString::const_iterator done_reading;
-  aString.EndReading(done_reading);
-
-  // for each chunk of |aString|...
-  PRUint32 fragmentLength = 0;
-  nsAString::const_iterator iter;
-  for (aString.BeginReading(iter); iter != done_reading;
-       iter.advance(PRInt32(fragmentLength))) {
-    fragmentLength = PRUint32(iter.size_forward());
-    const PRUnichar* c = iter.get();
-    const PRUnichar* fragmentEnd = c + fragmentLength;
-
-    // for each character in this chunk...
-    while (c < fragmentEnd)
-      if (*c++ & EIGHT_BIT)
-        return PR_FALSE;
-  }
-
-  return PR_TRUE;
-}
-
 NS_IMETHODIMP
 nsGlobalWindow::Atob(const nsAString& aAsciiBase64String,
                      nsAString& aBinaryData)
 {
-  if (!Is8bit(aAsciiBase64String)) {
-    aBinaryData.Truncate();
-    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
-  }
-
-  nsresult rv = nsXPConnect::Base64Decode(aAsciiBase64String, aBinaryData);
-  if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
-    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
-  }
-  return rv;
+  return nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Btoa(const nsAString& aBinaryData,
                      nsAString& aAsciiBase64String)
 {
-  if (!Is8bit(aBinaryData)) {
-    aAsciiBase64String.Truncate();
-    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
-  }
-
-  return nsXPConnect::Base64Encode(aBinaryData, aAsciiBase64String);
+  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
 }
 
 //*****************************************************************************
 // nsGlobalWindow::nsIDOMEventTarget
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsGlobalWindow::RemoveEventListener(const nsAString& aType,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1073,16 +1073,30 @@ TabChildGlobal::GetDocShell(nsIDocShell*
   *aDocShell = nsnull;
   if (!mTabChild)
     return NS_ERROR_NULL_POINTER;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
   docShell.swap(*aDocShell);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+TabChildGlobal::Btoa(const nsAString& aBinaryData,
+                     nsAString& aAsciiBase64String)
+{
+  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
+}
+
+NS_IMETHODIMP
+TabChildGlobal::Atob(const nsAString& aAsciiString,
+                     nsAString& aBinaryData)
+{
+  return nsContentUtils::Atob(aAsciiString, aBinaryData);
+}
+
 JSContext*
 TabChildGlobal::GetJSContextForEventHandlers()
 {
   if (!mTabChild)
     return nsnull;
   return mTabChild->GetJSContext();
 }
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -105,16 +105,20 @@ public:
   }
   NS_IMETHOD GetContent(nsIDOMWindow** aContent);
   NS_IMETHOD GetDocShell(nsIDocShell** aDocShell);
   NS_IMETHOD Dump(const nsAString& aStr)
   {
     return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
   }
   NS_IMETHOD PrivateNoteIntentionalCrash();
+  NS_IMETHOD Btoa(const nsAString& aBinaryData,
+                  nsAString& aAsciiBase64String);
+  NS_IMETHOD Atob(const nsAString& aAsciiString,
+                  nsAString& aBinaryData);
 
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               PRBool aUseCapture)
   {
     // By default add listeners only for trusted events!
     return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
                                                     aUseCapture, PR_FALSE, 2);
--- a/dom/plugins/ipc/PPluginModule.ipdl
+++ b/dom/plugins/ipc/PPluginModule.ipdl
@@ -34,16 +34,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 include protocol PPluginIdentifier;
 include protocol PPluginInstance;
+include protocol PPluginScriptableObject;
 
 include "npapi.h";
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using NPError;
 using NPNVariable;
 using base::FileDescriptor;
 using mozilla::plugins::NativeThreadId;
@@ -148,12 +149,15 @@ parent:
   async PluginHideWindow(uint32_t aWindowId);
 
   // OS X Specific calls to allow the plugin to manage the cursor.
   async SetCursor(NSCursorInfo cursorInfo);
   async ShowCursor(bool show);
   async PushCursor(NSCursorInfo cursorInfo);
   async PopCursor();
   sync GetNativeCursorsSupported() returns (bool supported);
+
+  sync NPN_SetException(nullable PPluginScriptableObject actor,
+                        nsCString message);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -1511,17 +1511,29 @@ void NP_CALLBACK
 }
 
 void NP_CALLBACK
 _setexception(NPObject* aNPObj,
               const NPUTF8* aMessage)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     ENSURE_PLUGIN_THREAD_VOID();
-    NS_WARNING("Not yet implemented!");
+
+    PluginModuleChild* self = PluginModuleChild::current();
+    PluginScriptableObjectChild* actor = NULL;
+    if (aNPObj) {
+        actor = self->GetActorForNPObject(aNPObj);
+        if (!actor) {
+            NS_ERROR("Failed to get actor!");
+            return;
+        }
+    }
+
+    self->SendNPN_SetException(static_cast<PPluginScriptableObjectChild*>(actor),
+                               NullableString(aMessage));
 }
 
 void NP_CALLBACK
 _pushpopupsenabledstate(NPP aNPP,
                         NPBool aEnabled)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     ENSURE_PLUGIN_THREAD_VOID();
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -1204,8 +1204,26 @@ PluginModuleParent::AddToRefreshTimer(Pl
 void
 PluginModuleParent::RemoveFromRefreshTimer(PluginInstanceParent *aInstance) {
     PRBool visibleRemoved = mCATimerTargets.RemoveElement(aInstance);
     if (visibleRemoved && mCATimerTargets.IsEmpty()) {
         mCATimer->Cancel();
     }
 }
 #endif
+
+bool
+PluginModuleParent::RecvNPN_SetException(PPluginScriptableObjectParent* aActor,
+                                         const nsCString& aMessage)
+{
+    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
+
+    NPObject* aNPObj = NULL;
+    if (aActor) {
+        aNPObj = static_cast<PluginScriptableObjectParent*>(aActor)->GetObject(true);
+        if (!aNPObj) {
+            NS_ERROR("Failed to get object!");
+            return false;
+        }
+    }
+    mozilla::plugins::parent::_setexception(aNPObj, NullableStringGet(aMessage));
+    return true;
+}
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -205,16 +205,20 @@ protected:
     RecvPushCursor(const NSCursorInfo& aCursorInfo);
 
     NS_OVERRIDE virtual bool
     RecvPopCursor();
 
     NS_OVERRIDE virtual bool
     RecvGetNativeCursorsSupported(bool* supported);
 
+    NS_OVERRIDE virtual bool
+    RecvNPN_SetException(PPluginScriptableObjectParent* aActor,
+                         const nsCString& aMessage);
+
     static PluginInstanceParent* InstCast(NPP instance);
     static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
 
 private:
     void SetPluginFuncs(NPPluginFuncs* aFuncs);
 
     // Implement the module-level functions from NPAPI; these are
     // normally resolved directly from the DSO.
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -97,20 +97,20 @@ include $(topsrcdir)/config/rules.mk
   test_bug539565-2.html \
   test_enumerate.html \
   test_npruntime_construct.html \
   307-xo-redirect.sjs \
   test_redirect_handling.html \
   test_clear_site_data.html \
   test_zero_opacity.html \
   test_NPPVpluginWantsAllNetworkStreams.html \
+  test_npruntime_npnsetexception.html \
   $(NULL)
 
 #  test_plugin_scroll_painting.html \ bug 596491
-#  test_npruntime_npnsetexception.html \ Disabled for e10s
 
 ifeq ($(OS_ARCH),WINNT)
 _MOCHITEST_FILES += \
   test_windowed_invalidate.html \
   $(NULL)
 
 # test_positioning.html \ disabled due to oddness, perhaps scrolling of the
 # mochitest window?
--- a/dom/plugins/test/mochitest/neverending.sjs
+++ b/dom/plugins/test/mochitest/neverending.sjs
@@ -1,15 +1,16 @@
+var timer = null; // declare timer outside to prevent premature GC
 function handleRequest(request, response)
 {
   response.processAsync();
   response.setHeader("Content-Type", "text/plain", false);
 
   for (var i = 0; i < 1000; ++i)
     response.write("Hello... ");
 
-  var timer = Components.classes["@mozilla.org/timer;1"]
+  timer = Components.classes["@mozilla.org/timer;1"]
     .createInstance(Components.interfaces.nsITimer);
   timer.initWithCallback(function() {
       response.write("world.\n");
       response.finish();
     }, 10 * 1000 /* 10 secs */, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
 }
--- a/dom/system/nsDeviceMotion.cpp
+++ b/dom/system/nsDeviceMotion.cpp
@@ -44,16 +44,19 @@
 #include "nsIServiceManager.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMDeviceOrientationEvent.h"
 #include "nsIDOMDeviceMotionEvent.h"
 #include "nsIServiceManager.h"
 #include "nsIPrefService.h"
 #include "nsDOMDeviceMotionEvent.h"
 
+static const nsTPtrArray<nsIDOMWindow>::index_type NoIndex =
+    nsTPtrArray<nsIDOMWindow>::NoIndex;
+
 class nsDeviceMotionData : public nsIDeviceMotionData
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDEVICEMOTIONDATA
 
   nsDeviceMotionData(unsigned long type, double x, double y, double z);
 
@@ -166,50 +169,54 @@ nsDeviceMotion::TimeoutHandler(nsITimer 
   if (self->mListeners.Count() == 0 && self->mWindowListeners.Length() == 0) {
     self->Shutdown();
     self->mStarted = PR_FALSE;
   }
 }
 
 NS_IMETHODIMP nsDeviceMotion::AddListener(nsIDeviceMotionListener *aListener)
 {
-  if (mListeners.IndexOf(aListener) >= 0)
+  if (mListeners.IndexOf(aListener) != -1)
     return NS_OK; // already exists
 
   if (mStarted == PR_FALSE) {
     mStarted = PR_TRUE;
     Startup();
   }
 
   mListeners.AppendObject(aListener);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDeviceMotion::RemoveListener(nsIDeviceMotionListener *aListener)
 {
-  if (mListeners.IndexOf(aListener) < 0)
+  if (mListeners.IndexOf(aListener) == -1)
     return NS_OK; // doesn't exist
 
   mListeners.RemoveObject(aListener);
   StartDisconnectTimer();
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDeviceMotion::AddWindowListener(nsIDOMWindow *aWindow)
 {
   if (mStarted == PR_FALSE) {
     mStarted = PR_TRUE;
     Startup();
   }
-  mWindowListeners.AppendElement(aWindow);
+  if (mWindowListeners.IndexOf(aWindow) != NoIndex)
+    mWindowListeners.AppendElement(aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDeviceMotion::RemoveWindowListener(nsIDOMWindow *aWindow)
 {
+  if (mWindowListeners.IndexOf(aWindow) != NoIndex)
+    return NS_OK;
+
   mWindowListeners.RemoveElement(aWindow);
   StartDisconnectTimer();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z)
 {
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -138,12 +138,15 @@ include $(topsrcdir)/config/rules.mk
 		test_bug622361.html \
 		test_bug633133.html \
 		test_bug642026.html \
 		test_bug648465.html \
 		test_bug654137.html \
 		test_window_bar.html \
 		file_window_bar.html \
 		test_resize_move_windows.html \
+		test_devicemotion_multiple_listeners.html \
+		devicemotion_outer.html \
+		devicemotion_inner.html \
 		$(NULL)
 
 libs:: 	$(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/devicemotion_inner.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<script>
+function handler(ev) {}
+window.addEventListener("devicemotion", handler);
+window.ondeviceorientation = handler;
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/devicemotion_outer.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<script>
+var total = 50;
+var loaded = 0;
+for (var i = 0; i < total; i++) {
+  var f = document.createElement("iframe");
+  document.body.appendChild(f);
+  f.onload = function() {
+                    loaded++;
+                    if (loaded == total - 1)
+                      document.location.replace("about:blank");
+	     }
+  f.setAttribute('src', 'devicemotion_inner.html');
+}
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_devicemotion_multiple_listeners.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=673472
+-->
+<head>
+  <title>Test for Bug 673472</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"/>
+  <base href="http://mochi.test:8888/tests/dom/tests/mochitest/bugs/">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=673472">Mozilla Bug 673472</a>
+<pre id="test">
+<script type="application/javascript">
+
+function f() {
+try {
+  var ifr = document.getElementById('i');
+  if (ifr.contentWindow.document.location == 'about:blank') {
+    ifr.parentNode.removeChild(ifr);
+    ok(true, "no crash received");
+    SpecialPowers.executeSoon(SimpleTest.finish);
+  }
+} catch(e) {
+ok(false, e);
+}
+}
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+<iframe src="devicemotion_outer.html" onload="f()" id=i></iframe>  
+</body>
+</html>
--- a/dom/workers/XMLHttpRequestPrivate.cpp
+++ b/dom/workers/XMLHttpRequestPrivate.cpp
@@ -55,21 +55,18 @@
 #include "nsXMLHttpRequest.h"
 
 #include "Events.h"
 #include "EventTarget.h"
 #include "Exceptions.h"
 #include "RuntimeService.h"
 #include "XMLHttpRequest.h"
 
-USING_WORKERS_NAMESPACE
-
-using mozilla::dom::workers::xhr::XMLHttpRequestPrivate;
-using mozilla::dom::workers::xhr::Proxy;
-using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
+BEGIN_WORKERS_NAMESPACE
+namespace xhr {
 
 class Proxy : public nsIDOMEventListener
 {
 public:
   // Read on multiple threads.
   WorkerPrivate* mWorkerPrivate;
   XMLHttpRequestPrivate* mXMLHttpRequestPrivate;
 
@@ -183,16 +180,25 @@ public:
   {
     AssertIsOnMainThread();
 
     return mSyncQueueKey == PR_UINT32_MAX &&
            mSyncEventResponseSyncQueueKey == PR_UINT32_MAX;
   }
 };
 
+} // namespace xhr
+END_WORKERS_NAMESPACE
+
+USING_WORKERS_NAMESPACE
+
+using mozilla::dom::workers::xhr::XMLHttpRequestPrivate;
+using mozilla::dom::workers::xhr::Proxy;
+using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
+
 namespace {
 
 inline intN
 GetDOMExceptionCodeFromResult(nsresult aResult)
 {
   if (NS_SUCCEEDED(aResult)) {
     return 0;
   }
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -644,17 +644,17 @@ nsHTMLEditor::DoInsertHTMLWithContext(co
           curNode->GetParentNode(getter_AddRefs(parent));
           if (parent && !nsTextEditUtils::IsBody(parent))
           {
             res = InsertNodeAtPoint(parent, address_of(parentNode), &offsetOfNewNode, PR_TRUE);
             if (NS_SUCCEEDED(res)) 
             {
               bDidInsert = PR_TRUE;
               insertedContextParent = parent;
-              lastInsertNode = parent;
+              lastInsertNode = GetChildAt(parentNode, offsetOfNewNode);
             }
           }
           curNode = parent;
         }
       }
       if (lastInsertNode)
       {
         res = GetNodeLocation(lastInsertNode, address_of(parentNode), &offsetOfNewNode);
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -1544,48 +1544,59 @@ nsHTMLEditRules::WillInsertBreak(nsISele
   }
   
   res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
   
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = PR_FALSE;
-  
+
   // split any mailcites in the way.
   // should we abort this if we encounter table cell boundaries?
   if (IsMailEditor())
   {
     res = SplitMailCites(aSelection, IsPlaintextEditor(), aHandled);
     NS_ENSURE_SUCCESS(res, res);
     if (*aHandled) return NS_OK;
   }
 
   // smart splitting rules
   nsCOMPtr<nsIDOMNode> node;
   PRInt32 offset;
-  
+
   res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(node), &offset);
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
-    
+
+  // do nothing if the node is read-only
+  if (!mHTMLEditor->IsModifiableNode(node))
+  {
+    *aCancel = PR_TRUE;
+    return NS_OK;
+  }
+
   // identify the block
   nsCOMPtr<nsIDOMNode> blockParent;
-  
   if (IsBlockNode(node)) 
     blockParent = node;
   else 
     blockParent = mHTMLEditor->GetBlockNodeParent(node);
-    
   NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
-  
-  // do nothing if the node is read-only
-  if (!mHTMLEditor->IsModifiableNode(blockParent))
-  {
-    *aCancel = PR_TRUE;
+
+  // if the active editing host is an inline element,
+  // or if the active editing host is the block parent itself,
+  // just append a br.
+  nsCOMPtr<nsIContent> hostContent = mHTMLEditor->GetActiveEditingHost();
+  nsCOMPtr<nsIDOMNode> hostNode = do_QueryInterface(hostContent);
+  if (!nsEditorUtils::IsDescendantOf(blockParent, hostNode)) 
+  {
+    res = StandardBreakImpl(node, offset, aSelection);
+    NS_ENSURE_SUCCESS(res, res);
+    *aHandled = PR_TRUE;
     return NS_OK;
   }
 
   // if block is empty, populate with br.
   // (for example, imagine a div that contains the word "text".  the user selects
   // "text" and types return.  "text" is deleted leaving an empty block.  we want
   // to put in one br to make block have a line.  then code further below will put 
   // in a second br.)
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -758,17 +758,17 @@ nsresult nsHTMLEditor::RemoveStyleInside
         // and if it does not have a class nor an id
         nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
         res = RemoveElementIfNoStyleOrIdOrClass(element, nsEditProperty::span);
       }
     }
   }  
   if ( aProperty == nsEditProperty::font &&    // or node is big or small and we are setting font size
        (nsHTMLEditUtils::IsBig(aNode) || nsHTMLEditUtils::IsSmall(aNode)) &&
-       aAttribute->LowerCaseEqualsLiteral("size"))       
+       aAttribute && aAttribute->LowerCaseEqualsLiteral("size"))       
   {
     res = RemoveContainer(aNode);  // if we are setting font size, remove any nested bigs and smalls
   }
   return res;
 }
 
 PRBool nsHTMLEditor::IsOnlyAttribute(nsIDOMNode *aNode, 
                                      const nsAString *aAttribute)
@@ -1070,17 +1070,18 @@ nsHTMLEditor::GetInlinePropertyBase(nsIA
                                    isSet, getter_AddRefs(resultNode), outValue);
         *aFirst = *aAny = *aAll = isSet;
         
         if (!isSet && aCheckDefaults) 
         {
           // style not set, but if it is a default then it will appear if 
           // content is inserted, so we should report it as set (analogous to TypeInState).
           PRInt32 index;
-          if (TypeInState::FindPropInList(aProperty, *aAttribute, outValue, mDefaultStyles, index))
+          if (aAttribute &&
+              TypeInState::FindPropInList(aProperty, *aAttribute, outValue, mDefaultStyles, index))
           {
             *aFirst = *aAny = *aAll = PR_TRUE;
             if (outValue)
               outValue->Assign(mDefaultStyles[index]->value);
           }
         }
         return NS_OK;
       }
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -53,16 +53,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug410986.html \
 		test_bug414526.html \
 		test_bug417418.html \
 		test_bug432225.html \
 		test_bug439808.html \
  		test_bug449243.html \
 		test_bug455992.html \
 		test_bug456244.html \
+		test_bug460740.html \
 		test_bug478725.html \
 		test_bug480972.html \
 		test_bug484181.html \
 		test_bug487524.html \
 		test_bug520189.html \
 		test_bug525389.html \
 		test_bug537046.html \
 		test_bug549262.html \
@@ -92,16 +93,17 @@ include $(topsrcdir)/config/rules.mk
 		data/cfhtml-chromium.txt \
 		data/cfhtml-firefox.txt \
 		data/cfhtml-ie.txt \
 		data/cfhtml-ooo.txt \
 		$(NULL)
 
 _CHROME_TEST_FILES = \
 		test_contenteditable_text_input_handling.html \
+		test_bug489202.xul \
 		test_bug490879.xul \
 		test_bug607584.xul \
 		test_bug616590.xul \
 		test_bug635636.html \
 		green.png \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug460740.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=460740
+-->
+<head>
+  <title>Test for Bug 460740</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.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=460740">Mozilla Bug 460740</a>
+<p id="display"></p>
+<div id="content">
+  <ul>
+    <li contenteditable>
+      Editable LI
+    </li>
+    <li>
+      <div contenteditable>
+        Editable DIV inside LI
+      </div>
+    </li>
+    <li>
+      <div>
+        <div contenteditable>
+          Editable DIV inside DIV inside LI
+        </div>
+      </div>
+    </li>
+    <li>
+      <h3>
+        <div contenteditable>
+          Editable DIV inside H3 inside LI
+        </div>
+      </h3>
+    </li>
+  </ul>
+  <div contenteditable>
+    Editable DIV
+  </div>
+  <h3 contenteditable>
+    Editable H3
+  </h3>
+  <p contenteditable>
+    Editable P
+  </p>
+  <div>
+    <p contenteditable>
+      Editable P in a DIV
+    </p>
+  </div>
+  <p><span contenteditable>Editable SPAN in a P</span></p>
+</div>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 460740 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+const CARET_BEGIN  = 0;
+const CARET_MIDDLE = 1;
+const CARET_END    = 2;
+
+function split(element, caretPos) {
+  // compute the requested position
+  var len = element.textContent.length;
+  var pos = -1;
+  switch (caretPos) {
+    case CARET_BEGIN:
+      pos = 0;
+      break;
+    case CARET_MIDDLE:
+      pos = Math.floor(len/2);
+      break;
+    case CARET_END:
+      pos = len;
+      break;
+  }
+
+  // put the caret on the requested position
+  var range = document.createRange();
+  var sel = window.getSelection();
+  range.setStart(element.firstChild, len);
+  range.setEnd(element.firstChild, len);
+  sel.addRange(range);
+  
+  // simulates a [Return] keypress
+  synthesizeKey("VK_RETURN", {});
+}
+
+// count the number of non-BR elements in #content
+function getBlockCount() {
+  return document.querySelectorAll("#content *:not(br)").length;
+}
+
+// count the number of BRs in element
+function checkBR(element) {
+  return element.querySelectorAll("br").length;
+}
+
+function runTests() {
+  var count = getBlockCount();
+  var nodes = document.querySelectorAll("#content [contenteditable]");
+  for (var i = 0; i < nodes.length; i++) {
+    var node = nodes[i];
+    node.focus();
+    is(checkBR(node), 0, "This node should not have any <br> element yet.");
+    for (var j = 0; j < 3; j++) { // CARET_BEGIN|MIDDLE|END
+      split(node, j);
+      ok(checkBR(node) > 0, "Pressing [Return] should add (at least) one <br> element.");
+      is(getBlockCount(), count, "Pressing [Return] should not change the number of non-<br> elements.");
+      document.execCommand("Undo", false, null);
+    }
+  }
+  SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug489202.xul
@@ -0,0 +1,79 @@
+<?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=489202
+-->
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Mozilla Bug 489202" onload="runTest();">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"/>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=489202"
+     target="_blank">Mozilla Bug 489202</a>
+  <p/>
+  <editor xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          id="i1"
+          type="content"
+          editortype="htmlmail"
+          style="width: 400px; height: 100px;"/>
+  <p/>
+  <pre id="test">
+  </pre>
+  </body>
+  <script class="testbody" type="application/javascript">
+  <![CDATA[
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
+  var Cc = Components.classes;
+  var Ci = Components.interfaces;
+
+function runTest() {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+  var trans = Cc["@mozilla.org/widget/transferable;1"]
+      .createInstance(Ci.nsITransferable);
+  trans.addDataFlavor("text/html");
+  var test_data = '<meta/><a href="http://mozilla.org/">mozilla.org</a>';
+  var cstr = Cc["@mozilla.org/supports-string;1"]
+      .createInstance(Ci.nsISupportsString);
+  cstr.data = test_data;
+  trans.setTransferData("text/html", cstr, test_data.length*2);
+
+  window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+     .getInterface(Components.interfaces.nsIWebNavigation)
+     .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
+     .rootTreeItem
+     .QueryInterface(Components.interfaces.nsIDocShell)
+     .appType = Components.interfaces.nsIDocShell.APP_TYPE_EDITOR; 
+  var e = document.getElementById('i1');
+  var doc = e.contentDocument;
+  doc.designMode = "on";
+  doc.body.innerHTML = "";
+  doc.defaultView.focus();
+  var selection = doc.defaultView.getSelection();
+  selection.removeAllRanges();
+  selection.selectAllChildren(doc.body);
+  selection.collapseToEnd();
+
+  var point = doc.defaultView.getSelection().getRangeAt(0).startOffset;
+  ok(point==0, "Cursor should be at editor start before paste");
+
+  utils.sendContentCommandEvent("pasteTransferable", trans);
+
+  point = doc.defaultView.getSelection().getRangeAt(0).startOffset;
+  ok(point>0, "Cursor should not be at editor start after paste");
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+]]>
+</script>
+</window>
--- a/gfx/src/nsCoord.h
+++ b/gfx/src/nsCoord.h
@@ -93,16 +93,25 @@ inline nscoord NSToCoordRound(float aVal
 {
 #if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
   return NS_lroundup30(aValue);
 #else
   return nscoord(NS_floorf(aValue + 0.5f));
 #endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
 }
 
+inline nscoord NSToCoordRound(double aValue)
+{
+#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
+  return NS_lroundup30((float)aValue);
+#else
+  return nscoord(NS_floor(aValue + 0.5f));
+#endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
+}
+
 inline nscoord NSToCoordRoundWithClamp(float aValue)
 {
 #ifndef NS_COORD_IS_FLOAT
   // Bounds-check before converting out of float, to avoid overflow
   NS_WARN_IF_FALSE(aValue <= nscoord_MAX,
                    "Overflowed nscoord_MAX in conversion to nscoord");
   if (aValue >= nscoord_MAX) {
     return nscoord_MAX;
@@ -349,16 +358,21 @@ inline float NSCoordToFloat(nscoord aCoo
 /*
  * Coord Rounding Functions
  */
 inline nscoord NSToCoordFloor(float aValue)
 {
   return nscoord(NS_floorf(aValue));
 }
 
+inline nscoord NSToCoordFloor(double aValue)
+{
+  return nscoord(NS_floor(aValue));
+}
+
 inline nscoord NSToCoordFloorClamped(float aValue)
 {
 #ifndef NS_COORD_IS_FLOAT
   // Bounds-check before converting out of float, to avoid overflow
   NS_WARN_IF_FALSE(aValue <= nscoord_MAX,
                    "Overflowed nscoord_MAX in conversion to nscoord");
   if (aValue >= nscoord_MAX) {
     return nscoord_MAX;
@@ -372,16 +386,21 @@ inline nscoord NSToCoordFloorClamped(flo
   return NSToCoordFloor(aValue);
 }
 
 inline nscoord NSToCoordCeil(float aValue)
 {
   return nscoord(NS_ceilf(aValue));
 }
 
+inline nscoord NSToCoordCeil(double aValue)
+{
+  return nscoord(NS_ceil(aValue));
+}
+
 inline nscoord NSToCoordCeilClamped(float aValue)
 {
 #ifndef NS_COORD_IS_FLOAT
   // Bounds-check before converting out of float, to avoid overflow
   NS_WARN_IF_FALSE(aValue <= nscoord_MAX,
                    "Overflowed nscoord_MAX in conversion to nscoord");
   if (aValue >= nscoord_MAX) {
     return nscoord_MAX;
@@ -390,16 +409,34 @@ inline nscoord NSToCoordCeilClamped(floa
                    "Overflowed nscoord_MIN in conversion to nscoord");
   if (aValue <= nscoord_MIN) {
     return nscoord_MIN;
   }
 #endif
   return NSToCoordCeil(aValue);
 }
 
+inline nscoord NSToCoordCeilClamped(double aValue)
+{
+#ifndef NS_COORD_IS_FLOAT
+  // Bounds-check before converting out of double, to avoid overflow
+  NS_WARN_IF_FALSE(aValue <= nscoord_MAX,
+                   "Overflowed nscoord_MAX in conversion to nscoord");
+  if (aValue >= nscoord_MAX) {
+    return nscoord_MAX;
+  }
+  NS_WARN_IF_FALSE(aValue >= nscoord_MIN,
+                   "Overflowed nscoord_MIN in conversion to nscoord");
+  if (aValue <= nscoord_MIN) {
+    return nscoord_MIN;
+  }
+#endif
+  return NSToCoordCeil(aValue);
+}
+
 /*
  * Int Rounding Functions
  */
 inline PRInt32 NSToIntFloor(float aValue)
 {
   return PRInt32(NS_floorf(aValue));
 }
 
@@ -408,16 +445,21 @@ inline PRInt32 NSToIntCeil(float aValue)
   return PRInt32(NS_ceilf(aValue));
 }
 
 inline PRInt32 NSToIntRound(float aValue)
 {
   return NS_lroundf(aValue);
 }
 
+inline PRInt32 NSToIntRound(double aValue)
+{
+  return NS_lround(aValue);
+}
+
 inline PRInt32 NSToIntRoundUp(float aValue)
 {
   return PRInt32(NS_floorf(aValue + 0.5f));
 }
 
 inline PRInt32 NSToIntRoundUp(double aValue)
 {
   return PRInt32(NS_floor(aValue + 0.5));
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -5937,16 +5937,21 @@ fi
   sort confdefs.h | egrep -v "$_EGREP_PATTERN" >> $_CONFIG_TMP
 
   if test "$?" != 0; then
     AC_MSG_ERROR([Error outputting config definitions])
   fi
 
   cat >> $_CONFIG_TMP <<\EOF
 
+/* The c99 defining the limit macros (UINT32_MAX for example), says:
+ * C++ implementations should define these macros only when __STDC_LIMIT_MACROS
+ * is defined before <stdint.h> is included. */
+#define __STDC_LIMIT_MACROS
+
 #endif /* _JS_CONFDEFS_H_ */
 
 EOF
 
   # Only write js-confdefs.h when something changes (or it doesn't exist)
   if cmp -s $_CONFIG_TMP $_CONFIG_DEFS_H; then
     rm $_CONFIG_TMP
   else
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testBug673066.js
@@ -0,0 +1,23 @@
+function f(code) {
+    a = code.replace(/s/, "");
+    wtt = a
+    code = code.replace(/\/\*DUPTRY\d+\*\//, function(k) {
+        n = parseInt(k.substr(8), 0);
+        return g("try{}catch(e){}", n)
+    });
+    f = eval("(function(){" + code + "})")
+    if (typeof disassemble == 'function') {
+        disassemble("-r", f)
+    }
+}
+function g(s, n) {
+    if (n == 0) {
+        return s
+    }
+    s2 = s + s
+    r = n % 2
+    d = (n - r) / 2
+    m = g(s2, d)
+    return r ? m + s : m
+}
+f("switch(''){default:break;/*DUPTRY525*/}")
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -160,17 +160,17 @@ JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GCThing
 #ifdef DEBUG
 void
 ArenaHeader::checkSynchronizedWithFreeList() const
 {
     /*
      * Do not allow to access the free list when its real head is still stored
      * in FreeLists and is not synchronized with this one.
      */
-    JS_ASSERT(compartment);
+    JS_ASSERT(allocated());
 
     /*
      * We can be called from the background finalization thread when the free
      * list in the compartment can mutate at any moment. We cannot do any
      * checks in this case.
      */
     if (!compartment->rt->gcRunning)
         return;
@@ -190,17 +190,17 @@ ArenaHeader::checkSynchronizedWithFreeLi
     JS_ASSERT(firstSpan.end == list->end);
 }
 #endif
 
 template<typename T>
 inline bool
 Arena::finalize(JSContext *cx)
 {
-    JS_ASSERT(aheader.compartment);
+    JS_ASSERT(aheader.allocated());
     JS_ASSERT(!aheader.getMarkingDelay()->link);
 
     uintptr_t thing = thingsStart(sizeof(T));
     uintptr_t end = thingsEnd();
 
     FreeSpan nextFree(aheader.getFirstFreeSpan());
     nextFree.checkSpan();
 
@@ -315,28 +315,31 @@ JSCompartment::finishArenaLists()
         arenas[i].releaseAll(i);
 }
 
 void
 Chunk::init(JSRuntime *rt)
 {
     info.runtime = rt;
     info.age = 0;
-    info.emptyArenaListHead = &arenas[0].aheader;
-    ArenaHeader *aheader = &arenas[0].aheader;
-    ArenaHeader *last = &arenas[JS_ARRAY_LENGTH(arenas) - 1].aheader;
-    while (aheader < last) {
-        ArenaHeader *following = reinterpret_cast<ArenaHeader *>(aheader->address() + ArenaSize);
-        aheader->next = following;
-        aheader->compartment = NULL;
-        aheader = following;
+    info.numFree = ArenasPerChunk;
+
+    /* Assemble all arenas into a linked list and mark them as not allocated. */
+    ArenaHeader **prevp = &info.emptyArenaListHead;
+    Arena *end = &arenas[JS_ARRAY_LENGTH(arenas)];
+    for (Arena *a = &arenas[0]; a != end; ++a) {
+#ifdef DEBUG
+        memset(a, ArenaSize, JS_FREE_PATTERN);
+#endif
+        *prevp = &a->aheader;
+        a->aheader.setAsNotAllocated();
+        prevp = &a->aheader.next;
     }
-    last->next = NULL;
-    last->compartment = NULL;
-    info.numFree = ArenasPerChunk;
+    *prevp = NULL;
+
     for (size_t i = 0; i != JS_ARRAY_LENGTH(markingDelay); ++i)
         markingDelay[i].init();
 }
 
 bool
 Chunk::unused()
 {
     return info.numFree == ArenasPerChunk;
@@ -376,16 +379,17 @@ Chunk::allocateArena(JSContext *cx, unsi
         TriggerCompartmentGC(comp);
 
     return aheader;
 }
 
 void
 Chunk::releaseArena(ArenaHeader *aheader)
 {
+    JS_ASSERT(aheader->allocated());
     JSRuntime *rt = info.runtime;
 #ifdef JS_THREADSAFE
     Maybe<AutoLockGC> maybeLock;
     if (rt->gcHelperThread.sweeping)
         maybeLock.construct(info.runtime);
 #endif
     JSCompartment *comp = aheader->compartment;
 
@@ -395,52 +399,25 @@ Chunk::releaseArena(ArenaHeader *aheader
 #ifdef JS_THREADSAFE
     if (rt->gcHelperThread.sweeping) {
         rt->reduceGCTriggerBytes(GC_HEAP_GROWTH_FACTOR * ArenaSize);
         comp->reduceGCTriggerBytes(GC_HEAP_GROWTH_FACTOR * ArenaSize);
     }
 #endif
     JS_ATOMIC_ADD(&rt->gcBytes, -int32(ArenaSize));
     JS_ATOMIC_ADD(&comp->gcBytes, -int32(ArenaSize));
+
+    aheader->setAsNotAllocated();
     aheader->next = info.emptyArenaListHead;
     info.emptyArenaListHead = aheader;
-    aheader->compartment = NULL;
     ++info.numFree;
     if (unused())
         info.age = 0;
 }
 
-JSRuntime *
-Chunk::getRuntime()
-{
-    return info.runtime;
-}
-
-inline jsuword
-GetGCChunk(JSRuntime *rt)
-{
-    void *p = rt->gcChunkAllocator->alloc();
-#ifdef MOZ_GCTIMER
-    if (p)
-        JS_ATOMIC_INCREMENT(&newChunkCount);
-#endif
-    return reinterpret_cast<jsuword>(p);
-}
-
-inline void
-ReleaseGCChunk(JSRuntime *rt, jsuword chunk)
-{
-    void *p = reinterpret_cast<void *>(chunk);
-    JS_ASSERT(p);
-#ifdef MOZ_GCTIMER
-    JS_ATOMIC_INCREMENT(&destroyChunkCount);
-#endif
-    rt->gcChunkAllocator->free_(p);
-}
-
 inline Chunk *
 AllocateGCChunk(JSRuntime *rt)
 {
     Chunk *p = (Chunk *)rt->gcChunkAllocator->alloc();
 #ifdef MOZ_GCTIMER
     if (p)
         JS_ATOMIC_INCREMENT(&newChunkCount);
 #endif
@@ -671,17 +648,17 @@ InFreeList(ArenaHeader *aheader, uintptr
         span = span->nextSpan();
     }
 }
 
 template <typename T>
 inline ConservativeGCTest
 MarkArenaPtrConservatively(JSTracer *trc, ArenaHeader *aheader, uintptr_t addr)
 {
-    JS_ASSERT(aheader->compartment);
+    JS_ASSERT(aheader->allocated());
     JS_ASSERT(sizeof(T) == aheader->getThingSize());
 
     uintptr_t offset = addr & ArenaMask;
     uintptr_t minOffset = Arena::thingsStartOffset(sizeof(T));
     if (offset < minOffset)
         return CGCT_NOTARENA;
 
     /* addr can point inside the thing so we must align the address. */
@@ -737,31 +714,31 @@ MarkIfGCThingWord(JSTracer *trc, jsuword
 #if JS_BITS_PER_WORD == 32
     jsuword addr = w & JSID_PAYLOAD_MASK;
 #elif JS_BITS_PER_WORD == 64
     jsuword addr = w & JSID_PAYLOAD_MASK & JSVAL_PAYLOAD_MASK;
 #endif
 
     Chunk *chunk = Chunk::fromAddress(addr);
 
-    if (!trc->context->runtime->gcUserChunkSet.has(chunk) && 
+    if (!trc->context->runtime->gcUserChunkSet.has(chunk) &&
         !trc->context->runtime->gcSystemChunkSet.has(chunk))
         return CGCT_NOTCHUNK;
 
     /*
      * We query for pointers outside the arena array after checking for an
      * allocated chunk. Such pointers are rare and we want to reject them
      * after doing more likely rejections.
      */
     if (!Chunk::withinArenasRange(addr))
         return CGCT_NOTARENA;
 
     ArenaHeader *aheader = &chunk->arenas[Chunk::arenaIndex(addr)].aheader;
 
-    if (!aheader->compartment)
+    if (!aheader->allocated())
         return CGCT_FREEARENA;
 
     ConservativeGCTest test;
     unsigned thingKind = aheader->getThingKind();
 
     switch (thingKind) {
       case FINALIZE_OBJECT0:
       case FINALIZE_OBJECT0_BACKGROUND:
@@ -2817,17 +2794,17 @@ TraceRuntime(JSTracer *trc)
      * Calls from inside a normal GC or a recursive calls are OK and do not
      * require session setup.
      */
     MarkRuntime(trc);
 }
 
 void
 IterateCompartmentsArenasCells(JSContext *cx, void *data,
-                               IterateCompartmentCallback compartmentCallback, 
+                               IterateCompartmentCallback compartmentCallback,
                                IterateArenaCallback arenaCallback,
                                IterateCellCallback cellCallback)
 {
     CHECK_REQUEST(cx);
 
     LeaveTrace(cx);
 
     JSRuntime *rt = cx->runtime;
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -233,31 +233,47 @@ struct ArenaHeader {
      * and end offsets within the arena, not as FreeSpan structure, to
      * minimize the header size. When the arena has no free things, the span
      * must be the empty one pointing to the arena's end. For such a span the
      * start and end offsets must be ArenaSize.
      */
     uint16_t        firstFreeSpanStart;
     uint16_t        firstFreeSpanEnd;
 
+    /*
+     * One of FinalizeKind constants or FINALIZE_LIMIT when the arena does not
+     * contain any GC things and is on the list of empty arenas in the GC
+     * chunk. The later allows to quickly check if the arena is allocated
+     * during the conservative GC scanning without searching the arena in the
+     * list.
+     */
     unsigned        thingKind;
 
     friend struct FreeLists;
 
   public:
     inline uintptr_t address() const;
     inline Chunk *chunk() const;
 
+    void setAsNotAllocated() {
+        thingKind = FINALIZE_LIMIT;
+    }
+
+    bool allocated() const {
+        return thingKind < FINALIZE_LIMIT;
+    }
+
     inline void init(JSCompartment *comp, unsigned thingKind, size_t thingSize);
 
     Arena *getArena() {
         return reinterpret_cast<Arena *>(address());
     }
 
     unsigned getThingKind() const {
+        JS_ASSERT(allocated());
         return thingKind;
     }
 
     bool hasFreeThings() const {
         return firstFreeSpanStart != ArenaSize;
     }
 
     void setAsFullyUsed() {
@@ -482,19 +498,18 @@ struct Chunk {
     bool unused();
     bool hasAvailableArenas();
     bool withinArenasRange(Cell *cell);
 
     template <size_t thingSize>
     ArenaHeader *allocateArena(JSContext *cx, unsigned thingKind);
 
     void releaseArena(ArenaHeader *aheader);
+};
 
-    JSRuntime *getRuntime();
-};
 JS_STATIC_ASSERT(sizeof(Chunk) <= GC_CHUNK_SIZE);
 JS_STATIC_ASSERT(sizeof(Chunk) + BytesPerArena > GC_CHUNK_SIZE);
 
 inline uintptr_t
 Cell::address() const
 {
     uintptr_t addr = uintptr_t(this);
     JS_ASSERT(addr % Cell::CellSize == 0);
@@ -525,17 +540,17 @@ Cell::isAligned() const
 {
     return Arena::isAligned(address(), arenaHeader()->getThingSize());
 }
 #endif
 
 inline void
 ArenaHeader::init(JSCompartment *comp, unsigned kind, size_t thingSize)
 {
-    JS_ASSERT(!compartment);
+    JS_ASSERT(!allocated());
     JS_ASSERT(!getMarkingDelay()->link);
     compartment = comp;
     thingKind = kind;
     firstFreeSpanStart = uint16_t(Arena::thingsStartOffset(thingSize));
     firstFreeSpanEnd = uint16_t(ArenaSize);
 }
 
 inline uintptr_t
@@ -1340,17 +1355,17 @@ typedef void (*IterateCellCallback)(JSCo
 
 /*
  * This function calls |compartmentCallback| on every compartment,
  * |arenaCallback| on every in-use arena, and |cellCallback| on every in-use
  * cell in the GC heap.
  */
 extern JS_FRIEND_API(void)
 IterateCompartmentsArenasCells(JSContext *cx, void *data,
-                               IterateCompartmentCallback compartmentCallback, 
+                               IterateCompartmentCallback compartmentCallback,
                                IterateArenaCallback arenaCallback,
                                IterateCellCallback cellCallback);
 
 } /* namespace js */
 
 extern void
 js_FinalizeStringRT(JSRuntime *rt, JSString *str);
 
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -107,18 +107,18 @@ Mark(JSTracer *trc, T *thing)
     JS_ASSERT(thing);
     JS_ASSERT(JS_IS_VALID_TRACE_KIND(GetGCThingTraceKind(thing)));
     JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);
 
     JS_ASSERT(!JSAtom::isStatic(thing));
     JS_ASSERT(thing->isAligned());
 
     JSRuntime *rt = trc->context->runtime;
-    JS_ASSERT(thing->arenaHeader()->compartment);
-    JS_ASSERT(thing->arenaHeader()->compartment->rt == rt);
+    JS_ASSERT(thing->compartment());
+    JS_ASSERT(thing->compartment()->rt == rt);
 
     if (rt->gcCheckCompartment && thing->compartment() != rt->gcCheckCompartment &&
         thing->compartment() != rt->atomsCompartment)
     {
         JS_Assert("compartment mismatch in GC", __FILE__, __LINE__);
     }
 
     /*
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5735,16 +5735,18 @@ js_DeleteProperty(JSContext *cx, JSObjec
         if (strict)
             return obj->reportNotConfigurable(cx, id);
         rval->setBoolean(false);
         return true;
     }
 
     if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, SHAPE_USERID(shape), rval))
         return false;
+    if (rval->isFalse())
+        return true;
 
     if (obj->containsSlot(shape->slot)) {
         const Value &v = obj->nativeGetSlot(shape->slot);
         GCPoke(cx, v);
 
         /*
          * Delete is rare enough that we can take the hit of checking for an
          * active cloned method function object that must be homed to a callee
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -350,30 +350,32 @@ struct JSObject : js::gc::Cell {
 
     inline js::Shape **nativeSearch(jsid id, bool adding = false);
     inline const js::Shape *nativeLookup(jsid id);
 
     inline bool nativeContains(jsid id);
     inline bool nativeContains(const js::Shape &shape);
 
     enum {
-        DELEGATE                  =   0x01,
-        SYSTEM                    =   0x02,
-        NOT_EXTENSIBLE            =   0x04,
-        BRANDED                   =   0x08,
-        GENERIC                   =   0x10,
-        METHOD_BARRIER            =   0x20,
-        INDEXED                   =   0x40,
-        OWN_SHAPE                 =   0x80,
-        BOUND_FUNCTION            =  0x100,
-        HAS_EQUALITY              =  0x200,
-        VAROBJ                    =  0x400,
-        METHOD_THRASH_COUNT_MASK  = 0x3000,
-        METHOD_THRASH_COUNT_SHIFT =     12,
-        METHOD_THRASH_COUNT_MAX   = METHOD_THRASH_COUNT_MASK >> METHOD_THRASH_COUNT_SHIFT
+        DELEGATE                  =       0x01,
+        SYSTEM                    =       0x02,
+        NOT_EXTENSIBLE            =       0x04,
+        BRANDED                   =       0x08,
+        GENERIC                   =       0x10,
+        METHOD_BARRIER            =       0x20,
+        INDEXED                   =       0x40,
+        OWN_SHAPE                 =       0x80,
+        METHOD_THRASH_COUNT_MASK  =      0x300,
+        METHOD_THRASH_COUNT_SHIFT =          8,
+        METHOD_THRASH_COUNT_MAX   = METHOD_THRASH_COUNT_MASK >> METHOD_THRASH_COUNT_SHIFT,
+        BOUND_FUNCTION            =      0x400,
+        HAS_EQUALITY              =      0x800,
+        VAROBJ                    =     0x1000,
+
+        UNUSED_FLAG_BITS          = 0xFFFFE000
     };
 
     /*
      * Impose a sane upper bound, originally checked only for dense arrays, on
      * number of slots in an object.
      */
     enum {
         NSLOTS_BITS     = 29,
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1170,16 +1170,18 @@ JS_FRIEND_API(Class) FunctionProxyClass 
         NULL,             /* clear           */
     }
 };
 
 JS_FRIEND_API(JSObject *)
 NewProxyObject(JSContext *cx, JSProxyHandler *handler, const Value &priv, JSObject *proto,
                JSObject *parent, JSObject *call, JSObject *construct)
 {
+    JS_ASSERT_IF(proto, cx->compartment == proto->compartment());
+    JS_ASSERT_IF(parent, cx->compartment == parent->compartment());
     bool fun = call || construct;
     Class *clasp;
     if (fun)
         clasp = &FunctionProxyClass;
     else
         clasp = handler->isOuterWindow() ? &OuterWindowProxyClass : &ObjectProxyClass;
 
     if (!handler->isCrossCompartment() && priv.isObject()) {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1887,26 +1887,28 @@ SrcNotes(JSContext *cx, JSScript *script
             JSFunction *fun = (JSFunction *) JS_GetPrivate(cx, obj);
             str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
             JSAutoByteString bytes;
             if (!str || !bytes.encode(cx, str))
                 ReportException(cx);
             Sprint(sp, " function %u (%s)", index, !!bytes ? bytes.ptr() : "N/A");
             break;
           }
-          case SRC_SWITCH:
-            if (js_GetOpcode(cx, script, script->code + offset) == JSOP_GOTO)
+          case SRC_SWITCH: {
+            JSOp op = js_GetOpcode(cx, script, script->code + offset);
+            if (op == JSOP_GOTO || op == JSOP_GOTOX)
                 break;
             Sprint(sp, " length %u", uintN(js_GetSrcNoteOffset(sn, 0)));
             caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
             if (caseOff)
                 Sprint(sp, " first case offset %u", caseOff);
             UpdateSwitchTableBounds(cx, script, offset,
                                     &switchTableStart, &switchTableEnd);
             break;
+          }
           case SRC_CATCH:
             delta = (uintN) js_GetSrcNoteOffset(sn, 0);
             if (delta) {
                 if (script->main[offset] == JSOP_LEAVEBLOCK)
                     Sprint(sp, " stack depth %u", delta);
                 else
                     Sprint(sp, " guard delta %u", delta);
             }
--- a/js/src/tests/e4x/XML/regress-324688.js
+++ b/js/src/tests/e4x/XML/regress-324688.js
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 
 var summary = 'No Syntax Error when trailing space and XML.ignoreWhitespace ' +
     'true';
 var BUGNUMBER = 324688;
 var actual = 'No Error';
 var expect = 'No Error';
+var t; // use global scope to prevent timer from being GC'ed
 START(summary);
 
 function init()
 {
     if (typeof Components != 'undefined')
     {
         try
         {
@@ -73,17 +74,17 @@ function init()
                     print('actual = ' + actual);
                     TEST(1, expect, actual);
                     END();
                     gDelayTestDriverEnd = false;
                     jsTestDriverEnd();
                 }
             };
 
-            var t = Components.classes["@mozilla.org/timer;1"].
+            t = Components.classes["@mozilla.org/timer;1"].
                 createInstance(Components.interfaces.nsITimer);
             t.init(TestObject, 100, t.TYPE_ONE_SHOT);
         }
         catch(ex)
         {
             printStatus('Requires UniversalXPConnect');
         }
     }
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/Global/cross-global-implicit-this.js
@@ -0,0 +1,85 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 671947;
+var summary = "Unqualified function invocation uses the global object of the called property as |this|";
+var actual = "------------------------";
+var expect = "ooaoboabuuaubuabooaoboab";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+this.name = "o";
+
+function f() {
+  return this ? this.name : "t";
+}
+function g() {
+  "use strict";
+  return this ? this.name : "u";
+}
+function h() {
+  return this ? this.name : "v";
+}
+
+var sb = newGlobal('same-compartment');
+sb.parent = this;
+
+evalcx('\n' +
+       ' this.name="i";\n' +
+       ' this.f = parent.f;\n' +
+       ' this.g = parent.g;\n' +
+       ' this.a = { name:"a", f:parent.f, g:parent.g };\n' +
+       ' this.b = { name:"b", f:parent.f, g:parent.g };\n' +
+       ' Object.defineProperty(this, "h", { get: (function(){ return parent.h; })});\n' +
+       ' Object.defineProperty(a, "h", { get: (function(){ return parent.h; })});\n' +
+       ' Object.defineProperty(b, "h", { get: (function(){ return parent.h; })});\n' +
+
+       ' var results = "";\n' +
+
+       ' /* Three of the first four cases pass undefined (promoted inside the callee to the callee\'s global object). */\n' +
+       ' /* a.f() is the one exception, which passes the base, a, as the this object. */\n' +
+       ' results += (function(){return f();})();\n' +
+       ' results += (function(){return (1,f)();})();\n' +
+       ' results += (function(){return a.f();})();\n' +
+       ' results += (function(){return eval("f()");})();\n' +
+       ' /* Same cases as above, but wrapped in a with. The first & last of these cases pass b, */\n' +
+       ' /* the object scoped by the with, as the this value. */\n' +
+       ' /* a.f() still passes the explicit base, a. (1,f)() is a little tricksier - this passes */\n' +
+       ' /* undefined (promoted to the callee global object) since the comma operator calles GetValue */\n' +
+       ' /* on the reference (see ES5 11.14.) */\n' +
+       ' results += (function(){with(b){ return (function(){ return f();})(); }})();\n' +
+       ' results += (function(){with(b){ return (function(){ return (1,f)();})(); }})();\n' +
+       ' results += (function(){with(b){ return (function(){ return a.f();})(); }})();\n' +
+       ' results += (function(){with(b){ return (function(){ return eval("f()");})(); }})();\n' +
+
+       ' /* Same tests as above, but with a strict callee. */\n' +
+       ' /* We expect the same results, except undefined this is not replaced with the global object. */\n' +
+       ' results += (function(){return g();})();\n' +
+       ' results += (function(){return (1,g)();})();\n' +
+       ' results += (function(){return a.g();})();\n' +
+       ' results += (function(){return eval("g()");})();\n' +
+       ' results += (function(){with(b){ return g(); }})();\n' +
+       ' results += (function(){with(b){ return (1,g)(); }})();\n' +
+       ' results += (function(){with(b){ return a.g(); }})();\n' +
+       ' results += (function(){with(b){ return (function(){ return eval("g()");})(); }})();\n' +
+
+       ' /* Same as the first set, but h is a getter property. */\n' +
+       ' results += (function(){return h();})();\n' +
+       ' results += (function(){return (1,h)();})();\n' +
+       ' results += (function(){return a.h();})();\n' +
+       ' results += (function(){return eval("h()");})();\n' +
+       ' results += (function(){with(b){ return h(); }})();\n' +
+       ' results += (function(){with(b){ return (1,h)(); }})();\n' +
+       ' results += (function(){with(b){ return a.h(); }})();\n' +
+       ' results += (function(){with(b){ return (function(){ return eval("h()");})(); }})();\n' +
+
+       ' parent.actual = results;\n' +
+       '',
+       sb);
+
+reportCompare(expect, actual, "ok");
--- a/js/src/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/src/xpconnect/wrappers/WrapperFactory.cpp
@@ -106,17 +106,17 @@ WrapperFactory::WaiveXray(JSContext *cx,
 
         // No wrapper yet, make one.
         if (!wobj) {
             JSObject *proto = obj->getProto();
             if (proto && !(proto = WaiveXray(cx, proto)))
                 return nsnull;
 
             JSAutoEnterCompartment ac;
-            if (!ac.enter(cx, obj))
+            if (!ac.enter(cx, obj) || !JS_WrapObject(cx, &proto))
                 return nsnull;
             wobj = JSWrapper::New(cx, obj, proto, JS_GetGlobalForObject(cx, obj),
                                   &WaiveXrayWrapperWrapper);
             if (!wobj)
                 return nsnull;
 
             // Add the new wrapper so we find it next time.
             if (priv) {
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -2644,19 +2644,20 @@ nsListControlFrame::KeyPress(nsIDOMEvent
   // If we didn't do an incremental search, clear the string
   if (!didIncrementalSearch) {
     GetIncrementalString().Truncate();
   }
 
   // Actually process the new index and let the selection code
   // do the scrolling for us
   if (newIndex != kNothingSelected) {
-    // If you hold control, no key will actually do anything except space.
+    // If you hold control, but not shift, no key will actually do anything
+    // except space.
     PRBool wasChanged = PR_FALSE;
-    if (isControl && charcode != ' ') {
+    if (isControl && !isShift && charcode != ' ') {
       mStartSelectionIndex = newIndex;
       mEndSelectionIndex = newIndex;
       InvalidateFocus();
       ScrollToIndex(newIndex);
     } else if (mControlSelectMode && charcode == ' ') {
       wasChanged = SingleSelection(newIndex, PR_TRUE);
     } else {
       wasChanged = PerformSelection(newIndex, isShift, isControl);
--- a/layout/forms/test/Makefile.in
+++ b/layout/forms/test/Makefile.in
@@ -72,16 +72,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug377624.html \
 		test_bug571352.html \
 		test_bug572406.html \
 		test_bug572649.html \
 		test_bug36619.html \
 		test_bug620936.html \
 		test_bug595310.html \
 		test_bug644542.html \
+		test_bug672810.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_bug536567.html \
 		$(NULL)
 
 ifeq (WINNT,$(OS_ARCH))
 $(warning test_bug665540.html disabled due to bug 670053)
new file mode 100644
--- /dev/null
+++ b/layout/forms/test/test_bug672810.html
@@ -0,0 +1,117 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=672810
+-->
+<head>
+  <title>Test for Bug 672810</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.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=672810">Mozilla Bug 672810</a>
+<p id="display"></p>
+<div id="content">
+  <select id="s1" multiple size="10"><option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x</select>
+  <select id="s2" size="10"><option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x</select>
+  <select id="s3" size="1"><option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x<option>x</select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 672810 **/
+
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(function() {
+  var sel = document.getElementsByTagName('select');
+
+  sel[0].addEventListener('focus', function() {
+    s = sel[0];
+    s.removeEventListener('focus', arguments.callee, false);
+    synthesizeKey('VK_DOWN', {});
+    is(s.selectedIndex,0, s.id + ": initial DOWN selects first option");
+    synthesizeKey('VK_DOWN', {ctrlKey: true});
+    is(s.selectedIndex,0, s.id + ": first option is still selected");
+    ok(!s[1].selected,s.id + ": CTRL+DOWN did not select 2nd option");
+    synthesizeKey('VK_DOWN', {ctrlKey: true});
+    synthesizeKey('VK_DOWN', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,0, s.id + ": first option is still selected");
+    ok(!s[1].selected,s.id + ": 2nd option is still unselected");
+    ok(s[2].selected,s.id + ": 3rd option is selected");
+    ok(s[3].selected,s.id + ": 4th option is selected");
+    ok(!s[4].selected,s.id + ": 5th option is unselected");
+    synthesizeKey('VK_DOWN', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,0, s.id + ": first option is still selected");
+    ok(!s[1].selected,s.id + ": 2nd option is still unselected");
+    ok(s[2].selected,s.id + ": 3rd option is still selected");
+    ok(s[3].selected,s.id + ": 4th option is still selected");
+    ok(s[4].selected,s.id + ": 5th option is selected");
+    ok(!s[5].selected,s.id + ": 6th option is unselected");
+    synthesizeKey('VK_UP', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,0, s.id + ": first option is still selected");
+    ok(!s[1].selected,s.id + ": 2nd option is still unselected");
+    ok(s[2].selected,s.id + ": 3rd option is still selected");
+    ok(s[3].selected,s.id + ": 4th option is still selected");
+    ok(s[4].selected,s.id + ": 5th option is still selected");
+    ok(!s[5].selected,s.id + ": 6th option is still unselected");
+    synthesizeKey(' ', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,0, s.id + ": first option is still selected");
+    ok(!s[1].selected,s.id + ": 2nd option is still unselected");
+    ok(s[2].selected,s.id + ": 3rd option is still selected");
+    ok(!s[3].selected,s.id + ": 4th option is unselected");
+    ok(s[4].selected,s.id + ": 5th option is still selected");
+    ok(!s[5].selected,s.id + ": 6th option is still unselected");
+    synthesizeKey(' ', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,0, s.id + ": first option is still selected");
+    ok(!s[1].selected,s.id + ": 2nd option is still unselected");
+    ok(s[2].selected,s.id + ": 3rd option is still selected");
+    ok(s[3].selected,s.id + ": 4th option is selected");
+    ok(s[4].selected,s.id + ": 5th option is still selected");
+    ok(!s[5].selected,s.id + ": 6th option is still unselected");
+    setTimeout(function(){sel[1].focus()},0);
+  }, false);
+  sel[1].addEventListener('focus', function() {
+    s = sel[1];
+    s.removeEventListener('focus', arguments.callee, false);
+    synthesizeKey('VK_DOWN', {});
+    is(s.selectedIndex,0, s.id + ": initial DOWN selects first option");
+    synthesizeKey('VK_DOWN', {ctrlKey: true});
+    is(s.selectedIndex,1, s.id + ": 2nd option is selected");
+    ok(!s[0].selected,s.id + ": CTRL+DOWN deselected first option");
+    synthesizeKey('VK_DOWN', {ctrlKey: true});
+    synthesizeKey('VK_DOWN', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,3, s.id + ": 4th option is selected");
+    ok(!s[1].selected,s.id + ": CTRL+SHIFT+DOWN deselected 2nd option");
+    synthesizeKey(' ', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,3, s.id + ": 4th option is still selected");
+    synthesizeKey(' ', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,3, s.id + ": 4th option is still selected");
+    setTimeout(function(){sel[2].focus()},0);
+  }, false);
+  sel[2].addEventListener('focus', function() {
+    s = sel[2];
+    s.removeEventListener('focus', arguments.callee, false);
+    synthesizeKey('VK_DOWN', {});
+    is(s.selectedIndex,1, s.id + ": initial DOWN selects 2nd option");
+    synthesizeKey('VK_DOWN', {ctrlKey: true});
+    is(s.selectedIndex,2, s.id + ": 3rd option is selected");
+    ok(!s[1].selected,s.id + ": CTRL+DOWN deselected 2nd option");
+    synthesizeKey('VK_DOWN', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,3, s.id + ": 4th option is selected");
+    ok(!s[2].selected,s.id + ": CTRL+SHIFT+DOWN deselected 3rd option");
+    synthesizeKey(' ', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,3, s.id + ": 4th option is still selected");
+    synthesizeKey(' ', {ctrlKey: true, shiftKey: true});
+    is(s.selectedIndex,3, s.id + ": 4th option is still selected");
+    setTimeout(function(){SimpleTest.finish()},0);
+  }, false);
+  sel[0].focus();
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/reftests/pagination/reftest.list
+++ b/layout/reftests/pagination/reftest.list
@@ -39,8 +39,20 @@ fails == float-continuations-000.html fl
 == table-page-break-after-always-1.html table-page-break-before-auto-2-ref.html
 == table-page-break-after-left-1.html table-page-break-before-auto-2-ref.html
 == table-page-break-after-right-1.html table-page-break-before-auto-2-ref.html
 == rowgroup-page-break-after-always-1.html table-page-break-before-auto-2-ref.html
 == row-page-break-after-always-1.html table-page-break-before-auto-2-ref.html
 == row-page-break-after-always-2.html table-page-break-before-auto-2-ref.html
 == rowgroup-thead-page-break-after-always-1.html table-page-break-before-auto-3-ref.html 
 == rowgroup-tfoot-page-break-after-always-1.html table-page-break-before-auto-3-ref.html
+== table-caption-splitrowgroup-1.html table-caption-splitrowgroup-1-ref.html
+== table-caption-splitaftercaption-1.html table-caption-splitaftercaption-1-ref.html
+== table-caption-splitaftercaption-2.html table-caption-splitaftercaption-2-ref.html
+== table-caption-splitaftercaption-3.html table-caption-splitaftercaption-3-ref.html
+== table-caption-splitaftercaption-4.html table-caption-splitaftercaption-4-ref.html
+== table-caption-splitaftercaption-5.html table-caption-splitaftercaption-5-ref.html
+== table-caption-splitaftercaption-6.html table-caption-splitaftercaption-6-ref.html
+== table-caption-splitaftercaption-7.html table-caption-splitaftercaption-7-ref.html
+# == table-caption-splitaftercaption-8.html blank.html # bug 672654
+# == table-caption-splitaftercaption-9.html blank.html # bug 672654
+# == table-caption-splitaftercaption-10.html blank.html # bug 672654
+# == table-caption-splitaftercaption-11.html blank.html # bug 672654
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-1-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 90px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+</style>
+</head>
+<body>
+<div class=filler></div>
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-1.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 90px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+</style>
+</head>
+<body>
+<div class=filler></div>
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-10.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:5px; caption-side:top-outside}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer" style="padding-top:160px"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-11.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:5px; caption-side:bottom-outside}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer" style="padding-top:160px"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-2-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 25px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+</style>
+</head>
+<body>
+<div class=filler></div>
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-2.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:25px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+</style>
+</head>
+<body>
+<div class=filler></div>
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-3-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 25px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 10px; margin-bottom:20px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-3.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 10px; margin-bottom:20px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-4-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 25px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:5px}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-4.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:5px}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-5-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 25px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:5px; caption-side:bottom}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-5.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:5px; caption-side:bottom}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-6-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 25px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:15px; caption-side:top-outside}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-6.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:15px; caption-side:top-outside}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-7-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 25px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:15px; caption-side:bottom-outside}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-7.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:15px; caption-side:bottom-outside}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-8.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+tfoot div {border-color:orange;}
+caption {margin-top: 5px; margin-bottom:5px; caption-side:top}
+table {margin-top: 5px; margin-bottom:5px}
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer" style="padding-top:160px"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitaftercaption-9.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height:5px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+caption {margin-top: 5px; margin-bottom:5px; caption-side:bottom}
+table {margin-top: 5px; margin-bottom:5px}
+tfoot div.spacer {border-color:orange;}
+tbody div.spacer{border-width: 4px}	
+</style>
+</head>
+<body>
+
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer" style="padding-top:1060px"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+<tfoot><tr><td><div class="spacer"></div></td></tr></tfoot>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitrowgroup-1-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 80px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+</style>
+</head>
+<body>
+<div class=filler></div>
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+</table>
+
+<table cellspacing="0" cellpadding="0" style="page-break-before:always">
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+</table>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/pagination/table-caption-splitrowgroup-1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US" class="reftest-print">
+<head>
+<style type="text/css">
+div.filler {height: 80px; width: 50px; border:thin solid blue;}
+div.spacer { height: 0px; width: 0px; padding: 20px;border:thin solid green;}
+</style>
+</head>
+<body>
+<div class=filler></div>
+<table cellspacing="0" cellpadding="0">
+<caption><div class="spacer"></div></caption>
+<tbody>
+<tr><td><div class="spacer"></div></td></tr>
+<tr><td><div class="spacer"></div></td></tr>
+</tbody>
+</table>
+</body>
+</html>
--- a/layout/reftests/text-overflow/reftest.list
+++ b/layout/reftests/text-overflow/reftest.list
@@ -12,8 +12,9 @@ HTTP(..) == quirks-decorations.html quir
 HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
 HTTP(..) == standards-decorations.html standards-decorations-ref.html
 HTTP(..) == standards-line-height.html standards-line-height-ref.html
 HTTP(..) == selection.html selection-ref.html
 HTTP(..) == marker-shadow.html marker-shadow-ref.html
 == aligned-baseline.html aligned-baseline-ref.html
 skip-if(Android) == clipped-elements.html clipped-elements-ref.html
 == theme-overflow.html theme-overflow-ref.html
+HTTP(..) == table-cell.html table-cell-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/table-cell-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<!--
+    Any copyright is dedicated to the Public Domain.
+    http://creativecommons.org/licenses/publicdomain/
+-->
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+        <title>Test text-overflow:ellipsis on table-cell</title>
+        <style type="text/css">
+@font-face {
+  font-family: DejaVuSansMono;
+  src: url(../fonts/DejaVuSansMono.woff);
+}
+html,body {
+    color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono;
+}
+
+
+            .table {
+                color: black;
+                display: table;
+                table-layout: fixed;
+                height: 5em;
+                width: 5em;
+            }
+            .row {
+                display: table-row;
+            }
+            .cell {
+                display: table-cell;
+                white-space: nowrap;
+                overflow: hidden;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="table">
+            <div class="row">
+                <div class="cell">|||||||&#x2026;</div>
+            </div>
+            <div class="row">
+                <div class="cell"><span>|||||||&#x2026;</span></div>
+            </div>
+        </div>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/table-cell.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<!--
+    Any copyright is dedicated to the Public Domain.
+    http://creativecommons.org/licenses/publicdomain/
+
+    Test: text-overflow:ellipsis on table-cell
+-->
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+        <title>Test text-overflow:ellipsis on table-cell</title>
+        <style type="text/css">
+@font-face {
+  font-family: DejaVuSansMono;
+  src: url(../fonts/DejaVuSansMono.woff);
+}
+html,body {
+    color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono;
+}
+
+            .table {
+                color: black;
+                display: table;
+                table-layout: fixed;
+                height: 5em;
+                width: 5em;
+            }
+            .row {
+                display: table-row;
+            }
+            .cell {
+                display: table-cell;
+                white-space: nowrap;
+                overflow: hidden;
+                text-overflow: ellipsis;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="table">
+            <div class="row">
+                <div class="cell">||||||||||||||</div>
+            </div>
+            <div class="row">
+                <div class="cell"><span>||||||||||||||</span></div>
+            </div>
+        </div>
+</body></html>
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -2824,16 +2824,26 @@ nsTableFrame::ReflowChildren(nsTableRefl
             if (allowRepeatedFooter) {
               PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
             }
             aStatus = NS_FRAME_NOT_COMPLETE;
             PushChildren(rowGroups, childX);
             aLastChildReflowed = prevKidFrame;
             break;
           }
+          else { // we can't push so lets make clear how much space we need
+            PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect,
+                                     oldKidVisualOverflow);
+            aLastChildReflowed = kidFrame;
+            if (allowRepeatedFooter) {
+              PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
+              aLastChildReflowed = tfoot;
+            }
+            break;
+          }
         }
       }
 
       aLastChildReflowed   = kidFrame;
 
       pageBreak = PR_FALSE;
       // see if there is a page break after this row group or before the next one
       if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -1071,16 +1071,47 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPr
   if (mCaptionFrame) {
     nsReflowStatus capStatus; // don't let the caption cause incomplete
     rv = OuterDoReflowChild(aPresContext, mCaptionFrame, *captionRS,
                             captionMet, capStatus);
     if (NS_FAILED(rv)) return rv;
     captionSize.width = captionMet.width;
     captionSize.height = captionMet.height;
     captionMargin = captionRS->mComputedMargin;
+    // Now that we know the height of the caption, reduce the available height
+    // for the table frame if we are height constrained and the caption is above
+    // or below the inner table.
+    if (NS_UNCONSTRAINEDSIZE != aOuterRS.availableHeight) {
+      nscoord captionHeight = 0;
+      switch (captionSide) {
+        case NS_STYLE_CAPTION_SIDE_TOP:
+        case NS_STYLE_CAPTION_SIDE_BOTTOM: {
+          captionHeight = captionSize.height + captionMargin.TopBottom();
+          break;
+        }
+        case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: {
+          nsCollapsingMargin belowCaptionMargin;
+          belowCaptionMargin.Include(captionMargin.bottom);
+          belowCaptionMargin.Include(innerRS->mComputedMargin.top);
+          captionHeight = captionSize.height + captionMargin.top +
+                          belowCaptionMargin.get();
+          break;
+        }
+        case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: {
+          nsCollapsingMargin aboveCaptionMargin;
+          aboveCaptionMargin.Include(captionMargin.top);
+          aboveCaptionMargin.Include(innerRS->mComputedMargin.bottom);
+          captionHeight = captionSize.height + captionMargin.bottom +
+                          aboveCaptionMargin.get();
+          break;
+        }
+      }
+      innerRS->availableHeight =
+        NS_MAX(0, innerRS->availableHeight - captionHeight);
+    }
   } else {
     captionSize.SizeTo(0,0);
     captionMargin.SizeTo(0,0,0,0);
   }
 
   // Then, now that we know how much to reduce the width of the inner
   // table to account for side captions, reflow the inner table.
   nsHTMLReflowMetrics innerMet;
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -258,17 +258,18 @@ LogCookie(nsCookie *aCookie)
 
   if (aCookie) {
     PR_LOG(sCookieLog, PR_LOG_DEBUG,("----------------\n"));
     PR_LOG(sCookieLog, PR_LOG_DEBUG,("name: %s\n", aCookie->Name().get()));
     PR_LOG(sCookieLog, PR_LOG_DEBUG,("value: %s\n", aCookie->Value().get()));
     PR_LOG(sCookieLog, PR_LOG_DEBUG,("%s: %s\n", aCookie->IsDomain() ? "domain" : "host", aCookie->Host().get()));
     PR_LOG(sCookieLog, PR_LOG_DEBUG,("path: %s\n", aCookie->Path().get()));
 
-    PR_ExplodeTime(aCookie->Expiry() * PR_USEC_PER_SEC, PR_GMTParameters, &explodedTime);
+    PR_ExplodeTime(aCookie->Expiry() * PRInt64(PR_USEC_PER_SEC),
+                   PR_GMTParameters, &explodedTime);
     PR_FormatTimeUSEnglish(timeString, 40, "%c GMT", &explodedTime);
     PR_LOG(sCookieLog, PR_LOG_DEBUG,
       ("expires: %s%s", timeString, aCookie->IsSession() ? " (at end of session)" : ""));
 
     PR_ExplodeTime(aCookie->CreationTime(), PR_GMTParameters, &explodedTime);
     PR_FormatTimeUSEnglish(timeString, 40, "%c GMT", &explodedTime);
     PR_LOG(sCookieLog, PR_LOG_DEBUG,("created: %s", timeString));
 
@@ -1538,17 +1539,17 @@ nsCookieService::SetCookieStringInternal
   // to the current time, we must do it here since the current time in
   // SetCookieInternal() will change for each cookie processed (e.g. if the
   // user is prompted).
   PRTime tempServerTime;
   PRInt64 serverTime;
   PRStatus result = PR_ParseTimeString(aServerTime.get(), PR_TRUE,
                                        &tempServerTime);
   if (result == PR_SUCCESS) {
-    serverTime = tempServerTime / PR_USEC_PER_SEC;
+    serverTime = tempServerTime / PRInt64(PR_USEC_PER_SEC);
   } else {
     serverTime = PR_Now() / PR_USEC_PER_SEC;
   }
 
   // process each cookie in the header
   nsDependentCString cookieHeader(aCookieHeader);
   while (SetCookieInternal(aHostURI, baseDomain, requireHostMatch,
                            cookieStatus, cookieHeader, serverTime, aFromHttp)) {
@@ -3268,17 +3269,17 @@ nsCookieService::GetExpiry(nsCookieAttri
   } else if (!aCookieAttributes.expires.IsEmpty()) {
     PRTime expires;
 
     // parse expiry time
     if (PR_ParseTimeString(aCookieAttributes.expires.get(), PR_TRUE, &expires) != PR_SUCCESS) {
       return PR_TRUE;
     }
 
-    delta = expires / PR_USEC_PER_SEC - aServerTime;
+    delta = expires / PRInt64(PR_USEC_PER_SEC) - aServerTime;
 
   // default to session cookie if no attributes found
   } else {
     return PR_TRUE;
   }
 
   // if this addition overflows, expiryTime will be less than currentTime
   // and the cookie will be expired - that's okay.
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_bug667818.js
@@ -0,0 +1,17 @@
+function makeURI(str) {
+    return Components.classes["@mozilla.org/network/io-service;1"]
+                     .getService(Components.interfaces.nsIIOService)
+                     .newURI(str, null, null);
+}
+
+function run_test() {
+    var serv =   Components.classes["@mozilla.org/cookieService;1"]
+                           .getService(Components.interfaces.nsICookieService);
+    var uri = makeURI("http://example.com/");
+    // Try an expiration time before the epoch
+    serv.setCookieString(uri, null, "test=test; path=/; domain=example.com; expires=Sun, 31-Dec-1899 16:00:00 GMT;", null);
+    do_check_eq(serv.getCookieString(uri, null), null);
+    // Now sanity check
+    serv.setCookieString(uri, null, "test2=test2; path=/; domain=example.com;", null);
+    do_check_eq(serv.getCookieString(uri, null), "test2=test2");
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -66,16 +66,17 @@ tail =
 [test_bug654926.js]
 [test_bug654926_doom_and_read.js]
 [test_bug654926_test_seek.js]
 [test_bug659569.js]
 [test_bug660066.js]
 [test_bug651185.js]
 [test_bug667907.js]
 [test_bug670333.js]
+[test_bug667818.js]
 [test_cacheflags.js]
 [test_channel_close.js]
 [test_compareURIs.js]
 [test_content_sniffer.js]
 [test_cookie_header.js]
 [test_data_protocol.js]
 [test_dns_service.js]
 [test_duplicate_headers.js]
--- a/parser/htmlparser/tests/mochitest/file_bug568470-script.sjs
+++ b/parser/htmlparser/tests/mochitest/file_bug568470-script.sjs
@@ -1,14 +1,16 @@
+var timer = null; // Declare outside to prevent premature GC
+
 function handleRequest(request, response)
 {
   response.setHeader("Cache-Control", "no-cache", false);
   response.setHeader("Content-Type", "text/javascript", false);
   response.write("var i = 0;");
   response.bodyOutputStream.flush();
   response.processAsync();
-  var timer = Components.classes["@mozilla.org/timer;1"]
+  timer = Components.classes["@mozilla.org/timer;1"]
     .createInstance(Components.interfaces.nsITimer);
   timer.initWithCallback(function() {
       response.finish();
     }, 500, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
 }
 
--- a/parser/htmlparser/tests/mochitest/file_bug568470.sjs
+++ b/parser/htmlparser/tests/mochitest/file_bug568470.sjs
@@ -1,19 +1,21 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
 function handleRequest(request, response)
 {
   response.setHeader("Cache-Control", "no-cache", false);
   response.setHeader("Content-Type", "text/html", false);
   response.write("<script src='file_bug568470-script.sjs'></script>");
   response.write("<div id='flushable'>");
   for (var i = 0; i < 2000; i++) { 
     response.write("Lorem ipsum dolor sit amet. ");
   }
   response.write("</div>");
   response.bodyOutputStream.flush();
   response.processAsync();
-  var timer = Components.classes["@mozilla.org/timer;1"]
+  timer = Components.classes["@mozilla.org/timer;1"]
     .createInstance(Components.interfaces.nsITimer);
   timer.initWithCallback(function() {
       response.finish();
     }, 1200, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
 }
 
--- a/storage/src/TelemetryVFS.cpp
+++ b/storage/src/TelemetryVFS.cpp
@@ -32,19 +32,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include <string.h>
 #include "mozilla/Telemetry.h"
 #include "sqlite3.h"
-#include <string.h>
+#include "nsThreadUtils.h"
 
 namespace {
 
 using namespace mozilla;
 
 struct Histograms {
   const char *name;
   Telemetry::ID readB;
@@ -69,16 +70,37 @@ Histograms gHistograms[] = {
    Telemetry::MOZ_SQLITE_COOKIES_SYNC },
 
   {NULL,
    Telemetry::MOZ_SQLITE_OTHER_READ_B,
    Telemetry::MOZ_SQLITE_OTHER_WRITE_B,
    Telemetry::MOZ_SQLITE_OTHER_SYNC }
 };
 
+
+/** RAII class for measuring how long io takes on/off main thread */
+class IOThreadAutoTimer {
+public:
+  IOThreadAutoTimer(MOZILLA_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+    : start(TimeStamp::Now())
+  {
+    MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
+  }
+
+  ~IOThreadAutoTimer() {
+    Accumulate(NS_IsMainThread() ? Telemetry::MOZ_SQLITE_MAIN_THREAD_WAIT_MS
+               : Telemetry::MOZ_SQLITE_OTHER_THREAD_WAIT_MS
+               , (TimeStamp::Now() - start).ToMilliseconds());
+  }
+
+private:
+  const TimeStamp start;
+  MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
 struct telemetry_file {
   sqlite3_file base;        // Base class.  Must be first
   Histograms *histograms;   // histograms pertaining to this file
   sqlite3_file pReal[1];    // This contains the vfs that actually does work
 };
 
 /*
 ** Close a telemetry_file.
@@ -97,59 +119,63 @@ xClose(sqlite3_file *pFile)
 }
 
 /*
 ** Read data from a telemetry_file.
 */
 int
 xRead(sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst)
 {
+  IOThreadAutoTimer ioTimer;
   telemetry_file *p = (telemetry_file *)pFile;
   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_READ_MS> timer;
   int rc;
   rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
   // sqlite likes to read from empty files, this is normal, ignore it.
   if (rc != SQLITE_IOERR_SHORT_READ)
     Telemetry::Accumulate(p->histograms->readB, rc == SQLITE_OK ? iAmt : 0);
   return rc;
 }
 
 /*
 ** Write data to a telemetry_file.
 */
 int
 xWrite(sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst)
 {
+  IOThreadAutoTimer ioTimer;
   telemetry_file *p = (telemetry_file *)pFile;
   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_WRITE_MS> timer;
   int rc;
   rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
   Telemetry::Accumulate(p->histograms->writeB, rc == SQLITE_OK ? iAmt : 0);
   return rc;
 }
 
 /*
 ** Truncate a telemetry_file.
 */
 int
 xTruncate(sqlite3_file *pFile, sqlite_int64 size)
 {
+  IOThreadAutoTimer ioTimer;
   telemetry_file *p = (telemetry_file *)pFile;
   int rc;
   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_TRUNCATE> timer;
   rc = p->pReal->pMethods->xTruncate(p->pReal, size);
   return rc;
 }
 
 /*
 ** Sync a telemetry_file.
 */
 int
 xSync(sqlite3_file *pFile, int flags)
 {
+  IOThreadAutoTimer ioTimer;
   telemetry_file *p = (telemetry_file *)pFile;
   const TimeStamp start = TimeStamp::Now();
   int rc = p->pReal->pMethods->xSync(p->pReal, flags);
   Telemetry::Accumulate(p->histograms->syncMs, static_cast<PRUint32>((TimeStamp::Now() - start).ToMilliseconds()));
   return rc;
 }
 
 /*
@@ -266,16 +292,17 @@ xShmUnmap(sqlite3_file *pFile, int delFl
   rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
   return rc;
 }
  
 int
 xOpen(sqlite3_vfs* vfs, const char *zName, sqlite3_file* pFile,
           int flags, int *pOutFlags)
 {
+  IOThreadAutoTimer ioTimer;
   Telemetry::AutoTimer<Telemetry::MOZ_SQLITE_OPEN> timer;
   sqlite3_vfs *orig_vfs = static_cast<sqlite3_vfs*>(vfs->pAppData);
   int rc;
   telemetry_file *p = (telemetry_file *)pFile;
   Histograms *h = NULL;
   // check if the filename is one we are probing for
   for(size_t i = 0;i < sizeof(gHistograms)/sizeof(gHistograms[0]);i++) {
     h = &gHistograms[i];
--- a/testing/mozmill/tests/shared-modules/testModalDialogAPI.js
+++ b/testing/mozmill/tests/shared-modules/testModalDialogAPI.js
@@ -95,16 +95,17 @@ var mdObserver = {
  *        The callback handler to use to interact with the modal dialog
  */
 function modalDialog(callback)
 {
   this.observer = mdObserver;
   this.observer.handler = callback;
   this.observer.startTimer = this.start;
   this.observer.docFinder = this.getDialog;
+  this.modalDialogTimer = null; // put timer in class def so it doesn't get GC'ed
 }
 
 /**
  * Set a new callback handler.
  *
  * @param {function} callback
  *        The callback handler to use to interact with the modal dialog
  */
@@ -120,29 +121,29 @@ modalDialog.prototype.setHandler = funct
  *        Initial delay before the observer gets called
  * @param {object} observer
  *        (Optional) Observer for modal dialog checks
  */
 modalDialog.prototype.start = function modalDialog_start(delay, observer)
 {
   const dialogDelay = (delay == undefined) ? 100 : delay;
 
-  var modalDialogTimer = Cc["@mozilla.org/timer;1"].
+  this.modalDialogTimer = Cc["@mozilla.org/timer;1"].
                          createInstance(Ci.nsITimer);
 
   // If we are not called from the observer, we have to use the supplied
   // observer instead of this.observer
   if (observer) {
-    modalDialogTimer.init(observer,
-                          dialogDelay,
-                          Ci.nsITimer.TYPE_ONE_SHOT);
+    this.modalDialogTimer.init(observer,
+                               dialogDelay,
+                               Ci.nsITimer.TYPE_ONE_SHOT);
   } else {
-    modalDialogTimer.init(this.observer,
-                          dialogDelay,
-                          Ci.nsITimer.TYPE_ONE_SHOT);
+    this.modalDialogTimer.init(this.observer,
+                               dialogDelay,
+                               Ci.nsITimer.TYPE_ONE_SHOT);
   }
 }
 
 /**
  * Check if the modal dialog has been opened
  *
  * @private
  * @return Returns if the modal dialog has been found or not
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -565,18 +565,18 @@ class XPCShellTests(object):
       self.failCount = 1
 
     self.log.info("""INFO | Result summary:
 INFO | Passed: %d
 INFO | Failed: %d
 INFO | Todo: %d""" % (self.passCount, self.failCount, self.todoCount))
 
     if gotSIGINT and not keepGoing:
-      log.error("TEST-UNEXPECTED-FAIL | Received SIGINT (control-C), so stopped run. " \
-            "(Use --keep-going to keep running tests after killing one with SIGINT)")
+      self.log.error("TEST-UNEXPECTED-FAIL | Received SIGINT (control-C), so stopped run. " \
+                     "(Use --keep-going to keep running tests after killing one with SIGINT)")
       return False
     return self.failCount == 0
 
 class XPCShellOptions(OptionParser):
   def __init__(self):
     """Process command line arguments and call runTests() to do the real work."""
     OptionParser.__init__(self)
 
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -98,26 +98,28 @@ HISTOGRAM(HTTP_REQUEST_PER_PAGE_FROM_CAC
 
 HTTP_HISTOGRAMS(PAGE, "page: ")
 HTTP_HISTOGRAMS(SUB, "subitem: ")
 
 #undef _HTTP_HIST
 #undef HTTP_HISTOGRAMS
 HISTOGRAM(FIND_PLUGINS, 1, 3000, 10, EXPONENTIAL, "Time spent scanning filesystem for plugins (ms)")
 HISTOGRAM(CHECK_JAVA_ENABLED, 1, 3000, 10, EXPONENTIAL, "Time spent checking if Java is enabled (ms)")
-HISTOGRAM(MOZ_SQLITE_OPEN, 1, 3000, 10, EXPONENTIAL, "Time spent on sqlite open() (ms)")
-HISTOGRAM(MOZ_SQLITE_READ_MS, 1, 3000, 10, EXPONENTIAL, "Time spent on sqlite read() (ms)")
-HISTOGRAM(MOZ_SQLITE_OTHER_READ_B, 1, 32768, 3, LINEAR, "Sqlite read() (bytes)")
-HISTOGRAM(MOZ_SQLITE_PLACES_READ_B, 1, 32768, 3, LINEAR, "Sqlite read() (bytes)")
-HISTOGRAM(MOZ_SQLITE_COOKIES_READ_B, 1, 32768, 3, LINEAR, "Sqlite read() (bytes)")
-HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_READ_B, 1, 32768, 3, LINEAR, "Sqlite read() (bytes)")
-HISTOGRAM(MOZ_SQLITE_WRITE_MS, 1, 3000, 10, EXPONENTIAL, "Time spent on sqlite write() (ms)")
-HISTOGRAM(MOZ_SQLITE_PLACES_WRITE_B, 1, 32768, 3, LINEAR, "Sqlite write (bytes)")
-HISTOGRAM(MOZ_SQLITE_COOKIES_WRITE_B, 1, 32768, 3, LINEAR, "Sqlite write (bytes)")
-HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_WRITE_B, 1, 32768, 3, LINEAR, "Sqlite write (bytes)")
-HISTOGRAM(MOZ_SQLITE_OTHER_WRITE_B, 1, 32768, 3, LINEAR, "Sqlite write (bytes)")
-HISTOGRAM(MOZ_SQLITE_TRUNCATE, 1, 3000, 10, EXPONENTIAL, "Time spent on sqlite truncate() (ms)")
-HISTOGRAM(MOZ_SQLITE_PLACES_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on sqlite fsync() (ms)")
-HISTOGRAM(MOZ_SQLITE_COOKIES_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on sqlite fsync() (ms)")
-HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on sqlite fsync() (ms)")
-HISTOGRAM(MOZ_SQLITE_OTHER_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on sqlite fsync() (ms)")
+HISTOGRAM(MOZ_SQLITE_OPEN, 1, 3000, 10, EXPONENTIAL, "Time spent on SQLite open() (ms)")
+HISTOGRAM(MOZ_SQLITE_READ_MS, 1, 3000, 10, EXPONENTIAL, "Time spent on SQLite read() (ms)")
+HISTOGRAM(MOZ_SQLITE_OTHER_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)")
+HISTOGRAM(MOZ_SQLITE_PLACES_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)")
+HISTOGRAM(MOZ_SQLITE_COOKIES_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)")
+HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_READ_B, 1, 32768, 3, LINEAR, "SQLite read() (bytes)")
+HISTOGRAM(MOZ_SQLITE_WRITE_MS, 1, 3000, 10, EXPONENTIAL, "Time spent on SQLite write() (ms)")
+HISTOGRAM(MOZ_SQLITE_PLACES_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)")
+HISTOGRAM(MOZ_SQLITE_COOKIES_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)")
+HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)")
+HISTOGRAM(MOZ_SQLITE_OTHER_WRITE_B, 1, 32768, 3, LINEAR, "SQLite write (bytes)")
+HISTOGRAM(MOZ_SQLITE_TRUNCATE, 1, 3000, 10, EXPONENTIAL, "Time spent on SQLite truncate() (ms)")
+HISTOGRAM(MOZ_SQLITE_PLACES_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on SQLite fsync() (ms)")
+HISTOGRAM(MOZ_SQLITE_COOKIES_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on SQLite fsync() (ms)")
+HISTOGRAM(MOZ_SQLITE_URLCLASSIFIER_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on SQLite fsync() (ms)")
+HISTOGRAM(MOZ_SQLITE_OTHER_SYNC, 1, 10000, 10, EXPONENTIAL, "Time spent on SQLite fsync() (ms)")
 HISTOGRAM(STARTUP_MEASUREMENT_ERRORS, 1, 3, 4, LINEAR, "Flags errors in startup calculation()")
 HISTOGRAM(NETWORK_DISK_CACHE_OPEN, 1, 10000, 10, EXPONENTIAL, "Time spent opening disk cache (ms)")
+HISTOGRAM(MOZ_SQLITE_MAIN_THREAD_WAIT_MS, 1, 3000, 10, EXPONENTIAL, "Time spent waiting on SQLite IO on main thread (ms)")
+HISTOGRAM(MOZ_SQLITE_OTHER_THREAD_WAIT_MS, 1, 3000, 10, EXPONENTIAL, "Time spent waiting on SQLite IO off main thread (ms)")
--- a/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
+++ b/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
@@ -281,20 +281,23 @@ function runNextTest()
 }
 
 function runTests(tests)
 {
   gTests = tests;
   runNextTest();
 }
 
+var timerArray = [];
+
 function Timer(delay, cb) {
   this.cb = cb;
   var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   timer.initWithCallback(this, delay, timer.TYPE_ONE_SHOT);
+  timerArray.push(timer);
 }
 
 Timer.prototype = {
 QueryInterface: function(iid) {
     if (!iid.equals(Ci.nsISupports) && !iid.equals(Ci.nsITimerCallback)) {
       throw Cr.NS_ERROR_NO_INTERFACE;
     }
     return this;
--- a/toolkit/mozapps/downloads/tests/chrome/test_space_key_pauses_resumes.xul
+++ b/toolkit/mozapps/downloads/tests/chrome/test_space_key_pauses_resumes.xul
@@ -59,16 +59,17 @@
   <script type="application/javascript">
   <![CDATA[
 
 function bug413985obs(aWin)
 {
   this.mWin = aWin;
   this.wasPaused = false;
   this.wasResumed = false;
+  this.timer = null; // timer declared here to prevent premature GC 
 }
 bug413985obs.prototype = {
   observe: function(aSubject, aTopic, aData)
   {
     if ("timer-callback" == aTopic) {
       // dispatch a space keypress to resume the download
       synthesizeKey(" ", {}, this.mWin);
     }
@@ -83,18 +84,18 @@ bug413985obs.prototype = {
       synthesizeKey(" ", {}, this.mWin);
     }
 
     if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_PAUSED &&
         !this.wasResumed) {
       this.wasResumed = true;
       // We have to do this on a timer so other JS stuff that handles the UI
       // can actually catch up to us...
-      var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-      timer.init(this, 0, Ci.nsITimer.TYPE_ONE_SHOT);
+      this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+      this.timer.init(this, 0, Ci.nsITimer.TYPE_ONE_SHOT);
     }
 
     if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED) {
       ok(this.wasPaused && this.wasResumed,
          "The download was paused, and then resumed to completion");
       aDownload.targetFile.remove(false);
 
       var dm = Cc["@mozilla.org/download-manager;1"].
--- a/toolkit/themes/pinstripe/global/shared.inc
+++ b/toolkit/themes/pinstripe/global/shared.inc
@@ -22,12 +22,14 @@
 %define sidebarItemGraphiteFocusedBorderTop 1px solid #6B798D
 %define sidebarItemGraphiteFocusedBackground -moz-linear-gradient(top, #8293A6, #425972) repeat-x
 %define sidebarItemInactiveBorderTop 1px solid #979797
 %define sidebarItemInactiveBackground -moz-linear-gradient(top, #B4B4B4, #8A8A8A) repeat-x
 
 %define toolbarbuttonBorderColor rgba(59, 59, 59, 0.9)
 %define toolbarbuttonCornerRadius 3px
 %define toolbarbuttonBackground -moz-linear-gradient(top, #FFF, #ADADAD) repeat-x
+%define toolbarbuttonFocusedBorderColorAqua rgba(102, 122, 155, 0.9)
+%define toolbarbuttonFocusedBorderColorGraphite rgba(59, 59, 59, 0.7)
 %define toolbarbuttonPressedInnerShadow inset rgba(0, 0, 0, 0.3) 0 -6px 10px, inset #000 0 1px 3px, inset rgba(0, 0, 0, 0.2) 0 1px 3px
 %define toolbarbuttonPressedBackgroundColor #B5B5B5
 %define toolbarbuttonInactiveBorderColor rgba(146, 146, 146, 0.84)
 %define toolbarbuttonInactiveBackgroundImage -moz-linear-gradient(top, #FFF, #CCC)
--- a/toolkit/themes/pinstripe/mozapps/downloads/downloads.css
+++ b/toolkit/themes/pinstripe/mozapps/downloads/downloads.css
@@ -125,12 +125,21 @@ richlistitem[type="download"] button {
 }
 
 #clearListButton:hover:active:not([disabled="true"]) {
   background: @toolbarbuttonPressedBackgroundColor@;
   text-shadow: @loweredShadow@;
   box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
 }
 
+#clearListButton:-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorAqua@;
+  box-shadow: @focusRingShadow@;
+}
+
+#clearListButton:-moz-system-metric(mac-graphite-theme):-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorGraphite@;
+}
+
 #clearListButton:-moz-window-inactive {
   border-color: @toolbarbuttonInactiveBorderColor@;
   background-image: @toolbarbuttonInactiveBackgroundImage@;
 }
--- a/toolkit/themes/pinstripe/mozapps/update/updates.css
+++ b/toolkit/themes/pinstripe/mozapps/update/updates.css
@@ -52,16 +52,25 @@ wizardpage {
 }
 
 .wizard-buttons button:hover:active:not([disabled="true"]) {
   background: @toolbarbuttonPressedBackgroundColor@;
   text-shadow: @loweredShadow@;
   box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
 }
 
+.wizard-buttons button:-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorAqua@;
+  box-shadow: @focusRingShadow@;
+}
+
+.wizard-buttons button:-moz-system-metric(mac-graphite-theme):-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorGraphite@;
+}
+
 .wizard-buttons button:-moz-window-inactive {
   border-color: @toolbarbuttonInactiveBorderColor@;
   background-image: @toolbarbuttonInactiveBackgroundImage@;
 }
 
 .loadingBox {
   padding: 3px 5px 3px 5px;
 }
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -61,29 +61,29 @@ nsRunnable::Run()
   return NS_OK;
 }
 
 #endif  // XPCOM_GLUE_AVOID_NSPR
 
 //-----------------------------------------------------------------------------
 
 NS_METHOD
-NS_NewThread(nsIThread **result, nsIRunnable *event)
+NS_NewThread(nsIThread **result, nsIRunnable *event, PRUint32 stackSize)
 {
   nsCOMPtr<nsIThread> thread;
 #ifdef MOZILLA_INTERNAL_API
   nsresult rv = nsThreadManager::get()->
-      nsThreadManager::NewThread(0, getter_AddRefs(thread));
+      nsThreadManager::NewThread(0, stackSize, getter_AddRefs(thread));
 #else
   nsresult rv;
   nsCOMPtr<nsIThreadManager> mgr =
       do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = mgr->NewThread(0, getter_AddRefs(thread));
+  rv = mgr->NewThread(0, stackSize, getter_AddRefs(thread));
 #endif
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (event) {
     rv = thread->Dispatch(event, NS_DISPATCH_NORMAL);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -70,22 +70,26 @@
 
 /**
  * Create a new thread, and optionally provide an initial event for the thread.
  *
  * @param result
  *   The resulting nsIThread object.
  * @param initialEvent
  *   The initial event to run on this thread.  This parameter may be null.
+ * @param stackSize
+ *   The size in bytes to reserve for the thread's stack.
  *
  * @returns NS_ERROR_INVALID_ARG
  *   Indicates that the given name is not unique.
  */
 extern NS_COM_GLUE NS_METHOD
-NS_NewThread(nsIThread **result, nsIRunnable *initialEvent = nsnull);
+NS_NewThread(nsIThread **result,
+             nsIRunnable *initialEvent = nsnull,
+             PRUint32 stackSize = nsIThreadManager::DEFAULT_STACK_SIZE);
 
 /**
  * Get a reference to the current thread.
  *
  * @param result
  *   The resulting nsIThread object.
  */
 extern NS_COM_GLUE NS_METHOD
--- a/xpcom/threads/nsIThreadManager.idl
+++ b/xpcom/threads/nsIThreadManager.idl
@@ -40,30 +40,38 @@
 
 [ptr] native PRThread(PRThread);
 
 interface nsIThread;
 
 /**
  * An interface for creating and locating nsIThread instances.
  */
-[scriptable, uuid(487c10bf-0a22-4148-89fa-790d819dd559)]
+[scriptable, uuid(2bbbc38c-cf96-4099-ba6b-f6a44d8b014c)]
 interface nsIThreadManager : nsISupports
 {
   /**
+   * Default number of bytes reserved for a thread's stack, if no stack size
+   * is specified in newThread(). 0 means use platform default.
+   */
+  const unsigned long DEFAULT_STACK_SIZE = 0;
+
+  /**
    * Create a new thread (a global, user PRThread).
    *
    * @param creationFlags
    *   Reserved for future use.  Pass 0.
+   * @param stackSize
+   *   Number of bytes to reserve for the thread's stack.
    *
    * @returns
    *   The newly created nsIThread object.
    */
-  nsIThread newThread(in unsigned long creationFlags);
-   
+  nsIThread newThread(in unsigned long creationFlags, [optional] in unsigned long stackSize);
+
   /**
    * Get the nsIThread object (if any) corresponding to the given PRThread.
    * This method returns null if there is no corresponding nsIThread.
    *
    * @param prthread
    *   The PRThread of the nsIThread being requested.
    *
    * @returns
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -307,16 +307,30 @@ nsThread::ThreadFunc(void *arg)
 //-----------------------------------------------------------------------------
 
 nsThread::nsThread()
   : mLock("nsThread.mLock")
   , mEvents(&mEventsRoot)
   , mPriority(PRIORITY_NORMAL)
   , mThread(nsnull)
   , mRunningEvent(0)
+  , mStackSize(0)
+  , mShutdownContext(nsnull)
+  , mShutdownRequired(PR_FALSE)
+  , mEventsAreDoomed(PR_FALSE)
+{
+}
+
+nsThread::nsThread(PRUint32 aStackSize)
+  : mLock("nsThread.mLock")
+  , mEvents(&mEventsRoot)
+  , mPriority(PRIORITY_NORMAL)
+  , mThread(nsnull)
+  , mRunningEvent(0)
+  , mStackSize(aStackSize)
   , mShutdownContext(nsnull)
   , mShutdownRequired(PR_FALSE)
   , mEventsAreDoomed(PR_FALSE)
 {
 }
 
 nsThread::~nsThread()
 {
@@ -331,17 +345,17 @@ nsThread::Init()
  
   NS_ADDREF_THIS();
  
   mShutdownRequired = PR_TRUE;
 
   // ThreadFunc is responsible for setting mThread
   PRThread *thr = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
                                   PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
-                                  PR_JOINABLE_THREAD, 0);
+                                  PR_JOINABLE_THREAD, mStackSize);
   if (!thr) {
     NS_RELEASE_THIS();
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // ThreadFunc will wait for this event to be run before it tries to access
   // mThread.  By delaying insertion of this event into the queue, we ensure
   // that mThread is set properly.
--- a/xpcom/threads/nsThread.h
+++ b/xpcom/threads/nsThread.h
@@ -53,16 +53,17 @@ class nsThread : public nsIThreadInterna
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIEVENTTARGET
   NS_DECL_NSITHREAD
   NS_DECL_NSITHREADINTERNAL
   NS_DECL_NSISUPPORTSPRIORITY
 
   nsThread();
+  nsThread(PRUint32 aStackSize);
 
   // Initialize this as a wrapper for a new PRThread.
   nsresult Init();
 
   // Initialize this as a wrapper for the current PRThread.
   nsresult InitCurrentThread();
 
   // The PRThread corresponding to this thread.
@@ -133,16 +134,17 @@ private:
   nsAutoTObserverArray<nsCOMPtr<nsIThreadObserver>, 2> mEventObservers;
 
   nsChainedEventQueue *mEvents;   // never null
   nsChainedEventQueue  mEventsRoot;
 
   PRInt32   mPriority;
   PRThread *mThread;
   PRUint32  mRunningEvent;  // counter
+  PRUint32  mStackSize;
 
   struct nsThreadShutdownContext *mShutdownContext;
 
   PRPackedBool mShutdownRequired;
   PRPackedBool mShutdownPending;
   // Set to true when events posted to this thread will never run.
   PRPackedBool mEventsAreDoomed;
 };
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -227,22 +227,24 @@ nsThreadManager::GetCurrentThread()
   nsRefPtr<nsThread> thread = new nsThread();
   if (!thread || NS_FAILED(thread->InitCurrentThread()))
     return nsnull;
 
   return thread.get();  // reference held in TLS
 }
 
 NS_IMETHODIMP
-nsThreadManager::NewThread(PRUint32 creationFlags, nsIThread **result)
+nsThreadManager::NewThread(PRUint32 creationFlags,
+                           PRUint32 stackSize,
+                           nsIThread **result)
 {
   // No new threads during Shutdown
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
-  nsThread *thr = new nsThread();
+  nsThread *thr = new nsThread(stackSize);
   if (!thr)
     return NS_ERROR_OUT_OF_MEMORY;
   NS_ADDREF(thr);
 
   nsresult rv = thr->Init();
   if (NS_FAILED(rv)) {
     NS_RELEASE(thr);
     return rv;
--- a/xpcom/threads/nsThreadPool.cpp
+++ b/xpcom/threads/nsThreadPool.cpp
@@ -105,17 +105,19 @@ nsThreadPool::PutEvent(nsIRunnable *even
     mEvents.PutEvent(event);
   }
 
   LOG(("THRD-P(%p) put [spawn=%d]\n", this, spawnThread));
   if (!spawnThread)
     return NS_OK;
 
   nsCOMPtr<nsIThread> thread;
-  nsThreadManager::get()->NewThread(0, getter_AddRefs(thread));
+  nsThreadManager::get()->NewThread(0,
+                                    nsIThreadManager::DEFAULT_STACK_SIZE,
+                                    getter_AddRefs(thread));
   NS_ENSURE_STATE(thread);
 
   PRBool killThread = PR_FALSE;
   {
     ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
     if (mThreads.Count() < (PRInt32) mThreadLimit) {
       mThreads.AppendObject(thread);
     } else {