Merge latest green fx-team changeset and mozilla-central
authorEd Morley <emorley@mozilla.com>
Mon, 09 Sep 2013 13:13:11 +0100
changeset 146137 218d4334d29e5d55bcb70498bb66228d8b4463c5
parent 146136 81f13346eb7ca2ea12d046230eab8e6ad82ab544 (current diff)
parent 146121 5b97d9cfe8900634acfcd4448237ecf9b7b87e61 (diff)
child 146150 b1f2748e657cb7e72de1c6b91f930b5ea1faac24
child 146174 11abb5d7d409884e5df82889f7f24d9636919493
child 146207 3d50a4b732af31f5d607be382b26c70bb5092913
child 155722 c44d006da6bd4d478229616d185c4d2cdcd691ee
push id25242
push useremorley@mozilla.com
push dateMon, 09 Sep 2013 12:13:52 +0000
treeherdermozilla-central@218d4334d29e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge latest green fx-team changeset and mozilla-central
content/media/omx/MP3FrameParser.cpp
content/media/omx/MP3FrameParser.h
dom/base/nsDOMException.cpp
dom/base/nsDOMException.h
dom/workers/Exceptions.cpp
dom/workers/Exceptions.h
js/xpconnect/src/XPCStack.cpp
xpcom/base/nsExceptionService.cpp
xpcom/base/nsExceptionService.h
xpcom/base/nsIExceptionService.idl
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "0bfd8f0e9f4a8ee91237545603cc8a216518de18", 
+    "revision": "627f494cb7b6eb49057434711d1070341430b367", 
     "repo_path": "/integration/gaia-central"
 }
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -388,34 +388,34 @@ Element::WrapObject(JSContext *aCx, JS::
     return obj;
   }
 
   // Make sure the style context goes away _before_ we load the binding
   // since that can destroy the relevant presshell.
   mozilla::css::URLValue *bindingURL;
   bool ok = GetBindingURL(doc, &bindingURL);
   if (!ok) {
-    dom::Throw<true>(aCx, NS_ERROR_FAILURE);
+    dom::Throw(aCx, NS_ERROR_FAILURE);
     return nullptr;
   }
 
   if (!bindingURL) {
     // No binding, nothing left to do here.
     return obj;
   }
 
   nsCOMPtr<nsIURI> uri = bindingURL->GetURI();
   nsCOMPtr<nsIPrincipal> principal = bindingURL->mOriginPrincipal;
 
   // We have a binding that must be installed.
   bool dummy;
 
   nsXBLService* xblService = nsXBLService::GetInstance();
   if (!xblService) {
-    dom::Throw<true>(aCx, NS_ERROR_NOT_AVAILABLE);
+    dom::Throw(aCx, NS_ERROR_NOT_AVAILABLE);
     return nullptr;
   }
 
   nsRefPtr<nsXBLBinding> binding;
   xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding), &dummy);
   
   if (binding) {
     if (nsContentUtils::IsSafeToRunScript()) {
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -84,17 +84,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(EventSour
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(EventSource)
   bool isBlack = tmp->IsBlack();
   if (isBlack || tmp->mWaitingForOnStopRequest) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
-      xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
+      // This marks the wrapper black.
+      tmp->GetWrapper();
     }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(EventSource)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -1216,17 +1216,19 @@ FragmentOrElement::MarkUserDataHandler(v
 {
   xpc_TryUnmarkWrappedGrayObject(static_cast<nsISupports*>(aChild));
 }
 
 void
 FragmentOrElement::MarkNodeChildren(nsINode* aNode)
 {
   JSObject* o = GetJSObjectChild(aNode);
-  xpc_UnmarkGrayObject(o);
+  if (o) {
+    JS::ExposeObjectToActiveJS(o);
+  }
 
   nsEventListenerManager* elm = aNode->GetListenerManager(false);
   if (elm) {
     elm->MarkForCC();
   }
 
   if (aNode->HasProperties()) {
     nsIDocument* ownerDoc = aNode->OwnerDoc();
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -20,16 +20,17 @@ LOCAL_INCLUDES += \
   -I$(topsrcdir)/content/xbl/src \
   -I$(topsrcdir)/content/xml/content/src \
   -I$(topsrcdir)/content/xml/document/src \
   -I$(topsrcdir)/content/xslt/src/xpath \
   -I$(topsrcdir)/content/xul/content/src \
   -I$(topsrcdir)/content/xul/document/src \
   -I$(topsrcdir)/dom/base \
   -I$(topsrcdir)/dom/ipc \
+  -I$(topsrcdir)/dom/workers \
   -I$(topsrcdir)/js/ipc \
   -I$(topsrcdir)/image/src \
   -I$(topsrcdir)/js/xpconnect/src \
   -I$(topsrcdir)/layout/base \
   -I$(topsrcdir)/layout/generic \
   -I$(topsrcdir)/layout/style \
   -I$(topsrcdir)/layout/svg \
   -I$(topsrcdir)/layout/xul/base/src \
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -576,17 +576,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(WebSocket
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(WebSocket)
   bool isBlack = tmp->IsBlack();
   if (isBlack|| tmp->mKeepingAlive) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
-      xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
+      // This marks the wrapper black.
+      tmp->GetWrapper();
     }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(WebSocket)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5180,23 +5180,25 @@ nsContentUtils::GetContextForEventHandle
 
   return nullptr;
 }
 
 /* static */
 JSContext *
 nsContentUtils::GetCurrentJSContext()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   return sXPConnect->GetCurrentJSContext();
 }
 
 /* static */
 JSContext *
 nsContentUtils::GetSafeJSContext()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   return sXPConnect->GetSafeJSContext();
 }
 
 /* static */
 nsresult
 nsContentUtils::ASCIIToLower(nsAString& aStr)
 {
   PRUnichar* iter = aStr.BeginWriting();
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -11321,17 +11321,17 @@ nsIDocument::WrapObject(JSContext *aCx, 
   JS::Rooted<JS::Value> winVal(aCx);
   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   nsresult rv = nsContentUtils::WrapNative(aCx, obj, win,
                                            &NS_GET_IID(nsIDOMWindow),
                                            winVal.address(),
                                            getter_AddRefs(holder),
                                            false);
   if (NS_FAILED(rv)) {
-    Throw<true>(aCx, rv);
+    Throw(aCx, rv);
     return nullptr;
   }
 
   NS_NAMED_LITERAL_STRING(doc_str, "document");
 
   if (!JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(winVal),
                            reinterpret_cast<const jschar *>
                                            (doc_str.get()),
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -2468,17 +2468,17 @@ nsINode::WrapObject(JSContext *aCx, JS::
   // Event handling is possible only if (1). If (2) event handling is
   // prevented.
   // If the document has never had a script handling object, untrusted
   // scripts (3) shouldn't touch it!
   bool hasHadScriptHandlingObject = false;
   if (!OwnerDoc()->GetScriptHandlingObject(hasHadScriptHandlingObject) &&
       !hasHadScriptHandlingObject &&
       !nsContentUtils::IsCallerChrome()) {
-    Throw<true>(aCx, NS_ERROR_UNEXPECTED);
+    Throw(aCx, NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   JS::Rooted<JSObject*> obj(aCx, WrapNode(aCx, aScope));
   if (obj && ChromeOnlyAccess() &&
       !nsContentUtils::IsSystemPrincipal(NodePrincipal()) &&
       xpc::AllowXBLScope(js::GetObjectCompartment(obj)))
   {
--- a/content/base/src/nsInProcessTabChildGlobal.h
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -15,22 +15,24 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIClassInfo.h"
 #include "nsIDocShell.h"
 #include "nsIDOMElement.h"
 #include "nsCOMArray.h"
 #include "nsThreadUtils.h"
 #include "nsIGlobalObject.h"
+#include "nsIScriptObjectPrincipal.h"
 #include "nsWeakReference.h"
 
 class nsInProcessTabChildGlobal : public nsDOMEventTargetHelper,
                                   public nsFrameScriptExecutor,
                                   public nsIInProcessContentFrameMessageManager,
                                   public nsIGlobalObject,
+                                  public nsIScriptObjectPrincipal,
                                   public nsSupportsWeakReference,
                                   public mozilla::dom::ipc::MessageManagerCallback
 {
 public:
   nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner,
                             nsFrameMessageManager* aChrome);
   virtual ~nsInProcessTabChildGlobal();
   NS_DECL_ISUPPORTS_INHERITED
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -3394,17 +3394,17 @@ nsObjectLoadingContent::DoNewResolve(JSC
                                      JS::Handle<jsid> aId,
                                      JS::MutableHandle<JS::Value> aValue)
 {
   // We don't resolve anything; we just try to make sure we're instantiated
 
   nsRefPtr<nsNPAPIPluginInstance> pi;
   nsresult rv = ScriptRequestPluginInstance(aCx, getter_AddRefs(pi));
   if (NS_FAILED(rv)) {
-    return mozilla::dom::Throw<true>(aCx, rv);
+    return mozilla::dom::Throw(aCx, rv);
   }
   return true;
 }
 
 void
 nsObjectLoadingContent::GetOwnPropertyNames(JSContext* aCx,
                                             nsTArray<nsString>& /* unused */,
                                             ErrorResult& aRv)
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -441,17 +441,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttp
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXMLHttpRequest)
   bool isBlack = tmp->IsBlack();
   if (isBlack || tmp->mWaitingForOnStopRequest) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
-      xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
+      // This marks the wrapper black.
+      tmp->GetWrapper();
     }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsXMLHttpRequest)
   return tmp->
     IsBlackAndDoesNotNeedTracing(static_cast<nsDOMEventTargetHelper*>(tmp));
--- a/content/canvas/src/ImageData.h
+++ b/content/canvas/src/ImageData.h
@@ -9,17 +9,17 @@
 
 #include "nsIDOMCanvasRenderingContext2D.h"
 
 #include "mozilla/Attributes.h"
 #include <stdint.h>
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsTraceRefcnt.h"
-#include "xpcpublic.h"
+#include "js/GCAPI.h"
 
 namespace mozilla {
 namespace dom {
 
 class ImageData MOZ_FINAL : public nsISupports
 {
 public:
   ImageData(uint32_t aWidth, uint32_t aHeight, JSObject& aData)
@@ -49,17 +49,17 @@ public:
     return mHeight;
   }
   JSObject* Data(JSContext* cx, JS::Handle<JSObject*> /* unused */) const
   {
     return GetDataObject();
   }
   JSObject* GetDataObject() const
   {
-    xpc_UnmarkGrayObject(mData);
+    JS::ExposeObjectToActiveJS(mData);
     return mData;
   }
 
   JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> scope);
 
 private:
   void HoldData();
   void DropData();
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -487,18 +487,20 @@ nsDOMDataTransfer::MozGetDataAt(const ns
         nsCOMPtr<nsISupports> data;
         formatitem.mData->GetAsISupports(getter_AddRefs(data));
         // Make sure the code that is calling us is same-origin with the data.
         nsCOMPtr<EventTarget> pt = do_QueryInterface(data);
         if (pt) {
           nsresult rv = NS_OK;
           nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
           NS_ENSURE_TRUE(c && NS_SUCCEEDED(rv), NS_ERROR_DOM_SECURITY_ERR);
-          nsIScriptObjectPrincipal* sp = c->GetGlobalObject();
-          NS_ENSURE_TRUE(sp, NS_ERROR_DOM_SECURITY_ERR);
+          nsIGlobalObject* go = c->GetGlobalObject();
+          NS_ENSURE_TRUE(go, NS_ERROR_DOM_SECURITY_ERR);
+          nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
+          MOZ_ASSERT(sp, "This cannot fail on the main thread.");
           nsIPrincipal* dataPrincipal = sp->GetPrincipal();
           NS_ENSURE_TRUE(dataPrincipal, NS_ERROR_DOM_SECURITY_ERR);
           NS_ENSURE_TRUE(principal || (principal = GetCurrentPrincipal(&rv)),
                          NS_ERROR_DOM_SECURITY_ERR);
           NS_ENSURE_SUCCESS(rv, rv);
           bool equals = false;
           NS_ENSURE_TRUE(NS_SUCCEEDED(principal->Equals(dataPrincipal, &equals)) && equals,
                          NS_ERROR_DOM_SECURITY_ERR);
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -1325,19 +1325,21 @@ void
 nsEventListenerManager::MarkForCC()
 {
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     const nsListenerStruct& ls = mListeners.ElementAt(i);
     nsIJSEventListener* jsl = ls.GetJSListener();
     if (jsl) {
       if (jsl->GetHandler().HasEventHandler()) {
-        xpc_UnmarkGrayObject(jsl->GetHandler().Ptr()->Callable());
+        JS::ExposeObjectToActiveJS(jsl->GetHandler().Ptr()->Callable());
       }
-      xpc_UnmarkGrayObject(jsl->GetEventScope());
+      if (JSObject* scope = jsl->GetEventScope()) {
+        JS::ExposeObjectToActiveJS(scope);
+      }
     } else if (ls.mListenerType == eWrappedJSListener) {
       xpc_TryUnmarkWrappedGrayObject(ls.mListener.GetXPCOMCallback());
     } else if (ls.mListenerType == eWebIDLListener) {
       // Callback() unmarks gray
       ls.mListener.GetWebIDLCallback()->Callback();
     }
   }
   if (mRefCnt.IsPurple()) {
--- a/content/html/document/src/HTMLAllCollection.cpp
+++ b/content/html/document/src/HTMLAllCollection.cpp
@@ -62,13 +62,14 @@ HTMLAllCollection::GetObject(JSContext* 
       return nullptr;
     }
 
     // Make the JSObject hold a reference to the document.
     JS_SetPrivate(mObject, ToSupports(mDocument));
     NS_ADDREF(mDocument);
   }
 
-  return xpc_UnmarkGrayObject(mObject);
+  JS::ExposeObjectToActiveJS(mObject);
+  return mObject;
 }
 
 } // namespace dom
 } // namespace mozilla
rename from content/media/omx/MP3FrameParser.cpp
rename to content/media/MP3FrameParser.cpp
--- a/content/media/omx/MP3FrameParser.cpp
+++ b/content/media/MP3FrameParser.cpp
@@ -27,17 +27,17 @@ public:
     mLength(aLength),
     mSize(0)
   {
     MOZ_ASSERT(mBuffer || !mLength);
   }
 
   nsresult Parse();
 
-  int64_t GetMP3Offset() const {
+  int64_t Length() const {
     return ID3_HEADER_LENGTH + mSize;
   }
 
 private:
   const uint8_t* mBuffer;
   uint32_t       mLength;
   uint32_t       mSize;
 };
@@ -79,24 +79,21 @@ public:
   };
 
   MP3Buffer(const uint8_t* aBuffer, uint32_t aLength)
   : mBuffer(aBuffer),
     mLength(aLength),
     mDurationUs(0),
     mNumFrames(0),
     mBitRateSum(0),
-    mFrameSizeSum(0),
-    mTrailing(0)
+    mFrameSizeSum(0)
   {
     MOZ_ASSERT(mBuffer || !mLength);
   }
 
-  static const uint8_t* FindNextHeader(const uint8_t* aBuffer, uint32_t aLength);
-
   nsresult Parse();
 
   int64_t GetDuration() const {
     return mDurationUs;
   }
 
   int64_t GetNumberOfFrames() const {
     return mNumFrames;
@@ -105,20 +102,16 @@ public:
   int64_t GetBitRateSum() const {
     return mBitRateSum;
   }
 
   int64_t GetFrameSizeSum() const {
     return mFrameSizeSum;
   }
 
-  int64_t GetTrailing() const {
-    return mTrailing;
-  }
-
 private:
 
   enum MP3FrameHeaderField {
     MP3_HDR_FIELD_SYNC,
     MP3_HDR_FIELD_VERSION,
     MP3_HDR_FIELD_LAYER,
     MP3_HDR_FIELD_BITRATE,
     MP3_HDR_FIELD_SAMPLERATE,
@@ -133,19 +126,19 @@ private:
   };
 
   static uint32_t ExtractBits(uint32_t aValue, uint32_t aOffset,
                               uint32_t aBits);
   static uint32_t ExtractFrameHeaderField(uint32_t aHeader,
                                           enum MP3FrameHeaderField aField);
   static uint32_t ExtractFrameHeader(const uint8_t* aBuffer);
   static nsresult DecodeFrameHeader(const uint8_t* aBuffer,
-                                          size_t* aFrameSize,
-                                          uint32_t* aBitRate,
-                                          uint64_t* aDuration);
+                                    uint32_t* aFrameSize,
+                                    uint32_t* aBitRate,
+                                    uint64_t* aDuration);
 
   static const uint16_t sBitRate[16];
   static const uint16_t sSampleRate[4];
 
   const uint8_t* mBuffer;
   uint32_t       mLength;
 
   // The duration of this parsers data in milliseconds.
@@ -154,19 +147,16 @@ private:
   // The number of frames in the range.
   int64_t mNumFrames;
 
   // The sum of all frame's bit rates.
   int64_t mBitRateSum;
 
   // The sum of all frame's sizes in byte.
   int32_t mFrameSizeSum;
-
-  // The number of trailing bytes.
-  int32_t mTrailing;
 };
 
 const uint16_t MP3Buffer::sBitRate[16] = {
   0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0
 };
 
 const uint16_t MP3Buffer::sSampleRate[4] = {
   44100, 48000, 32000, 0
@@ -209,34 +199,16 @@ uint32_t MP3Buffer::ExtractFrameHeader(c
   //  else
   //    return 0;
   //
   return (frameSync == uint32_t(MP3_HDR_CONST_FRAMESYNC)) *
          (version == uint32_t(MP3_HDR_CONST_VERSION)) *
          (layer == uint32_t(MP3_HDR_CONST_LAYER)) * !!bitRate * !!sampleRate * header;
 }
 
-const uint8_t* MP3Buffer::FindNextHeader(const uint8_t* aBuffer, uint32_t aLength)
-{
-  MOZ_ASSERT(aBuffer || !aLength);
-
-  // Find MP3's frame-sync marker while there are at least 4 bytes
-  // left to contain the MP3 frame header
-
-  while (aLength >= MP3_HEADER_LENGTH) {
-    if (ExtractFrameHeader(aBuffer)) {
-      break;
-    }
-    ++aBuffer;
-    --aLength;
-  }
-
-  return aBuffer;
-}
-
 nsresult MP3Buffer::DecodeFrameHeader(const uint8_t* aBuffer,
                                       uint32_t* aFrameSize,
                                       uint32_t* aBitRate,
                                       uint64_t* aDuration)
 {
   uint32_t header = ExtractFrameHeader(aBuffer);
 
   if (!header) {
@@ -263,213 +235,196 @@ nsresult MP3Buffer::DecodeFrameHeader(co
 
 nsresult MP3Buffer::Parse()
 {
   // We walk over the newly arrived data and sum up the
   // bit rates, sizes, durations, etc. of the contained
   // MP3 frames.
 
   const uint8_t* buffer = mBuffer;
-  uint32_t       length = mLength;
+  uint32_t length = mLength;
 
   while (length >= MP3_HEADER_LENGTH) {
 
     uint32_t frameSize;
     uint32_t bitRate;
     uint64_t duration;
 
     nsresult rv = DecodeFrameHeader(buffer, &frameSize, &bitRate, &duration);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
 
     mBitRateSum += bitRate;
     mDurationUs += duration;
     ++mNumFrames;
 
     mFrameSizeSum += frameSize;
 
     if (frameSize <= length) {
       length -= frameSize;
     } else {
       length = 0;
     }
 
     buffer += frameSize;
   }
 
-  mTrailing = length;
-
   return NS_OK;
 }
 
+// Some MP3's have large ID3v2 tags, up to 150KB, so we allow lots of
+// skipped bytes to be read, just in case, before we give up and assume
+// we're not parsing an MP3 stream.
+static const uint32_t MAX_SKIPPED_BYTES = 200 * 1024;
+
 MP3FrameParser::MP3FrameParser(int64_t aLength)
 : mBufferLength(0),
   mLock("MP3FrameParser.mLock"),
   mDurationUs(0),
   mBitRateSum(0),
   mNumFrames(0),
   mOffset(0),
   mUnhandled(0),
   mLength(aLength),
-  mTrailing(0),
-  mIsMP3(true)
+  mMP3Offset(-1),
+  mSkippedBytes(0),
+  mIsMP3(MAYBE_MP3)
 { }
 
-size_t MP3FrameParser::ParseInternalBuffer(const uint8_t* aBuffer, uint32_t aLength, int64_t aOffset)
+nsresult MP3FrameParser::ParseBuffer(const uint8_t* aBuffer,
+                                     uint32_t aLength,
+                                     int64_t aStreamOffset,
+                                     uint32_t* aOutBytesRead)
 {
-  if (mOffset != aOffset) {
-    // If we don't append, we throw away our temporary buffer.
-    mBufferLength = 0;
-    return 0;
-  }
-
-  size_t copyLength = 0;
-
-  if (mBufferLength || !mOffset) {
-
-    // We have some data in our temporary buffer and append to it, or
-    // we are at the beginning of the stream. We both cases, we append
-    // some data to our temporary buffer and try to parse it.
-    copyLength = std::min<size_t>(NS_ARRAY_LENGTH(mBuffer)-mBufferLength, aLength);
-    memcpy(mBuffer+mBufferLength, aBuffer, copyLength*sizeof(*mBuffer));
-    mBufferLength += copyLength;
-  }
-
-  if ((mBufferLength >= ID3Buffer::ID3_HEADER_LENGTH) && (mOffset < ID3Buffer::ID3_HEADER_LENGTH)) {
-
-    // There might be an ID3 header at the very beginning of the stream.
-    ID3Buffer id3Buffer(mBuffer, mBufferLength);
-    nsresult rv = id3Buffer.Parse();
-
-    if (rv == NS_OK) {
-      mOffset += id3Buffer.GetMP3Offset()-(mBufferLength-copyLength);
-      mBufferLength = 0;
+  // Iterate forwards over the buffer, looking for ID3 tag, or MP3
+  // Frame headers.
+  uint32_t bufferOffset = 0;
+  uint32_t headersParsed = 0;
+  while (bufferOffset < aLength) {
+    const uint8_t* buffer = aBuffer + bufferOffset;
+    const uint32_t length = aLength - bufferOffset;
+    if (mMP3Offset == -1) {
+      // We've not found any MP3 frames yet, there may still be ID3 tags in
+      // the stream, so test for them.
+      if (length < ID3Buffer::ID3_HEADER_LENGTH) {
+        // We don't have enough data to get a complete ID3 header, bail.
+        break;
+      }
+      ID3Buffer id3Buffer(buffer, length);
+      if (NS_SUCCEEDED(id3Buffer.Parse())) {
+        bufferOffset += id3Buffer.Length();
+        // Try to parse the next chunk.
+        headersParsed++;
+        continue;
+      }
+    }
+    if (length < MP3Buffer::MP3_HEADER_LENGTH) {
+      // We don't have enough data to get a complete MP3 frame header, bail.
+      break;
+    }
+    MP3Buffer mp3Buffer(buffer, length);
+    if (NS_SUCCEEDED(mp3Buffer.Parse())) {
+      headersParsed++;
+      if (mMP3Offset == -1) {
+        mMP3Offset = aStreamOffset + bufferOffset;
+      }
+      mDurationUs += mp3Buffer.GetDuration();
+      mBitRateSum += mp3Buffer.GetBitRateSum();
+      mNumFrames += mp3Buffer.GetNumberOfFrames();
+      bufferOffset += mp3Buffer.GetFrameSizeSum();
+    } else {
+      // No ID3 or MP3 frame header here. Try the next byte.
+      ++bufferOffset;
     }
   }
-
-  if (mBufferLength >= MP3Buffer::MP3_HEADER_LENGTH) {
-
-    // Or there could be a regular frame header somewhere
-    // in the stream.
-    MP3Buffer mp3Buffer(mBuffer, mBufferLength);
-    nsresult rv = mp3Buffer.Parse();
-
-    if (rv == NS_OK) {
-      mDurationUs += mp3Buffer.GetDuration();
-      mBitRateSum += mp3Buffer.GetBitRateSum();
-      mNumFrames  += mp3Buffer.GetNumberOfFrames();
-      mOffset     += mp3Buffer.GetFrameSizeSum()-(mBufferLength-copyLength);
-      mBufferLength = 0;
+  if (headersParsed == 0) {
+    if (mIsMP3 == MAYBE_MP3) {
+      mSkippedBytes += aLength;
+      if (mSkippedBytes > MAX_SKIPPED_BYTES) {
+        mIsMP3 = NOT_MP3;
+        return NS_ERROR_FAILURE;
+      }
     }
+  } else {
+    mIsMP3 = DEFINITELY_MP3;
+    mSkippedBytes = 0;
   }
-
-  if (mBufferLength) {
-    // We have not been able to successfully parse the
-    // content of the temporary buffer. If the buffer is
-    // full already, the stream does not contain MP3.
-    mOffset += copyLength;
-    mIsMP3   = (mBufferLength < NS_ARRAY_LENGTH(mBuffer));
-  } else {
-    // We parsed the temporary buffer. The parser code
-    // will update the input data.
-    copyLength = 0;
-  }
-
-  if (mOffset > mLength) {
-    mLength = mOffset;
-  }
-
-  return copyLength;
+  *aOutBytesRead = bufferOffset;
+  return NS_OK;
 }
 
-void MP3FrameParser::Parse(const uint8_t* aBuffer, uint32_t aLength, int64_t aOffset)
+void MP3FrameParser::Parse(const char* aBuffer, uint32_t aLength, int64_t aOffset)
 {
   MutexAutoLock mon(mLock);
 
-  // We first try to parse the remaining data from the last call that
-  // is stored in an internal buffer.
-  size_t bufferIncr = ParseInternalBuffer(aBuffer, aLength, aOffset);
-
-  aBuffer += bufferIncr;
-  aLength -= bufferIncr;
-  aOffset += bufferIncr;
-
-  // The number of attempts to parse the data. This should be 1 of we
-  // append to the end of the existing data.
-  int retries = 1;
-
-  if (aOffset+aLength <= mOffset) {
+  const uint8_t* buffer = reinterpret_cast<const uint8_t*>(aBuffer);
+  const int64_t lastChunkEnd = mOffset + mBufferLength;
+  if (aOffset + aLength <= lastChunkEnd) {
     // We already processed this fragment.
     return;
-  } else if (aOffset < mOffset) {
+  } else if (aOffset < lastChunkEnd) {
     // mOffset is within the new fragment, shorten range.
-    aLength -= mOffset-aOffset;
-    aBuffer += mOffset-aOffset;
-    aOffset  = mOffset;
-  } else if (aOffset > mOffset) {
+    aLength -= lastChunkEnd - aOffset;
+    buffer += lastChunkEnd - aOffset;
+    aOffset = lastChunkEnd;
+  } else if (aOffset > lastChunkEnd) {
     // Fragment comes after current position, store difference.
-    mUnhandled += aOffset-mOffset;
-
-    // We might start in the middle of a frame and have find the next
-    // frame header. As our detection heuristics might return false
-    // positives, we simply try multiple times. The current value comes
-    // from experimentation with MP3 files. If you encounter false positives
-    // and incorrectly parsed MP3 files, try incrementing this value.
-    retries = 5;
+    mUnhandled += aOffset - lastChunkEnd;
+    mSkippedBytes = 0;
   }
 
-  uint32_t trailing = 0;
-
-  while (retries) {
-
-    MP3Buffer mp3Buffer(aBuffer, aLength);
-    nsresult rv = mp3Buffer.Parse();
-
-    if (rv != NS_OK) {
-      --retries;
-
-      if (!retries) {
-        mIsMP3 = false;
-        return;
-      }
-
-      // We might be in the middle of a frame, find next frame header
-      const uint8_t *buffer = MP3Buffer::FindNextHeader(aBuffer+1, aLength-1);
-
-      mUnhandled += buffer-aBuffer;
-      mOffset     = aOffset + buffer-aBuffer;
-      aLength    -= buffer-aBuffer;
-      aBuffer     = buffer;
-    } else {
-      mDurationUs += mp3Buffer.GetDuration();
-      mBitRateSum += mp3Buffer.GetBitRateSum();
-      mNumFrames  += mp3Buffer.GetNumberOfFrames();
-      mOffset     += mp3Buffer.GetFrameSizeSum();
-
-      trailing = mp3Buffer.GetTrailing();
-      retries = 0;
+  if (mBufferLength > 0) {
+    // We have some data which was left over from the last buffer we received.
+    // Append to it, so that we have enough data to parse a complete header, and
+    // try to parse it.
+    uint32_t copyLength = std::min<size_t>(NS_ARRAY_LENGTH(mBuffer)-mBufferLength, aLength);
+    memcpy(mBuffer+mBufferLength, buffer, copyLength*sizeof(*mBuffer));
+    // Caculate the offset of the data in the start of the buffer.
+    int64_t streamOffset = mOffset - mBufferLength;
+    uint32_t bufferLength = mBufferLength + copyLength;
+    uint32_t bytesRead = 0;
+    if (NS_FAILED(ParseBuffer(mBuffer,
+                              bufferLength,
+                              streamOffset,
+                              &bytesRead))) {
+      return;
     }
+    MOZ_ASSERT(bytesRead >= mBufferLength, "Parse should leave original buffer");
+    // Adjust the incoming buffer pointer/length so that it reflects that we may have
+    // consumed data from buffer.
+    uint32_t adjust = bytesRead - mBufferLength;
+    aOffset += adjust;
+    aLength -= adjust;
+    mBufferLength = 0;
   }
 
-  if (trailing) {
-    // Store trailing bytes in temporary buffer.
-    MOZ_ASSERT(trailing < (NS_ARRAY_LENGTH(mBuffer)*sizeof(*mBuffer)));
-    memcpy(mBuffer, aBuffer+(aLength-trailing), trailing);
+  uint32_t bytesRead = 0;
+  if (NS_FAILED(ParseBuffer(buffer,
+                            aLength,
+                            aOffset,
+                            &bytesRead))) {
+    return;
+  }
+  mOffset += bytesRead;
+
+  if (bytesRead < aLength) {
+    // We have some data left over. Store trailing bytes in temporary buffer
+    // to be parsed next time we receive more data.
+    uint32_t trailing = aLength - bytesRead;
+    MOZ_ASSERT(trailing < (NS_ARRAY_LENGTH(mBuffer)*sizeof(mBuffer[0])));
+    memcpy(mBuffer, buffer+(aLength-trailing), trailing);
     mBufferLength = trailing;
   }
 
   if (mOffset > mLength) {
     mLength = mOffset;
   }
 }
 
-void MP3FrameParser::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
-{
-  Parse(reinterpret_cast<const uint8_t*>(aBuffer), aLength, aOffset);
-}
-
 int64_t MP3FrameParser::GetDuration()
 {
   MutexAutoLock mon(mLock);
 
   if (!mNumFrames) {
     return -1; // Not a single frame decoded yet
   }
 
@@ -479,9 +434,15 @@ int64_t MP3FrameParser::GetDuration()
   NS_ENSURE_TRUE(avgBitRate > 0, mDurationUs);
 
   MOZ_ASSERT(mLength >= mOffset);
   int64_t unhandled = mUnhandled + (mLength-mOffset);
 
   return mDurationUs + (uint64_t(MP3Buffer::MP3_DURATION_CONST) * unhandled) / avgBitRate;
 }
 
+int64_t MP3FrameParser::GetMP3Offset()
+{
+  MutexAutoLock mon(mLock);
+  return mMP3Offset;
 }
+
+}
rename from content/media/omx/MP3FrameParser.h
rename to content/media/MP3FrameParser.h
--- a/content/media/omx/MP3FrameParser.h
+++ b/content/media/MP3FrameParser.h
@@ -37,40 +37,76 @@ namespace mozilla {
 
 class MP3FrameParser
 {
 public:
   MP3FrameParser(int64_t aLength=-1);
 
   bool IsMP3() {
     MutexAutoLock mon(mLock);
-    return mIsMP3;
+    return mIsMP3 != NOT_MP3;
   }
 
-  void Parse(const uint8_t* aBuffer, uint32_t aLength, int64_t aOffset);
+  void Parse(const char* aBuffer, uint32_t aLength, int64_t aStreamOffset);
 
-  void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
-
+  // Returns the duration, in microseconds. If the entire stream has not
+  // been parsed yet, this is an estimate based on the bitrate of the
+  // frames parsed so far.
   int64_t GetDuration();
 
+  // Returns the offset of the first MP3 frame in the stream, or -1 of
+  // no MP3 frame has been detected yet.
+  int64_t GetMP3Offset();
+
 private:
-  size_t ParseInternalBuffer(const uint8_t* aBuffer, uint32_t aLength, int64_t aOffset);
 
-  uint8_t  mBuffer[10];
+  // Parses aBuffer, starting at offset 0. Returns the number of bytes
+  // parsed, relative to the start of the buffer. Note this may be
+  // greater than aLength if the headers in the buffer indicate that
+  // the frame or ID3 tag extends outside of aBuffer. Returns failure
+  // if too many non-MP3 bytes are parsed.
+  nsresult ParseBuffer(const uint8_t* aBuffer,
+                       uint32_t aLength,
+                       int64_t aStreamOffset,
+                       uint32_t* aOutBytesRead);
+
+  // mBuffer must be at least 19 bytes long, in case the last byte in the
+  // buffer is the first byte in a 10 byte long ID3 tag header.
+  uint8_t  mBuffer[32];
   uint32_t mBufferLength;
 
   // A low-contention lock for protecting the parser results
   Mutex mLock;
 
   // All fields below are protected by mLock
   uint64_t mDurationUs;
   uint64_t mBitRateSum;
   uint64_t mNumFrames;
+
+  // Offset of the last data parsed. This is the end offset of the last data
+  // block parsed, so it's the start offset we expect to get on the next
+  // call to Parse().
   int64_t  mOffset;
+
+  // Count of the number of bytes that the parser hasn't seen so far. This
+  // happens when the stream seeks.
   int64_t  mUnhandled;
   int64_t  mLength;
-  uint32_t mTrailing;
+  // Offset of first MP3 frame in the bitstream. Has value -1 until the
+  // first MP3 frame is found.
+  int64_t mMP3Offset;
+
+  // Count of bytes that have been parsed but skipped over because we couldn't
+  // find a sync pattern or an ID3 header. If this gets too high, we assume
+  // the stream either isn't MP3, or is corrupt.
+  uint32_t mSkippedBytes;
 
-  // Contains the state of the MP3 detection
-  bool mIsMP3;
+  enum eIsMP3 {
+    MAYBE_MP3, // We're giving the stream the benefit of the doubt...
+    DEFINITELY_MP3, // We've hit at least one ID3 tag or MP3 frame.
+    NOT_MP3 // Not found any evidence of the stream being MP3.
+  };
+
+  eIsMP3 mIsMP3;
+
 };
 
 }
--- a/content/media/directshow/SourceFilter.cpp
+++ b/content/media/directshow/SourceFilter.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SourceFilter.h"
 #include "MediaResource.h"
 #include "mozilla/RefPtr.h"
 #include "DirectShowUtils.h"
+#include "MP3FrameParser.h"
 #include "prlog.h"
 
 using namespace mozilla::media;
 
 namespace mozilla {
 
 // Define to trace what's on...
 //#define DEBUG_SOURCE_TRACE 1
@@ -654,87 +655,78 @@ SourceFilter::GetPin(int n)
 
 // Get's the media type we're supplying.
 const MediaType*
 SourceFilter::GetMediaType() const
 {
   return &mMediaType;
 }
 
-// Gets the length of the ID3v2 tag which starts at aStartOffset.
-static nsresult
-GetID3TagLength(MediaResource* aResource,
-                int64_t aStartOffset,
-                int32_t* aLength)
+static uint32_t
+Read(MediaResource* aResource,
+     const int64_t aOffset,
+     char* aBuffer,
+     const uint32_t aBytesToRead)
 {
-  MOZ_ASSERT(aLength);
-  char header[10];
   uint32_t totalBytesRead = 0;
-  while (totalBytesRead < 10) {
+  while (totalBytesRead < aBytesToRead) {
     uint32_t bytesRead = 0;
-    nsresult rv = aResource->ReadAt(aStartOffset + totalBytesRead,
-                                    header+totalBytesRead,
-                                    10-totalBytesRead,
+    nsresult rv = aResource->ReadAt(aOffset + totalBytesRead,
+                                    aBuffer+totalBytesRead,
+                                    aBytesToRead-totalBytesRead,
                                     &bytesRead);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (bytesRead == 0) {
-      // Reached end of file?
-      return NS_ERROR_FAILURE;
+    if (NS_FAILED(rv) || bytesRead == 0) {
+      // Error or end of stream?
+      break;
     }
     totalBytesRead += bytesRead;
   }
-  if (strncmp("ID3", header, 3)) {
-    // No ID3v2 header
-    *aLength = 0;
-    return NS_OK;
-  }
-
-  int32_t id3Length =
-    10 +
-    (int32_t(0x7f & header[6]) << 21) +
-    (int32_t(0x7f & header[7]) << 14) +
-    (int32_t(0x7f & header[8]) << 7) +
-     int32_t(0x7f & header[9]);
-
-  *aLength = id3Length;
-  return NS_OK;
+  return totalBytesRead;
 }
 
-// Parses the ID3v2 headers in the resource and returns the offset of the
-// MP3 data after the ID3v2 headers. This is used to trim off the ID3v2 headers,
-// as DirectShow can't handle some ID3v2 tags (possibly ones that are large).
+// Parses the MP3 stream and returns the offset of the first MP3
+// sync frame after the ID3v2 headers. This is used to trim off
+// the ID3v2 headers, as DirectShow can't handle large ID3v2 tags.
 static nsresult
 GetMP3DataOffset(MediaResource* aResource, int64_t* aOutOffset)
 {
-  nsresult rv;
-  int64_t id3TagsEndOffset = 0;
-  int32_t length = 0;
+  MP3FrameParser parser;
+  int64_t offset = 0;
+  const uint32_t len = 1024;
+  char buffer[len];
   do {
-    rv = GetID3TagLength(aResource, id3TagsEndOffset, &length);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (length > 0) {
-      id3TagsEndOffset += length;
+    uint32_t bytesRead = Read(aResource, offset, buffer, len);
+    if (bytesRead == 0) {
+      break;
     }
-  } while (length > 0);
-  *aOutOffset = id3TagsEndOffset;
+    parser.Parse(buffer, bytesRead, offset);
+    offset += bytesRead;
+  } while (parser.GetMP3Offset() == -1 && parser.IsMP3());
+
+  if (!parser.IsMP3() || parser.GetMP3Offset() == -1) {
+    return NS_ERROR_FAILURE;
+  }
+
+  *aOutOffset = parser.GetMP3Offset();
   return NS_OK;
 }
 
 nsresult
 SourceFilter::Init(MediaResource* aResource)
 {
   LOG("SourceFilter::Init()");
 
   // Get the offset of MP3 data in the stream, and pass that into
   // the output pin so that the stream that we present to DirectShow
   // does not contain ID3v2 tags. DirectShow can't properly parse some
   // streams' ID3v2 tags.
   int64_t mp3DataOffset = 0;
   nsresult rv = GetMP3DataOffset(aResource, &mp3DataOffset);
   NS_ENSURE_SUCCESS(rv, rv);
+  LOG("First MP3 sync/data frame lies at offset %lld", mp3DataOffset);
 
   mOutputPin = new OutputPin(aResource,
                              this,
                              mLock,
                              mp3DataOffset);
   NS_ENSURE_TRUE(mOutputPin != nullptr, NS_ERROR_FAILURE);
 
   return NS_OK;
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -61,16 +61,17 @@ EXPORTS += [
     'AudioSegment.h',
     'AudioStream.h',
     'BufferDecoder.h',
     'BufferMediaResource.h',
     'DOMMediaStream.h',
     'DecoderTraits.h',
     'EncodedBufferCache.h',
     'FileBlockCache.h',
+    'MP3FrameParser.h',
     'MediaCache.h',
     'MediaDecoder.h',
     'MediaDecoderOwner.h',
     'MediaDecoderReader.h',
     'MediaDecoderStateMachine.h',
     'MediaMetadataManager.h',
     'MediaRecorder.h',
     'MediaResource.h',
@@ -106,16 +107,17 @@ CPP_SOURCES += [
     'AudioSegment.cpp',
     'AudioStream.cpp',
     'AudioStreamTrack.cpp',
     'BufferDecoder.cpp',
     'DOMMediaStream.cpp',
     'DecoderTraits.cpp',
     'EncodedBufferCache.cpp',
     'FileBlockCache.cpp',
+    'MP3FrameParser.cpp',
     'MediaCache.cpp',
     'MediaDecoder.cpp',
     'MediaDecoderReader.cpp',
     'MediaDecoderStateMachine.cpp',
     'MediaRecorder.cpp',
     'MediaResource.cpp',
     'MediaStreamGraph.cpp',
     'MediaStreamTrack.cpp',
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -618,17 +618,17 @@ bool OmxDecoder::SetAudioFormat() {
 }
 
 void OmxDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
 {
   if (!mMP3FrameParser.IsMP3()) {
     return;
   }
 
-  mMP3FrameParser.NotifyDataArrived(aBuffer, aLength, aOffset);
+  mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
 
   int64_t durationUs = mMP3FrameParser.GetDuration();
 
   if (durationUs != mDurationUs) {
     mDurationUs = durationUs;
 
     MOZ_ASSERT(mDecoder);
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
--- a/content/media/omx/moz.build
+++ b/content/media/omx/moz.build
@@ -9,17 +9,16 @@ MODULE = 'content'
 EXPORTS += [
     'MediaOmxDecoder.h',
     'MediaOmxReader.h',
 ]
 
 CPP_SOURCES += [
     'MediaOmxDecoder.cpp',
     'MediaOmxReader.cpp',
-    'MP3FrameParser.cpp',
     'OmxDecoder.cpp',
     'OMXCodecProxy.cpp',
 ]
 
 LIBXUL_LIBRARY = True
 
 LIBRARY_NAME = 'gkconomx_s'
 
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -225,16 +225,17 @@ MOCHITEST_FILES += \
 		variable-channel.opus \
 		chained-video.ogv \
 		chained-audio-video.ogg \
 		variable-preskip.opus \
 		dirac.ogg \
 		multiple-bos.ogg \
 		no-cues.webm \
 		owl.mp3 \
+		owl-funnier-id3.mp3 \
 		owl-funny-id3.mp3 \
 		split.webm \
 		seek.ogv \
 		seek.webm \
 		seek.yuv \
 		short-video.ogv \
 		small-shot.ogg \
 		small-shot.m4a \
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -180,16 +180,19 @@ var gPlayTests = [
   { name:"gizmo.mp4", type:"video/mp4", duration:5.56 },
 
   { name:"small-shot.m4a", type:"audio/mp4", duration:0.29 },
   { name:"small-shot.mp3", type:"audio/mpeg", duration:0.27 },
   { name:"owl.mp3", type:"audio/mpeg", duration:3.29 },
   // owl.mp3 as above, but with something funny going on in the ID3v2 tag
   // that causes DirectShow to fail.
   { name:"owl-funny-id3.mp3", type:"audio/mpeg", duration:3.29 },
+  // owl.mp3 as above, but with something even funnier going on in the ID3v2 tag
+  // that causes DirectShow to fail.
+  { name:"owl-funnier-id3.mp3", type:"audio/mpeg", duration:3.29 },
 
   // Invalid file
   { name:"bogus.duh", type:"bogus/duh", duration:Number.NaN }
 ];
 
 // A file for each type we can support.
 var gSnifferTests = [
   { name:"big.wav", type:"audio/x-wav", duration:9.278981, size:102444 },
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..05ec507530e4882cec238ed1ec1ca920614293ad
GIT binary patch
literal 69603
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%0Dl_-qU%zE;)sTC~Xx<``usc@1`6iMJBZ
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
TQ3U`1{=Z6S`2W}c4eS2_iguix
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -208,17 +208,19 @@ void
 nsXBLDocGlobalObject::ClearGlobalObjectOwner()
 {
   mGlobalObjectOwner = nullptr;
 }
 
 void
 nsXBLDocGlobalObject::UnmarkCompilationGlobal()
 {
-  xpc_UnmarkGrayObject(mJSObject);
+  if (mJSObject) {
+    JS::ExposeObjectToActiveJS(mJSObject);
+  }
 }
 
 JSObject *
 nsXBLDocGlobalObject::GetCompilationGlobal()
 {
   // The prototype document has its own special secret script object
   // that can be used to compile scripts and event handlers.
   if (mJSObject || mDestroyed) {
@@ -352,17 +354,17 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsX
     ProtoTracer closure = { aCallbacks, aClosure };
     tmp->mBindingTable->Enumerate(TraceProtos, &closure);
   }
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 static void
 UnmarkXBLJSObject(void* aP, const char* aName, void* aClosure)
 {
-  xpc_UnmarkGrayObject(static_cast<JSObject*>(aP));
+  JS::ExposeObjectToActiveJS(static_cast<JSObject*>(aP));
 }
 
 static bool
 UnmarkProtos(nsHashKey* aKey, void* aData, void* aClosure)
 {
   nsXBLPrototypeBinding* proto = static_cast<nsXBLPrototypeBinding*>(aData);
   proto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr);
   return kHashEnumerateNext;
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -351,17 +351,17 @@ nsXBLPrototypeHandler::EnsureEventHandle
 {
   AutoPushJSContext cx(aBoundContext->GetNativeContext());
 
   // Check to see if we've already compiled this
   nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aGlobal);
   if (pWindow) {
     JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
     if (cachedHandler) {
-      xpc_UnmarkGrayObject(cachedHandler);
+      JS::ExposeObjectToActiveJS(cachedHandler);
       aHandler.set(cachedHandler);
       NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
       return NS_OK;
     }
   }
 
   // Ensure that we have something to compile
   nsDependentString handlerText(mHandlerText);
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2633,17 +2633,19 @@ nsXULPrototypeScript::Compile(const PRUn
            .setFileAndLine(urlspec.get(), aLineNo)
            .setVersion(JSVersion(mLangVersion));
     // If the script was inline, tell the JS parser to save source for
     // Function.prototype.toSource(). If it's out of line, we retrieve the
     // source from the files on demand.
     options.setSourcePolicy(mOutOfLine ? JS::CompileOptions::LAZY_SOURCE
                                        : JS::CompileOptions::SAVE_SOURCE);
     JS::RootedObject scope(cx, JS::CurrentGlobalOrNull(cx));
-    xpc_UnmarkGrayObject(scope);
+    if (scope) {
+      JS::ExposeObjectToActiveJS(scope);
+    }
 
     if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options)) {
         if (!JS::CompileOffThread(cx, scope, options,
                                   static_cast<const jschar*>(aText), aTextLength,
                                   OffThreadScriptReceiverCallback,
                                   static_cast<void*>(aOffThreadReceiver))) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
--- a/content/xul/document/src/XULDocument.cpp
+++ b/content/xul/document/src/XULDocument.cpp
@@ -3663,17 +3663,20 @@ XULDocument::ExecuteScript(nsIScriptCont
     if (!aContext->GetScriptsEnabled())
         return NS_OK;
 
     // Execute the precompiled script with the given version
     nsAutoMicroTask mt;
     JSContext *cx = aContext->GetNativeContext();
     AutoCxPusher pusher(cx);
     JS::Rooted<JSObject*> global(cx, mScriptGlobalObject->GetGlobalJSObject());
-    xpc_UnmarkGrayObject(global);
+    // XXXkhuey can this ever be null?
+    if (global) {
+      JS::ExposeObjectToActiveJS(global);
+    }
     xpc_UnmarkGrayScript(aScriptObject);
     JSAutoCompartment ac(cx, global);
     JS::Rooted<JS::Value> unused(cx);
     if (!JS_ExecuteScript(cx, global, aScriptObject, unused.address()))
         nsJSUtils::ReportPendingException(cx);
     return NS_OK;
 }
 
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -47,17 +47,22 @@ class nsXULPDGlobalObject : public nsISu
 public:
     nsXULPDGlobalObject(nsXULPrototypeDocument* owner);
 
     // nsISupports interface
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXULPDGlobalObject)
 
     JSObject* GetCompilationGlobal();
-    void UnmarkCompilationGlobal() { xpc_UnmarkGrayObject(mJSObject); }
+    void UnmarkCompilationGlobal()
+    {
+        if (mJSObject) {
+            JS::ExposeObjectToActiveJS(mJSObject);
+        }
+    }
     void Destroy();
     nsIPrincipal* GetPrincipal();
     void ClearGlobalObjectOwner();
 
 protected:
     virtual ~nsXULPDGlobalObject();
 
     nsCOMPtr<nsIPrincipal> mCachedPrincipal;
@@ -725,19 +730,24 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULPDGlobalObject)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULPDGlobalObject)
 
 JSObject *
 nsXULPDGlobalObject::GetCompilationGlobal()
 {
-  if (mJSObject || mDestroyed) {
+  if (mJSObject) {
     // We've been initialized before. This is what we get.
-    return xpc_UnmarkGrayObject(mJSObject);
+    JS::ExposeObjectToActiveJS(mJSObject);
+    return mJSObject;
+  }
+
+  if (mDestroyed) {
+    return nullptr;
   }
 
   AutoSafeJSContext cx;
   JS::CompartmentOptions options;
   options.setZone(JS::SystemZone)
          .setInvisibleToDebugger(true);
   mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
                                  nsJSPrincipals::get(GetPrincipal()),
--- a/dom/base/DOMError.cpp
+++ b/dom/base/DOMError.cpp
@@ -1,19 +1,24 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/DOMErrorBinding.h"
-#include "nsDOMException.h"
 #include "nsPIDOMWindow.h"
 
+// Implemented in DOMException.cpp
+nsresult
+NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
+                                   const char** aMessage,
+                                   uint16_t* aCode = nullptr);
+
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(DOMError, mWindow)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMError)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMError)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMError)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
new file mode 100644
--- /dev/null
+++ b/dom/base/DOMException.cpp
@@ -0,0 +1,708 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/DOMException.h"
+
+#include "jsapi.h"
+#include "jsprf.h"
+#include "js/OldDebugAPI.h"
+#include "mozilla/Util.h"
+#include "mozilla/dom/Exceptions.h"
+#include "nsContentUtils.h"
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionHoldDrop.h"
+#include "nsIClassInfoImpl.h"
+#include "nsIDocument.h"
+#include "nsIDOMDOMException.h"
+#include "nsIException.h"
+#include "nsMemory.h"
+#include "prprf.h"
+#include "xpcprivate.h"
+
+#include "mozilla/dom/DOMExceptionBinding.h"
+
+using namespace mozilla;
+
+enum DOM4ErrorTypeCodeMap {
+  /* DOM4 errors from http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#domexception */
+  IndexSizeError             = nsIDOMDOMException::INDEX_SIZE_ERR,
+  HierarchyRequestError      = nsIDOMDOMException::HIERARCHY_REQUEST_ERR,
+  WrongDocumentError         = nsIDOMDOMException::WRONG_DOCUMENT_ERR,
+  InvalidCharacterError      = nsIDOMDOMException::INVALID_CHARACTER_ERR,
+  NoModificationAllowedError = nsIDOMDOMException::NO_MODIFICATION_ALLOWED_ERR,
+  NotFoundError              = nsIDOMDOMException::NOT_FOUND_ERR,
+  NotSupportedError          = nsIDOMDOMException::NOT_SUPPORTED_ERR,
+  // Can't remove until setNamedItem is removed
+  InUseAttributeError        = nsIDOMDOMException::INUSE_ATTRIBUTE_ERR,
+  InvalidStateError          = nsIDOMDOMException::INVALID_STATE_ERR,
+  SyntaxError                = nsIDOMDOMException::SYNTAX_ERR,
+  InvalidModificationError   = nsIDOMDOMException::INVALID_MODIFICATION_ERR,
+  NamespaceError             = nsIDOMDOMException::NAMESPACE_ERR,
+  InvalidAccessError         = nsIDOMDOMException::INVALID_ACCESS_ERR,
+  TypeMismatchError          = nsIDOMDOMException::TYPE_MISMATCH_ERR,
+  SecurityError              = nsIDOMDOMException::SECURITY_ERR,
+  NetworkError               = nsIDOMDOMException::NETWORK_ERR,
+  AbortError                 = nsIDOMDOMException::ABORT_ERR,
+  URLMismatchError           = nsIDOMDOMException::URL_MISMATCH_ERR,
+  QuotaExceededError         = nsIDOMDOMException::QUOTA_EXCEEDED_ERR,
+  TimeoutError               = nsIDOMDOMException::TIMEOUT_ERR,
+  InvalidNodeTypeError       = nsIDOMDOMException::INVALID_NODE_TYPE_ERR,
+  DataCloneError             = nsIDOMDOMException::DATA_CLONE_ERR,
+  EncodingError              = 0,
+
+  /* XXX Should be JavaScript native errors */
+  TypeError                  = 0,
+  RangeError                 = 0,
+
+  /* IndexedDB errors http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#exceptions */
+  UnknownError             = 0,
+  ConstraintError          = 0,
+  DataError                = 0,
+  TransactionInactiveError = 0,
+  ReadOnlyError            = 0,
+  VersionError             = 0,
+
+  /* File API errors http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException */
+  NotReadableError         = 0,
+
+  /* FileHandle API errors */
+  LockedFileInactiveError = 0,
+};
+
+#define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message},
+#define DOM_MSG_DEF(val, message) {(val), NS_ERROR_GET_CODE(val), #val, message},
+
+static const struct ResultStruct
+{
+  nsresult mNSResult;
+  uint16_t mCode;
+  const char* mName;
+  const char* mMessage;
+} sDOMErrorMsgMap[] = {
+#include "domerr.msg"
+};
+
+#undef DOM4_MSG_DEF
+#undef DOM_MSG_DEF
+
+static void
+NSResultToNameAndMessage(nsresult aNSResult,
+                         const char** aName,
+                         const char** aMessage,
+                         uint16_t* aCode)
+{
+  *aName = nullptr;
+  *aMessage = nullptr;
+  *aCode = 0;
+  for (uint32_t idx = 0; idx < ArrayLength(sDOMErrorMsgMap); idx++) {
+    if (aNSResult == sDOMErrorMsgMap[idx].mNSResult) {
+      *aName = sDOMErrorMsgMap[idx].mName;
+      *aMessage = sDOMErrorMsgMap[idx].mMessage;
+      *aCode = sDOMErrorMsgMap[idx].mCode;
+      return;
+    }
+  }
+
+  NS_WARNING("Huh, someone is throwing non-DOM errors using the DOM module!");
+
+  return;
+}
+
+nsresult
+NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
+                                   const char** aMessage, uint16_t* aCode)
+{
+  const char* name = nullptr;
+  const char* message = nullptr;
+  uint16_t code = 0;
+  NSResultToNameAndMessage(aNSResult, &name, &message, &code);
+
+  if (name && message) {
+    *aName = name;
+    *aMessage = message;
+    if (aCode) {
+      *aCode = code;
+    }
+    return NS_OK;
+  }
+
+  return NS_ERROR_NOT_AVAILABLE;
+}
+
+namespace mozilla {
+namespace dom {
+
+bool Exception::sEverMadeOneFromFactory = false;
+
+NS_IMPL_CLASSINFO(Exception, nullptr, nsIClassInfo::DOM_OBJECT,
+                  NS_XPCEXCEPTION_CID)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Exception)
+  NS_INTERFACE_MAP_ENTRY(nsIException)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCException)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
+  NS_IMPL_QUERY_CLASSINFO(Exception)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(Exception)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(Exception)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(Exception)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Exception)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Exception)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mThrownJSVal);
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Exception)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CI_INTERFACE_GETTER1(Exception, nsIXPCException)
+
+Exception::Exception(const char *aMessage,
+                     nsresult aResult,
+                     const char *aName,
+                     nsIStackFrame *aLocation,
+                     nsISupports *aData)
+: mMessage(nullptr),
+  mResult(NS_OK),
+  mName(nullptr),
+  mLocation(nullptr),
+  mData(nullptr),
+  mFilename(nullptr),
+  mLineNumber(0),
+  mInner(nullptr),
+  mInitialized(false),
+  mHoldingJSVal(false)
+{
+  SetIsDOMBinding();
+
+  // A little hack... The nsIGenericModule nsIClassInfo scheme relies on there
+  // having been at least one instance made via the factory. Otherwise, the
+  // shared factory/classinsance object never gets created and our QI getter
+  // for our instance's pointer to our nsIClassInfo will always return null.
+  // This is bad because it means that wrapped exceptions will never have a
+  // shared prototype. So... We force one to be created via the factory
+  // *once* and then go about our business.
+  if (!sEverMadeOneFromFactory) {
+    nsCOMPtr<nsIXPCException> e =
+        do_CreateInstance(XPC_EXCEPTION_CONTRACTID);
+    sEverMadeOneFromFactory = true;
+  }
+
+  nsCOMPtr<nsIStackFrame> location;
+  if (aLocation) {
+    location = aLocation;
+  } else {
+    location = GetCurrentJSStack();
+    // it is legal for there to be no active JS stack, if C++ code
+    // is operating on a JS-implemented interface pointer without
+    // having been called in turn by JS.  This happens in the JS
+    // component loader, and will become more common as additional
+    // components are implemented in JS.
+  }
+  // We want to trim off any leading native 'dataless' frames
+  if (location) {
+    while (1) {
+      uint32_t language;
+      int32_t lineNumber;
+      if (NS_FAILED(location->GetLanguage(&language)) ||
+          language == nsIProgrammingLanguage::JAVASCRIPT ||
+          NS_FAILED(location->GetLineNumber(&lineNumber)) ||
+          lineNumber) {
+        break;
+      }
+      nsCOMPtr<nsIStackFrame> caller;
+      if (NS_FAILED(location->GetCaller(getter_AddRefs(caller))) || !caller) {
+        break;
+      }
+      location = caller;
+    }
+  }
+
+  Initialize(aMessage, aResult, aName, location, aData, nullptr);
+}
+
+Exception::Exception()
+  : mMessage(nullptr),
+    mResult(NS_OK),
+    mName(nullptr),
+    mFilename(nullptr),
+    mLineNumber(-1),
+    mInitialized(false),
+    mHoldingJSVal(false)
+{
+}
+
+Exception::~Exception()
+{
+  if (mMessage) {
+    nsMemory::Free(mMessage);
+    mMessage = nullptr;
+  }
+  if (mName) {
+    nsMemory::Free(mName);
+    mName = nullptr;
+  }
+  if (mFilename) {
+    nsMemory::Free(mFilename);
+    mFilename = nullptr;
+  }
+
+  if (mHoldingJSVal) {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    mozilla::DropJSObjects(this);
+  }
+}
+
+bool
+Exception::StealJSVal(JS::Value* aVp)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (mHoldingJSVal) {
+    *aVp = mThrownJSVal;
+    mThrownJSVal.setNull();
+
+    mozilla::DropJSObjects(this);
+    mHoldingJSVal = false;
+    return true;
+  }
+
+  return false;
+}
+
+void
+Exception::StowJSVal(JS::Value& aVp)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  mThrownJSVal = aVp;
+  if (!mHoldingJSVal) {
+    mozilla::HoldJSObjects(this);
+    mHoldingJSVal = true;
+  }
+}
+
+/* readonly attribute string message; */
+NS_IMETHODIMP
+Exception::GetMessageMoz(char** aMessage)
+{
+  NS_ENSURE_ARG_POINTER(aMessage);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  if (mMessage) {
+    *aMessage =
+      (char*) nsMemory::Clone(mMessage, sizeof(char)*(strlen(mMessage)+1));
+  } else {
+    *aMessage = nullptr;
+  }
+
+  return NS_OK;
+}
+
+/* readonly attribute nsresult result; */
+NS_IMETHODIMP
+Exception::GetResult(nsresult* aResult)
+{
+  NS_ENSURE_ARG_POINTER(aResult);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  *aResult = mResult;
+  return NS_OK;
+}
+
+/* readonly attribute string name; */
+NS_IMETHODIMP
+Exception::GetName(char** aName)
+{
+  NS_ENSURE_ARG_POINTER(aName);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  const char* name = mName;
+  if (!name) {
+    nsXPCException::NameAndFormatForNSResult(mResult, &name, nullptr);
+  }
+
+  if (name) {
+    *aName = (char*) nsMemory::Clone(name, sizeof(char)*(strlen(name)+1));
+  } else {
+    *aName = nullptr;
+  }
+
+  return NS_OK;
+}
+
+/* readonly attribute string filename; */
+NS_IMETHODIMP
+Exception::GetFilename(char** aFilename)
+{
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+    XPC_STRING_GETTER_BODY(aFilename, mFilename);
+}
+
+/* readonly attribute uint32_t lineNumber; */
+NS_IMETHODIMP
+Exception::GetLineNumber(uint32_t *aLineNumber)
+{
+  NS_ENSURE_ARG_POINTER(aLineNumber);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  *aLineNumber = mLineNumber;
+  return NS_OK;
+}
+
+/* readonly attribute uint32_t columnNumber; */
+NS_IMETHODIMP
+Exception::GetColumnNumber(uint32_t* aColumnNumber)
+{
+  NS_ENSURE_ARG_POINTER(aColumnNumber);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  *aColumnNumber = 0;
+  return NS_OK;
+}
+
+/* readonly attribute nsIStackFrame location; */
+NS_IMETHODIMP
+Exception::GetLocation(nsIStackFrame** aLocation)
+{
+  NS_ENSURE_ARG_POINTER(aLocation);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  nsCOMPtr<nsIStackFrame> location = mLocation;
+  location.forget(aLocation);
+  return NS_OK;
+}
+
+/* readonly attribute nsISupports data; */
+NS_IMETHODIMP
+Exception::GetData(nsISupports** aData)
+{
+  NS_ENSURE_ARG_POINTER(aData);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  nsCOMPtr<nsISupports> data = mData;
+  data.forget(aData);
+  return NS_OK;
+}
+
+/* readonly attribute nsIException inner; */
+NS_IMETHODIMP
+Exception::GetInner(nsIException** aException)
+{
+  NS_ENSURE_ARG_POINTER(aException);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  nsCOMPtr<nsIException> inner = mInner;
+  inner.forget(aException);
+  return NS_OK;
+}
+
+/* string toString (); */
+NS_IMETHODIMP
+Exception::ToString(char **_retval)
+{
+  NS_ENSURE_ARG_POINTER(_retval);
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  static const char defaultMsg[] = "<no message>";
+  static const char defaultLocation[] = "<unknown>";
+  static const char format[] =
+"[Exception... \"%s\"  nsresult: \"0x%x (%s)\"  location: \"%s\"  data: %s]";
+
+  char* indicatedLocation = nullptr;
+
+  if (mLocation) {
+    // we need to free this if it does not fail
+    nsresult rv = mLocation->ToString(&indicatedLocation);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  const char* msg = mMessage ? mMessage : nullptr;
+  const char* location = indicatedLocation ?
+                              indicatedLocation : defaultLocation;
+  const char* resultName = mName;
+  if (!resultName &&
+      !nsXPCException::NameAndFormatForNSResult(mResult, &resultName,
+                                                (!msg) ? &msg : nullptr)) {
+    if (!msg) {
+      msg = defaultMsg;
+    }
+    resultName = "<unknown>";
+  }
+  const char* data = mData ? "yes" : "no";
+
+  char* temp = JS_smprintf(format, msg, mResult, resultName, location, data);
+  if (indicatedLocation) {
+    nsMemory::Free(indicatedLocation);
+  }
+
+  char* final = nullptr;
+  if (temp) {
+    final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1));
+    JS_smprintf_free(temp);
+  }
+
+  *_retval = final;
+  return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/* void initialize (in string aMessage, in nsresult aResult, in string aName, in nsIStackFrame aLocation, in nsISupports aData, in nsIException aInner); */
+NS_IMETHODIMP
+Exception::Initialize(const char *aMessage, nsresult aResult, const char *aName, nsIStackFrame *aLocation, nsISupports *aData, nsIException *aInner)
+{
+  NS_ENSURE_FALSE(mInitialized, NS_ERROR_ALREADY_INITIALIZED);
+
+  if (aMessage) {
+    mMessage =
+      (char*) nsMemory::Clone(aMessage, sizeof(char)*(strlen(aMessage)+1));
+  }
+
+  if (aName) {
+    mName = (char*) nsMemory::Clone(aName, sizeof(char)*(strlen(aName)+1));
+  }
+
+  mResult = aResult;
+
+  if (aLocation) {
+    mLocation = aLocation;
+    // For now, fill in our location details from our stack frame.
+    // Later we may allow other locations?
+    nsresult rc;
+    if (NS_FAILED(rc = aLocation->GetFilename(&mFilename))) {
+      return rc;
+    }
+    if (NS_FAILED(rc = aLocation->GetLineNumber(&mLineNumber))) {
+      return rc;
+    }
+  } else {
+    nsresult rv;
+    nsXPConnect* xpc = nsXPConnect::XPConnect();
+    rv = xpc->GetCurrentJSStack(getter_AddRefs(mLocation));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+
+  mData = aData;
+  mInner = aInner;
+
+  mInitialized = true;
+  return NS_OK;
+}
+
+JSObject*
+Exception::WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
+{
+  return ExceptionBinding::Wrap(cx, scope, this);
+}
+
+void
+Exception::GetMessageMoz(nsString& retval)
+{
+  char* str = nullptr;
+#ifdef DEBUG
+  DebugOnly<nsresult> rv = 
+#endif
+  GetMessageMoz(&str);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  CopyUTF8toUTF16(str, retval);
+  nsMemory::Free(str);
+}
+
+uint32_t
+Exception::Result() const
+{
+  return (uint32_t)mResult;
+}
+
+void
+Exception::GetName(nsString& retval)
+{
+  char* str = nullptr;
+#ifdef DEBUG
+  DebugOnly<nsresult> rv =
+#endif
+  GetName(&str);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  CopyUTF8toUTF16(str, retval);
+  nsMemory::Free(str);
+}
+
+void
+Exception::GetFilename(nsString& retval)
+{
+  char* str = nullptr;
+#ifdef DEBUG
+  DebugOnly<nsresult> rv =
+#endif
+  GetFilename(&str);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  CopyUTF8toUTF16(str, retval);
+  nsMemory::Free(str);
+}
+
+uint32_t
+Exception::LineNumber() const
+{
+  return mLineNumber;
+}
+
+uint32_t
+Exception::ColumnNumber() const
+{
+  return 0;
+}
+
+already_AddRefed<nsIStackFrame>
+Exception::GetLocation() const
+{
+  nsCOMPtr<nsIStackFrame> location = mLocation;
+  return location.forget();
+}
+
+already_AddRefed<nsISupports>
+Exception::GetInner() const
+{
+  nsCOMPtr<nsIException> inner = mInner;
+  return inner.forget();
+}
+
+already_AddRefed<nsISupports>
+Exception::GetData() const
+{
+  nsCOMPtr<nsISupports> data = mData;
+  return data.forget();
+}
+
+void
+Exception::Stringify(nsString& retval)
+{
+  char* str = nullptr;
+#ifdef DEBUG
+  DebugOnly<nsresult> rv =
+#endif
+  ToString(&str);
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  CopyUTF8toUTF16(str, retval);
+  nsMemory::Free(str);
+}
+
+NS_IMPL_ADDREF_INHERITED(DOMException, Exception)
+NS_IMPL_RELEASE_INHERITED(DOMException, Exception)
+NS_INTERFACE_MAP_BEGIN(DOMException)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMDOMException)
+NS_INTERFACE_MAP_END_INHERITING(Exception)
+
+DOMException::DOMException(nsresult aRv, const char* aMessage,
+                           const char* aName, uint16_t aCode)
+  : Exception(nullptr, aRv, nullptr, nullptr, nullptr),
+    mName(aName),
+    mMessage(aMessage),
+    mCode(aCode)
+{
+  SetIsDOMBinding();
+}
+
+NS_IMETHODIMP
+DOMException::GetCode(uint16_t* aCode)
+{
+  NS_ENSURE_ARG_POINTER(aCode);
+  *aCode = mCode;
+
+  // Warn only when the code was changed (other than DOM Core)
+  // or the code is useless (zero)
+  if (NS_ERROR_GET_MODULE(mResult) != NS_ERROR_MODULE_DOM || !mCode) {
+    nsCOMPtr<nsIDocument> doc = nsContentUtils::GetDocumentFromCaller();
+    if (doc) {
+      doc->WarnOnceAbout(nsIDocument::eDOMExceptionCode);
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMException::ToString(char **aReturn)
+{
+  *aReturn = nullptr;
+
+  static const char defaultMsg[] = "<no message>";
+  static const char defaultLocation[] = "<unknown>";
+  static const char defaultName[] = "<unknown>";
+  static const char format[] =
+    "[Exception... \"%s\"  code: \"%d\" nsresult: \"0x%x (%s)\"  location: \"%s\"]";
+
+  nsAutoCString location;
+
+  if (mInner) {
+    nsXPIDLCString filename;
+
+    mInner->GetFilename(getter_Copies(filename));
+
+    if (!filename.IsEmpty()) {
+      uint32_t line_nr = 0;
+
+      mInner->GetLineNumber(&line_nr);
+
+      char *temp = PR_smprintf("%s Line: %d", filename.get(), line_nr);
+      if (temp) {
+        location.Assign(temp);
+        PR_smprintf_free(temp);
+      }
+    }
+  }
+
+  if (location.IsEmpty()) {
+    location = defaultLocation;
+  }
+
+  const char* msg = mMessage ? mMessage : defaultMsg;
+  const char* resultName = mName ? mName : defaultName;
+
+  *aReturn = PR_smprintf(format, msg, mCode, mResult, resultName,
+                         location.get());
+
+  return *aReturn ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+void
+DOMException::GetName(nsString& retval)
+{
+  CopyUTF8toUTF16(mName, retval);
+}
+
+void
+DOMException::GetMessageMoz(nsString& retval)
+{
+  CopyUTF8toUTF16(mMessage, retval);
+}
+
+JSObject*
+DOMException::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return DOMExceptionBinding::Wrap(aCx, aScope, this);
+}
+
+/* static */already_AddRefed<DOMException>
+DOMException::Create(nsresult aRv)
+{
+  const char* name;
+  const char* message;
+  uint16_t code;
+  NSResultToNameAndMessage(aRv, &name, &message, &code);
+  nsRefPtr<DOMException> inst =
+    new DOMException(aRv, message, name, code);
+  return inst.forget();
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/base/DOMException.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_DOMException_h__
+#define mozilla_dom_DOMException_h__
+
+// We intentionally shadow non-virtual methods, but gcc gets confused.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Woverloaded-virtual"
+#endif
+
+#include <stdint.h>
+#include "jspubtd.h"
+#include "js/GCAPI.h"
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsID.h"
+#include "nsIDOMDOMException.h"
+#include "nsWrapperCache.h"
+#include "xpcexception.h"
+
+class nsIStackFrame;
+class nsString;
+
+nsresult
+NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
+                                   const char** aMessage,
+                                   uint16_t* aCode = nullptr);
+
+namespace mozilla {
+namespace dom {
+
+#define MOZILLA_EXCEPTION_IID \
+{ 0x55eda557, 0xeba0, 0x4fe3, \
+  { 0xae, 0x2e, 0xf3, 0x94, 0x49, 0x23, 0x62, 0xd6 } }
+
+class Exception : public nsIXPCException,
+                  public nsWrapperCache
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_EXCEPTION_IID)
+
+  NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCEXCEPTION_CID)
+
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Exception)
+  
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_NSIEXCEPTION
+  NS_DECL_NSIXPCEXCEPTION
+
+  // Cruft used by XPConnect for exceptions originating in JS implemented
+  // components.
+  bool StealJSVal(JS::Value* aVp);
+  void StowJSVal(JS::Value& aVp);
+
+  // WebIDL API
+  virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
+    MOZ_OVERRIDE;
+
+  nsISupports* GetParentObject() const { return nullptr; }
+
+  void GetMessageMoz(nsString& retval);
+
+  uint32_t Result() const;
+
+  void GetName(nsString& retval);
+
+  void GetFilename(nsString& retval);
+
+  uint32_t LineNumber() const;
+
+  uint32_t ColumnNumber() const;
+
+  already_AddRefed<nsIStackFrame> GetLocation() const;
+
+  already_AddRefed<nsISupports> GetInner() const;
+
+  already_AddRefed<nsISupports> GetData() const;
+
+  void Stringify(nsString& retval);
+
+  // XPCOM factory ctor.
+  Exception();
+
+  Exception(const char *aMessage,
+            nsresult aResult,
+            const char *aName,
+            nsIStackFrame *aLocation,
+            nsISupports *aData);
+
+protected:
+  virtual ~Exception();
+
+  char*           mMessage;
+  nsresult        mResult;
+  char*           mName;
+  nsCOMPtr<nsIStackFrame> mLocation;
+  nsCOMPtr<nsISupports> mData;
+  char*           mFilename;
+  int             mLineNumber;
+  nsCOMPtr<nsIException> mInner;
+  bool            mInitialized;
+
+  bool mHoldingJSVal;
+  JS::Heap<JS::Value> mThrownJSVal;
+
+private:
+  static bool sEverMadeOneFromFactory;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(Exception, MOZILLA_EXCEPTION_IID)
+
+class DOMException : public Exception,
+                     public nsIDOMDOMException
+{
+public:
+  DOMException(nsresult aRv, const char* aMessage,
+               const char* aName, uint16_t aCode);
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDOMDOMEXCEPTION
+
+  // nsIException overrides
+  NS_IMETHOD ToString(char **aReturn) MOZ_OVERRIDE;
+
+  // nsWrapperCache overrides
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+    MOZ_OVERRIDE;
+
+  uint16_t Code() const {
+    return mCode;
+  }
+
+  // Intentionally shadow the nsXPCException version.
+  void GetMessageMoz(nsString& retval);
+  void GetName(nsString& retval);
+
+  static already_AddRefed<DOMException>
+  Create(nsresult aRv);
+
+protected:
+
+  virtual ~DOMException() {}
+
+  // Intentionally shadow the nsXPCException version.
+  const char* mName;
+  const char* mMessage;
+
+  uint16_t mCode;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#endif
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1481,17 +1481,17 @@ Navigator::DoNewResolve(JSContext* aCx, 
                         JS::MutableHandle<JS::Value> aValue)
 {
   if (!JSID_IS_STRING(aId)) {
     return true;
   }
 
   nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager();
   if (!nameSpaceManager) {
-    return Throw<true>(aCx, NS_ERROR_NOT_INITIALIZED);
+    return Throw(aCx, NS_ERROR_NOT_INITIALIZED);
   }
 
   nsDependentJSString name(aId);
 
   const nsGlobalNameStruct* name_struct =
     nameSpaceManager->LookupNavigatorName(name);
   if (!name_struct) {
     return true;
@@ -1500,17 +1500,17 @@ Navigator::DoNewResolve(JSContext* aCx, 
   if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding) {
     ConstructNavigatorProperty construct = name_struct->mConstructNavigatorProperty;
     MOZ_ASSERT(construct);
 
     JS::Rooted<JSObject*> naviObj(aCx,
                                   js::CheckedUnwrap(aObject,
                                                     /* stopAtOuter = */ false));
     if (!naviObj) {
-      return Throw<true>(aCx, NS_ERROR_DOM_SECURITY_ERR);
+      return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR);
     }
 
     JS::Rooted<JSObject*> domObject(aCx);
     {
       JSAutoCompartment ac(aCx, naviObj);
 
       // Check whether our constructor is enabled after we unwrap Xrays, since
       // we don't want to define an interface on the Xray if it's disabled in
@@ -1526,17 +1526,17 @@ Navigator::DoNewResolve(JSContext* aCx, 
         if (!hasPermission) {
           aValue.setNull();
           return true;
         }
       }
 
       domObject = construct(aCx, naviObj);
       if (!domObject) {
-        return Throw<true>(aCx, NS_ERROR_FAILURE);
+        return Throw(aCx, NS_ERROR_FAILURE);
       }
     }
 
     if (!JS_WrapObject(aCx, domObject.address())) {
       return false;
     }
 
     aValue.setObject(*domObject);
@@ -1545,46 +1545,46 @@ Navigator::DoNewResolve(JSContext* aCx, 
 
   NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty,
                "unexpected type");
 
   nsresult rv = NS_OK;
 
   nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
   if (NS_FAILED(rv)) {
-    return Throw<true>(aCx, rv);
+    return Throw(aCx, rv);
   }
 
   JS::Rooted<JS::Value> prop_val(aCx, JS::UndefinedValue()); // Property value.
 
   nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
 
   if (gpi) {
     if (!mWindow) {
-      return Throw<true>(aCx, NS_ERROR_UNEXPECTED);
+      return Throw(aCx, NS_ERROR_UNEXPECTED);
     }
 
     rv = gpi->Init(mWindow, prop_val.address());
     if (NS_FAILED(rv)) {
-      return Throw<true>(aCx, rv);
+      return Throw(aCx, rv);
     }
   }
 
   if (JSVAL_IS_PRIMITIVE(prop_val) && !JSVAL_IS_NULL(prop_val)) {
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     rv = nsContentUtils::WrapNative(aCx, aObject, native, prop_val.address(),
                                     getter_AddRefs(holder), true);
 
     if (NS_FAILED(rv)) {
-      return Throw<true>(aCx, rv);
+      return Throw(aCx, rv);
     }
   }
 
   if (!JS_WrapValue(aCx, prop_val.address())) {
-    return Throw<true>(aCx, NS_ERROR_UNEXPECTED);
+    return Throw(aCx, NS_ERROR_UNEXPECTED);
   }
 
   aValue.set(prop_val);
   return true;
 }
 
 static PLDHashOperator
 SaveNavigatorName(const nsAString& aName, void* aClosure)
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -17,17 +17,16 @@ XPIDL_SOURCES += [
 MODULE = 'dom'
 
 EXPORTS += [
     'Crypto.h',
     'nsContentPermissionHelper.h',
     'nsDOMCID.h',
     'nsDOMClassInfoClasses.h',
     'nsDOMClassInfoID.h',
-    'nsDOMException.h',
     'nsDOMJSUtils.h',
     'nsDOMNavigationTiming.h',
     'nsDOMString.h',
     'nsFocusManager.h',
     'nsIDOMClassInfo.h',
     'nsIDOMScriptObjectFactory.h',
     'nsIGlobalObject.h',
     'nsIJSEventListener.h',
@@ -49,36 +48,37 @@ EXPORTS += [
     'nsWrapperCache.h',
     'nsWrapperCacheInlines.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'BarProps.h',
     'DOMCursor.h',
     'DOMError.h',
+    'DOMException.h',
     'DOMRequest.h',
     'MessageChannel.h',
     'MessagePort.h',
     'ScreenOrientation.h',
     'StructuredCloneTags.h',
     'URL.h',
 ]
 
 CPP_SOURCES += [
     'BarProps.cpp',
     'Crypto.cpp',
     'DOMCursor.cpp',
     'DOMError.cpp',
+    'DOMException.cpp',
     'DOMRequest.cpp',
     'Navigator.cpp',
     'MessageChannel.cpp',
     'MessagePort.cpp',
     'nsContentPermissionHelper.cpp',
     'nsDOMClassInfo.cpp',
-    'nsDOMException.cpp',
     'nsDOMNavigationTiming.cpp',
     'nsDOMScriptObjectFactory.cpp',
     'nsDOMWindowList.cpp',
     'nsDOMWindowUtils.cpp',
     'nsFocusManager.cpp',
     'nsGlobalWindow.cpp',
     'nsGlobalWindowCommands.cpp',
     'nsHistory.cpp',
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -72,17 +72,16 @@
 #include "nsPIDOMWindow.h"
 #include "nsIDOMJSWindow.h"
 #include "nsIDOMMediaList.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMConstructor.h"
 
 // DOM core includes
 #include "nsError.h"
-#include "nsIDOMDOMException.h"
 #include "nsIDOMDOMStringList.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsIDOMLoadStatus.h"
 #include "nsIDOMXPathNamespace.h"
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULCheckboxElement.h"
 #include "nsIDOMXULPopupElement.h"
 
@@ -333,20 +332,16 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_BASE_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_PRECREATE |
                            nsIXPCScriptable::WANT_NEWRESOLVE |
                            nsIXPCScriptable::WANT_HASINSTANCE |
                            nsIXPCScriptable::WANT_CALL |
                            nsIXPCScriptable::WANT_CONSTRUCT |
                            nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
 
-  // Core classes
-  NS_DEFINE_CLASSINFO_DATA(DOMException, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   // Misc Core related classes
 
   NS_DEFINE_CLASSINFO_DATA(DeviceAcceleration, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DeviceRotationRate, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // CSS classes
@@ -1105,21 +1100,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DOMConstructor, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(DOMException, nsIDOMDOMException)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMException)
-    DOM_CLASSINFO_MAP_ENTRY(nsIException)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(DeviceAcceleration, nsIDOMDeviceAcceleration)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceAcceleration)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DeviceRotationRate, nsIDOMDeviceRotationRate)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceRotationRate)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -4,19 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 // IWYU pragma: private, include "nsDOMClassInfoID.h"
 
 DOMCI_CLASS(Window)
 DOMCI_CLASS(Location)
 DOMCI_CLASS(DOMPrototype)
 DOMCI_CLASS(DOMConstructor)
 
-// Core classes
-DOMCI_CLASS(DOMException)
-
 DOMCI_CLASS(DeviceAcceleration)
 DOMCI_CLASS(DeviceRotationRate)
 
 // CSS classes
 DOMCI_CLASS(CSSStyleRule)
 DOMCI_CLASS(CSSCharsetRule)
 DOMCI_CLASS(CSSImportRule)
 DOMCI_CLASS(CSSMediaRule)
deleted file mode 100644
--- a/dom/base/nsDOMException.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsDOMException.h"
-
-#include "mozilla/Util.h"
-#include "nsCOMPtr.h"
-#include "nsCRTGlue.h"
-#include "nsContentUtils.h"
-#include "nsDOMClassInfoID.h"
-#include "nsError.h"
-#include "nsIDOMDOMException.h"
-#include "nsIDocument.h"
-#include "nsString.h"
-#include "prprf.h"
-#include "nsIException.h"
-
-using namespace mozilla;
-
-enum DOM4ErrorTypeCodeMap {
-  /* DOM4 errors from http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#domexception */
-  IndexSizeError             = nsIDOMDOMException::INDEX_SIZE_ERR,
-  HierarchyRequestError      = nsIDOMDOMException::HIERARCHY_REQUEST_ERR,
-  WrongDocumentError         = nsIDOMDOMException::WRONG_DOCUMENT_ERR,
-  InvalidCharacterError      = nsIDOMDOMException::INVALID_CHARACTER_ERR,
-  NoModificationAllowedError = nsIDOMDOMException::NO_MODIFICATION_ALLOWED_ERR,
-  NotFoundError              = nsIDOMDOMException::NOT_FOUND_ERR,
-  NotSupportedError          = nsIDOMDOMException::NOT_SUPPORTED_ERR,
-  // Can't remove until setNamedItem is removed
-  InUseAttributeError        = nsIDOMDOMException::INUSE_ATTRIBUTE_ERR,
-  InvalidStateError          = nsIDOMDOMException::INVALID_STATE_ERR,
-  SyntaxError                = nsIDOMDOMException::SYNTAX_ERR,
-  InvalidModificationError   = nsIDOMDOMException::INVALID_MODIFICATION_ERR,
-  NamespaceError             = nsIDOMDOMException::NAMESPACE_ERR,
-  InvalidAccessError         = nsIDOMDOMException::INVALID_ACCESS_ERR,
-  TypeMismatchError          = nsIDOMDOMException::TYPE_MISMATCH_ERR,
-  SecurityError              = nsIDOMDOMException::SECURITY_ERR,
-  NetworkError               = nsIDOMDOMException::NETWORK_ERR,
-  AbortError                 = nsIDOMDOMException::ABORT_ERR,
-  URLMismatchError           = nsIDOMDOMException::URL_MISMATCH_ERR,
-  QuotaExceededError         = nsIDOMDOMException::QUOTA_EXCEEDED_ERR,
-  TimeoutError               = nsIDOMDOMException::TIMEOUT_ERR,
-  InvalidNodeTypeError       = nsIDOMDOMException::INVALID_NODE_TYPE_ERR,
-  DataCloneError             = nsIDOMDOMException::DATA_CLONE_ERR,
-  EncodingError              = 0,
-
-  /* XXX Should be JavaScript native errors */
-  TypeError                  = 0,
-  RangeError                 = 0,
-
-  /* IndexedDB errors http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#exceptions */
-  UnknownError             = 0,
-  ConstraintError          = 0,
-  DataError                = 0,
-  TransactionInactiveError = 0,
-  ReadOnlyError            = 0,
-  VersionError             = 0,
-
-  /* File API errors http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException */
-  NotReadableError         = 0,
-
-  /* FileHandle API errors */
-  LockedFileInactiveError = 0,
-};
-
-#define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message},
-#define DOM_MSG_DEF(val, message) {(val), NS_ERROR_GET_CODE(val), #val, message},
-
-static const struct ResultStruct
-{
-  nsresult mNSResult;
-  uint16_t mCode;
-  const char* mName;
-  const char* mMessage;
-} sDOMErrorMsgMap[] = {
-#include "domerr.msg"
-};
-
-#undef DOM4_MSG_DEF
-#undef DOM_MSG_DEF
-
-static void
-NSResultToNameAndMessage(nsresult aNSResult,
-                         const char** aName,
-                         const char** aMessage,
-                         uint16_t* aCode)
-{
-  *aName = nullptr;
-  *aMessage = nullptr;
-  *aCode = 0;
-  for (uint32_t idx = 0; idx < ArrayLength(sDOMErrorMsgMap); idx++) {
-    if (aNSResult == sDOMErrorMsgMap[idx].mNSResult) {
-      *aName = sDOMErrorMsgMap[idx].mName;
-      *aMessage = sDOMErrorMsgMap[idx].mMessage;
-      *aCode = sDOMErrorMsgMap[idx].mCode;
-      return;
-    }
-  }
-
-  NS_WARNING("Huh, someone is throwing non-DOM errors using the DOM module!");
-
-  return;
-}
-
-nsresult
-NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
-                                   const char** aMessage, uint16_t* aCode)
-{
-  const char* name = nullptr;
-  const char* message = nullptr;
-  uint16_t code = 0;
-  NSResultToNameAndMessage(aNSResult, &name, &message, &code);
-
-  if (name && message) {
-    *aName = name;
-    *aMessage = message;
-    if (aCode) {
-      *aCode = code;
-    }
-    return NS_OK;
-  }
-
-  return NS_ERROR_NOT_AVAILABLE;
-}
-
-
-class nsDOMException : public nsIException,
-                       public nsIDOMDOMException
-{
-public:
-  nsDOMException() {}
-  virtual ~nsDOMException() {}
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIEXCEPTION
-  NS_IMETHOD Init(nsresult aNSResult, const char* aName,
-                  const char* aMessage, uint16_t aCode,
-                  nsIException* aDefaultException);
-  NS_DECL_NSIDOMDOMEXCEPTION
-
-protected:
-  const char* mName;
-  const char* mMessage;
-  nsCOMPtr<nsIException> mInner;
-  nsresult mResult;
-  uint16_t mCode;
-};
-
-DOMCI_DATA(DOMException, nsDOMException) 
-
-NS_IMPL_ADDREF(nsDOMException)
-NS_IMPL_RELEASE(nsDOMException)
-NS_INTERFACE_MAP_BEGIN(nsDOMException)
-  NS_INTERFACE_MAP_ENTRY(nsIException)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMDOMException)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMException)
-NS_INTERFACE_MAP_END
-
-nsresult
-NS_NewDOMException(nsresult aNSResult, nsIException* aDefaultException,
-                   nsIException** aException)
-{
-  const char* name;
-  const char* message;
-  uint16_t code;
-  NSResultToNameAndMessage(aNSResult, &name, &message, &code);
-  nsDOMException* inst = new nsDOMException();
-  inst->Init(aNSResult, name, message, code, aDefaultException);
-  *aException = inst;
-  NS_ADDREF(*aException);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetCode(uint16_t* aCode)
-{
-  NS_ENSURE_ARG_POINTER(aCode);
-  *aCode = mCode;
-
-  // Warn only when the code was changed (other than DOM Core)
-  // or the code is useless (zero)
-  if (NS_ERROR_GET_MODULE(mResult) != NS_ERROR_MODULE_DOM || !mCode) {
-    nsCOMPtr<nsIDocument> doc = nsContentUtils::GetDocumentFromCaller();
-    if (doc) {
-      doc->WarnOnceAbout(nsIDocument::eDOMExceptionCode);
-    }
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetMessageMoz(char **aMessage)
-{
-  if (mMessage) {
-    *aMessage = NS_strdup(mMessage);
-  } else {
-    *aMessage = nullptr;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetResult(nsresult* aResult)
-{
-  NS_ENSURE_ARG_POINTER(aResult);
-
-  *aResult = mResult;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetName(char **aName)
-{
-  NS_ENSURE_ARG_POINTER(aName);
-
-  if (mName) {
-    *aName = NS_strdup(mName);
-  } else {
-    *aName = nullptr;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetFilename(char **aFilename)
-{
-  if (mInner) {
-    return mInner->GetFilename(aFilename);
-  }
-
-  NS_ENSURE_ARG_POINTER(aFilename);
-
-  *aFilename = nullptr;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetLineNumber(uint32_t *aLineNumber)
-{
-  if (mInner) {
-    return mInner->GetLineNumber(aLineNumber);
-  }
-
-  NS_ENSURE_ARG_POINTER(aLineNumber);
-
-  *aLineNumber = 0;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetColumnNumber(uint32_t *aColumnNumber)
-{
-  if (mInner) {
-    return mInner->GetColumnNumber(aColumnNumber);
-  }
-
-  NS_ENSURE_ARG_POINTER(aColumnNumber);
-
-  *aColumnNumber = 0;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetLocation(nsIStackFrame **aLocation)
-{
-  if (mInner) {
-    return mInner->GetLocation(aLocation);
-  }
-
-  NS_ENSURE_ARG_POINTER(aLocation);
-
-  *aLocation = nullptr;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetInner(nsIException **aInner)
-{
-  NS_ENSURE_ARG_POINTER(aInner);
-
-  *aInner = nullptr;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::GetData(nsISupports **aData)
-{
-  if (mInner) {
-    return mInner->GetData(aData);
-  }
-
-  NS_ENSURE_ARG_POINTER(aData);
-
-  *aData = nullptr;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMException::ToString(char **aReturn)
-{
-  *aReturn = nullptr;
-
-  static const char defaultMsg[] = "<no message>";
-  static const char defaultLocation[] = "<unknown>";
-  static const char defaultName[] = "<unknown>";
-  static const char format[] =
-    "[Exception... \"%s\"  code: \"%d\" nsresult: \"0x%x (%s)\"  location: \"%s\"]";
-
-  nsAutoCString location;
-
-  if (mInner) {
-    nsXPIDLCString filename;
-
-    mInner->GetFilename(getter_Copies(filename));
-
-    if (!filename.IsEmpty()) {
-      uint32_t line_nr = 0;
-
-      mInner->GetLineNumber(&line_nr);
-
-      char *temp = PR_smprintf("%s Line: %d", filename.get(), line_nr);
-      if (temp) {
-        location.Assign(temp);
-        PR_smprintf_free(temp);
-      }
-    }
-  }
-
-  if (location.IsEmpty()) {
-    location = defaultLocation;
-  }
-
-  const char* msg = mMessage ? mMessage : defaultMsg;
-  const char* resultName = mName ? mName : defaultName;
-
-  *aReturn = PR_smprintf(format, msg, mCode, mResult, resultName,
-                         location.get());
-
-  return *aReturn ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-NS_IMETHODIMP
-nsDOMException::Init(nsresult aNSResult, const char* aName,
-                     const char* aMessage, uint16_t aCode,
-                     nsIException* aDefaultException)
-{
-  mResult = aNSResult;
-  mName = aName;
-  mMessage = aMessage;
-  mCode = aCode;
-  mInner = aDefaultException;
-  return NS_OK;
-}
deleted file mode 100644
--- a/dom/base/nsDOMException.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/NullPtr.h"
-#include "nsError.h"
-class nsIException;
-
-nsresult
-NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
-                                   const char** aMessage,
-                                   uint16_t* aCode = nullptr);
-
-nsresult
-NS_NewDOMException(nsresult aNSResult, nsIException* aDefaultException,
-                   nsIException** aException);
--- a/dom/base/nsDOMScriptObjectFactory.cpp
+++ b/dom/base/nsDOMScriptObjectFactory.cpp
@@ -19,17 +19,16 @@
  *                               use in OS2
  */
 
 #include "nsDOMScriptObjectFactory.h"
 #include "nsScriptNameSpaceManager.h"
 #include "nsIObserverService.h"
 #include "nsJSEnvironment.h"
 #include "nsGlobalWindow.h"
-#include "nsDOMException.h"
 #include "nsCRT.h"
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 #include "nsThreadUtils.h"
 
 using mozilla::dom::GetNameSpaceManager;
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1554,17 +1554,17 @@ NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindow)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindow)
 
 static PLDHashOperator
 MarkXBLHandlers(nsXBLPrototypeHandler* aKey, JS::Heap<JSObject*>& aData, void* aClosure)
 {
-  xpc_UnmarkGrayObject(aData);
+  JS::ExposeObjectToActiveJS(aData);
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
   if (tmp->IsBlackForCC()) {
     if (tmp->mCachedXBLPrototypeHandlers) {
       tmp->mCachedXBLPrototypeHandlers->Enumerate(MarkXBLHandlers, nullptr);
     }
@@ -2243,23 +2243,23 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   if (reUseInnerWindow) {
     // We're reusing the current inner window.
     NS_ASSERTION(!currentInner->IsFrozen(),
                  "We should never be reusing a shared inner window");
     newInnerWindow = currentInner;
 
     if (aDocument != oldDoc) {
       JS::Rooted<JSObject*> obj(cx, currentInner->mJSObject);
-      xpc_UnmarkGrayObject(obj);
+      JS::ExposeObjectToActiveJS(obj);
     }
 
     // We're reusing the inner window, but this still counts as a navigation,
     // so all expandos and such defined on the outer window should go away. Force
     // all Xray wrappers to be recomputed.
-    xpc_UnmarkGrayObject(mJSObject);
+    JS::ExposeObjectToActiveJS(mJSObject);
     if (!JS_RefreshCrossCompartmentWrappers(cx, mJSObject)) {
       return NS_ERROR_FAILURE;
     }
 
     // Inner windows are only reused for same-origin principals, but the principals
     // don't necessarily match exactly. Update the principal on the compartment to
     // match the new document.
     // NB: We don't just call currentInner->RefreshCompartmentPrincipals() here
@@ -2354,18 +2354,18 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
     if (!mJSObject) {
       CreateOuterObject(newInnerWindow);
       mContext->DidInitializeContext();
 
       mJSObject = mContext->GetWindowProxy();
       SetWrapper(mJSObject);
     } else {
-      JS::Rooted<JSObject*> global(cx,
-        xpc_UnmarkGrayObject(newInnerWindow->mJSObject));
+      JS::ExposeObjectToActiveJS(newInnerWindow->mJSObject);
+      JS::Rooted<JSObject*> global(cx, newInnerWindow->mJSObject);
       JS::Rooted<JSObject*> outerObject(cx,
         NewOuterWindowProxy(cx, global, thisChrome));
       if (!outerObject) {
         NS_ERROR("out of memory");
         return NS_ERROR_FAILURE;
       }
 
       js::SetProxyExtra(mJSObject, 0, js::PrivateValue(NULL));
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -24,16 +24,17 @@
 
 // Interfaces Needed
 #include "nsIBrowserDOMWindow.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIDOMJSWindow.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIScriptGlobalObject.h"
+#include "nsIScriptObjectPrincipal.h"
 #include "nsITimer.h"
 #include "nsIDOMModalContentWindow.h"
 #include "nsEventListenerManager.h"
 #include "nsIPrincipal.h"
 #include "nsSize.h"
 #include "mozFlushType.h"
 #include "prclist.h"
 #include "nsIDOMStorageEvent.h"
@@ -282,16 +283,17 @@ private:
 // objects that are still in memory (and in reality all inner window
 // object's lists also contain its outer and all other inner windows
 // belonging to the same outer window, but that's an unimportant
 // side effect of inheriting PRCList).
 
 class nsGlobalWindow : public mozilla::dom::EventTarget,
                        public nsPIDOMWindow,
                        public nsIScriptGlobalObject,
+                       public nsIScriptObjectPrincipal,
                        public nsIDOMJSWindow,
                        public nsSupportsWeakReference,
                        public nsIInterfaceRequestor,
                        public PRCListStr,
                        public nsIDOMWindowPerformance,
                        public nsITouchEventReceiver,
                        public nsIInlineEventHandlers
 #ifdef MOZ_B2G
--- a/dom/base/nsIGlobalObject.h
+++ b/dom/base/nsIGlobalObject.h
@@ -2,24 +2,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsIGlobalObject_h__
 #define nsIGlobalObject_h__
 
 #include "nsISupports.h"
-#include "nsIScriptObjectPrincipal.h"
 #include "js/TypeDecls.h"
 
 #define NS_IGLOBALOBJECT_IID \
-{ 0x8503e9a9, 0x530, 0x4b26,  \
-{ 0xae, 0x24, 0x18, 0xca, 0x38, 0xe5, 0xed, 0x17 } }
+{ 0xe2538ded, 0x13ef, 0x4f4d, \
+{ 0x94, 0x6b, 0x65, 0xd3, 0x33, 0xb4, 0xf0, 0x3c } }
 
-class nsIGlobalObject : public nsIScriptObjectPrincipal
+class nsIGlobalObject : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID)
 
   virtual JSObject* GetGlobalJSObject() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject,
--- a/dom/base/nsIJSEventListener.h
+++ b/dom/base/nsIJSEventListener.h
@@ -196,17 +196,22 @@ public:
   void Disconnect()
   {
     mTarget = nullptr;
   }
 
   // Can return null if we already have a handler.
   JSObject* GetEventScope() const
   {
-    return xpc_UnmarkGrayObject(mScopeObject);
+    if (!mScopeObject) {
+      return nullptr;
+    }
+
+    JS::ExposeObjectToActiveJS(mScopeObject);
+    return mScopeObject;
   }
 
   const nsEventHandler& GetHandler() const
   {
     return mHandler;
   }
 
   nsIAtom* EventName() const
--- a/dom/base/nsIScriptGlobalObject.h
+++ b/dom/base/nsIScriptGlobalObject.h
@@ -23,18 +23,18 @@ class nsIScriptGlobalObject;
 // aStatus will be filled in with the status.
 bool
 NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
                      nsScriptErrorEvent *aErrorEvent,
                      nsEventStatus *aStatus);
 
 
 #define NS_ISCRIPTGLOBALOBJECT_IID \
-{ 0xde24b30a, 0x12c6, 0x4e5f, \
-  { 0xa8, 0x5e, 0x90, 0xcd, 0xfb, 0x6c, 0x54, 0x51 } }
+{ 0x214fa2f6, 0xcc0c, 0x42cf, \
+  { 0x98, 0x4b, 0x45, 0xf5, 0x73, 0x9c, 0x6b, 0x73 } }
 
 /**
  * The global object which keeps a script context for each supported script
  * language. This often used to store per-window global state.
  * This is a heavyweight interface implemented only by DOM globals, and
  * it might go away some time in the future.
  */
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1039,34 +1039,39 @@ nsJSContext::JSObjectFromInterface(nsISu
 #ifdef DEBUG
   nsCOMPtr<nsISupports> targetSupp = do_QueryInterface(aTarget);
   nsCOMPtr<nsISupports> native =
     nsContentUtils::XPConnect()->GetNativeOfWrapper(cx,
                                                     JSVAL_TO_OBJECT(v));
   NS_ASSERTION(native == targetSupp, "Native should be the target!");
 #endif
 
-  *aRet = xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(v));
-
+  JSObject* obj = v.toObjectOrNull();
+  if (obj) {
+    JS::ExposeObjectToActiveJS(obj);
+  }
+
+  *aRet = obj;
   return NS_OK;
 }
 
-
 nsresult
 nsJSContext::BindCompiledEventHandler(nsISupports* aTarget,
                                       JS::Handle<JSObject*> aScope,
                                       JS::Handle<JSObject*> aHandler,
                                       JS::MutableHandle<JSObject*> aBoundHandler)
 {
   NS_ENSURE_ARG(aHandler);
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
   NS_PRECONDITION(!aBoundHandler, "Shouldn't already have a bound handler!");
 
-  xpc_UnmarkGrayObject(aScope);
-  xpc_UnmarkGrayObject(aHandler);
+  if (aScope) {
+    JS::ExposeObjectToActiveJS(aScope);
+  }
+  JS::ExposeObjectToActiveJS(aHandler);
   AutoPushJSContext cx(mContext);
 
   // Get the jsobject associated with this target
   JS::Rooted<JSObject*> target(cx);
   JS::Rooted<JSObject*> scope(cx, aScope);
   nsresult rv = JSObjectFromInterface(aTarget, scope, target.address());
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2597,17 +2602,22 @@ void
 nsJSContext::SetWindowProxy(JS::Handle<JSObject*> aWindowProxy)
 {
   mWindowProxy = aWindowProxy;
 }
 
 JSObject*
 nsJSContext::GetWindowProxy()
 {
-  return xpc_UnmarkGrayObject(GetWindowProxyPreserveColor());
+  JSObject* windowProxy = GetWindowProxyPreserveColor();
+  if (windowProxy) {
+    JS::ExposeObjectToActiveJS(windowProxy);
+  }
+
+  return windowProxy;
 }
 
 JSObject*
 nsJSContext::GetWindowProxyPreserveColor()
 {
   return mWindowProxy;
 }
 
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -172,17 +172,19 @@ nsJSUtils::CompileFunction(JSContext* aC
 
   // Since aTarget and aCx are same-compartment, there should be no distinction
   // between the object principal and the cx principal.
   // However, aTarget may be null in the wacky aShared case. So use the cx.
   JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetContextCompartment(aCx));
   aOptions.setPrincipals(p);
 
   // Do the junk Gecko is supposed to do before calling into JSAPI.
-  xpc_UnmarkGrayObject(aTarget);
+  if (aTarget) {
+    JS::ExposeObjectToActiveJS(aTarget);
+  }
 
   // Compile.
   JSFunction* fun = JS::CompileFunction(aCx, aTarget, aOptions,
                                         PromiseFlatCString(aName).get(),
                                         aArgCount, aArgArray,
                                         PromiseFlatString(aBody).get(),
                                         aBody.Length());
   if (!fun) {
@@ -233,17 +235,17 @@ nsJSUtils::EvaluateString(JSContext* aCx
   // Unfortunately, the JS engine actually compiles scripts with a return value
   // in a different, less efficient way.  Furthermore, it can't JIT them in many
   // cases.  So we need to be explicitly told whether the caller cares about the
   // return value.  Callers use null to indicate they don't care.
   if (aRetValue) {
     *aRetValue = JSVAL_VOID;
   }
 
-  xpc_UnmarkGrayObject(aScopeObject);
+  JS::ExposeObjectToActiveJS(aScopeObject);
   nsAutoMicroTask mt;
 
   JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject));
   aCompileOptions.setPrincipals(p);
 
   bool ok = false;
   nsresult rv = nsContentUtils::GetSecurityManager()->
                   CanExecuteScripts(aCx, nsJSPrincipals::get(p), &ok);
--- a/dom/base/nsWrapperCacheInlines.h
+++ b/dom/base/nsWrapperCacheInlines.h
@@ -2,38 +2,41 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsWrapperCacheInline_h___
 #define nsWrapperCacheInline_h___
 
 #include "nsWrapperCache.h"
-#include "xpcpublic.h"
+#include "js/GCAPI.h"
+#include "jsapi.h"
 
 inline JSObject*
 nsWrapperCache::GetWrapper() const
 {
     JSObject* obj = GetWrapperPreserveColor();
-    xpc_UnmarkGrayObject(obj);
+    if (obj) {
+      JS::ExposeObjectToActiveJS(obj);
+    }
     return obj;
 }
 
 inline bool
 nsWrapperCache::IsBlack()
 {
   JSObject* o = GetWrapperPreserveColor();
-  return o && !xpc_IsGrayGCThing(o);
+  return o && !JS::GCThingIsMarkedGray(o);
 }
 
 static void
 SearchGray(void* aGCThing, const char* aName, void* aClosure)
 {
   bool* hasGrayObjects = static_cast<bool*>(aClosure);
-  if (!*hasGrayObjects && aGCThing && xpc_IsGrayGCThing(aGCThing)) {
+  if (!*hasGrayObjects && aGCThing && JS::GCThingIsMarkedGray(aGCThing)) {
     *hasGrayObjects = true;
   }
 }
 
 inline bool
 nsWrapperCache::IsBlackAndDoesNotNeedTracing(nsISupports* aThis)
 {
   if (IsBlack()) {
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -28,16 +28,17 @@
 
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/DOMErrorBinding.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLSharedObjectElement.h"
 #include "mozilla/dom/HTMLEmbedElementBinding.h"
 #include "mozilla/dom/HTMLAppletElementBinding.h"
+#include "WorkerPrivate.h"
 
 namespace mozilla {
 namespace dom {
 
 JSErrorFormatString ErrorFormatString[] = {
 #define MSG_DEF(_name, _argc, _str) \
   { _str, _argc, JSEXN_TYPEERR },
 #include "mozilla/dom/Errors.msg"
@@ -673,17 +674,17 @@ NativeInterface2JSObjectAndThrowIfFailed
 {
   nsresult rv;
   if (!XPCConvert::NativeInterface2JSObject(aRetval, NULL, aHelper, aIID,
                                             NULL, aAllowNativeWrapper, &rv)) {
     // I can't tell if NativeInterface2JSObject throws JS exceptions
     // or not.  This is a sloppy stab at the right semantics; the
     // method really ought to be fixed to behave consistently.
     if (!JS_IsExceptionPending(aCx)) {
-      Throw<true>(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
+      Throw(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
     }
     return false;
   }
   return true;
 }
 
 bool
 TryPreserveWrapper(JSObject* obj)
@@ -742,17 +743,17 @@ XPCOMObjectToJsval(JSContext* cx, JS::Ha
 bool
 VariantToJsval(JSContext* aCx, JS::Handle<JSObject*> aScope,
                nsIVariant* aVariant, JS::Value* aRetval)
 {
   nsresult rv;
   if (!XPCVariant::VariantDataToJS(aVariant, &rv, aRetval)) {
     // Does it throw?  Who knows
     if (!JS_IsExceptionPending(aCx)) {
-      Throw<true>(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
+      Throw(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
     }
     return false;
   }
 
   return true;
 }
 
 bool
@@ -769,50 +770,50 @@ QueryInterface(JSContext* cx, unsigned a
   JSObject* obj = js::CheckedUnwrap(origObj);
   if (!obj) {
       JS_ReportError(cx, "Permission denied to access object");
       return false;
   }
 
   nsISupports* native = UnwrapDOMObjectToISupports(obj);
   if (!native) {
-    return Throw<true>(cx, NS_ERROR_FAILURE);
+    return Throw(cx, NS_ERROR_FAILURE);
   }
 
   if (argc < 1) {
-    return Throw<true>(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+    return Throw(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
   }
 
   JS::Value* argv = JS_ARGV(cx, vp);
   if (!argv[0].isObject()) {
-    return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
+    return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
   }
 
   nsIJSID* iid;
   SelfRef iidRef;
   if (NS_FAILED(xpc_qsUnwrapArg<nsIJSID>(cx, argv[0], &iid, &iidRef.ptr,
                                           &argv[0]))) {
-    return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
+    return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
   }
   MOZ_ASSERT(iid);
 
   if (iid->GetID()->Equals(NS_GET_IID(nsIClassInfo))) {
     nsresult rv;
     nsCOMPtr<nsIClassInfo> ci = do_QueryInterface(native, &rv);
     if (NS_FAILED(rv)) {
-      return Throw<true>(cx, rv);
+      return Throw(cx, rv);
     }
 
     return WrapObject(cx, origObj, ci, &NS_GET_IID(nsIClassInfo), args.rval());
   }
 
   nsCOMPtr<nsISupports> unused;
   nsresult rv = native->QueryInterface(*iid->GetID(), getter_AddRefs(unused));
   if (NS_FAILED(rv)) {
-    return Throw<true>(cx, rv);
+    return Throw(cx, rv);
   }
 
   *vp = thisv;
   return true;
 }
 
 bool
 ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
@@ -1752,17 +1753,17 @@ GlobalObject::GlobalObject(JSContext* aC
     obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
     if (!obj) {
       // We should never end up here on a worker thread, since there shouldn't
       // be any security wrappers to worry about.
       if (!MOZ_LIKELY(NS_IsMainThread())) {
         MOZ_CRASH();
       }
 
-      Throw<true>(aCx, NS_ERROR_XPC_SECURITY_MANAGER_VETO);
+      Throw(aCx, NS_ERROR_XPC_SECURITY_MANAGER_VETO);
       return;
     }
     ac.construct(aCx, obj);
   }
 
   mGlobalJSObject = JS_GetGlobalForObject(aCx, obj);
 }
 
@@ -1779,17 +1780,17 @@ GlobalObject::GetAsSupports() const
 
   // Switch this to UnwrapDOMObjectToISupports once our global objects are
   // using new bindings.
   nsresult rv = xpc_qsUnwrapArg<nsISupports>(mCx, val, &mGlobalObject,
                                              static_cast<nsISupports**>(getter_AddRefs(mGlobalObjectRef)),
                                              val.address());
   if (NS_FAILED(rv)) {
     mGlobalObject = nullptr;
-    Throw<true>(mCx, NS_ERROR_XPC_BAD_CONVERT_JS);
+    Throw(mCx, NS_ERROR_XPC_BAD_CONVERT_JS);
   }
 
   return mGlobalObject;
 }
 
 bool
 InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj,
                      JS::Handle<JSObject*> instance,
@@ -2056,10 +2057,17 @@ ConvertJSValueToByteString(JSContext* cx
   result.SetCapacity(length+1);
   JS_EncodeStringToBuffer(cx, s, result.BeginWriting(), length);
   result.BeginWriting()[length] = '\0';
   result.SetLength(length);
 
   return true;
 }
 
+bool
+ThreadsafeCheckIsChrome(JSContext* aCx, JSObject* aObj) {
+  using mozilla::dom::workers::GetWorkerPrivateFromContext;
+  return NS_IsMainThread() ? xpc::AccessCheck::isChrome(aObj):
+                             GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -11,16 +11,17 @@
 
 #include "jsfriendapi.h"
 #include "jswrapper.h"
 #include "mozilla/Alignment.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/CallbackObject.h"
 #include "mozilla/dom/DOMJSClass.h"
 #include "mozilla/dom/DOMJSProxyHandler.h"
+#include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/NonRefcountedDOMObject.h"
 #include "mozilla/dom/Nullable.h"
 #include "mozilla/dom/workers/Workers.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Util.h"
 #include "nsCycleCollector.h"
 #include "nsIXPConnect.h"
@@ -64,34 +65,16 @@ UnwrapArg(JSContext* cx, jsval v, Interf
   return rv;
 }
 
 bool
 ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
                  const ErrNum aErrorNumber,
                  const char* aInterfaceName);
 
-template<bool mainThread>
-inline bool
-Throw(JSContext* cx, nsresult rv)
-{
-  using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
-
-  // XXX Introduce exception machinery.
-  if (mainThread) {
-    xpc::Throw(cx, rv);
-  } else {
-    if (!JS_IsExceptionPending(cx)) {
-      ThrowDOMExceptionForNSResult(cx, rv);
-    }
-  }
-  return false;
-}
-
-template<bool mainThread>
 inline bool
 ThrowMethodFailedWithDetails(JSContext* cx, ErrorResult& rv,
                              const char* ifaceName,
                              const char* memberName,
                              bool reportJSContentExceptions = false)
 {
   if (rv.IsTypeError()) {
     rv.ReportTypeError(cx);
@@ -103,17 +86,17 @@ ThrowMethodFailedWithDetails(JSContext* 
     } else {
       rv.ReportJSException(cx);
     }
     return false;
   }
   if (rv.IsNotEnoughArgsError()) {
     rv.ReportNotEnoughArgsError(cx, ifaceName, memberName);
   }
-  return Throw<mainThread>(cx, rv.ErrorCode());
+  return Throw(cx, rv.ErrorCode());
 }
 
 // Returns true if the JSClass is used for DOM objects.
 inline bool
 IsDOMClass(const JSClass* clasp)
 {
   return clasp->flags & JSCLASS_IS_DOMJSCLASS;
 }
@@ -647,17 +630,17 @@ template <class T>
 MOZ_ALWAYS_INLINE bool
 WrapNewBindingObject(JSContext* cx, JS::Handle<JSObject*> scope, T* value,
                      JS::MutableHandle<JS::Value> rval)
 {
   MOZ_ASSERT(value);
   JSObject* obj = value->GetWrapperPreserveColor();
   bool couldBeDOMBinding = CouldBeDOMBinding(value);
   if (obj) {
-    xpc_UnmarkNonNullGrayObject(obj);
+    JS::ExposeObjectToActiveJS(obj);
   } else {
     // Inline this here while we have non-dom objects in wrapper caches.
     if (!couldBeDOMBinding) {
       return false;
     }
 
     obj = value->WrapObject(cx, scope);
     if (!obj) {
@@ -2347,12 +2330,15 @@ class GetCCParticipant<T, true>
 public:
   static MOZ_CONSTEXPR nsCycleCollectionParticipant*
   Get()
   {
     return nullptr;
   }
 };
 
+bool
+ThreadsafeCheckIsChrome(JSContext* aCx, JSObject* aObj);
+
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_BindingUtils_h__ */
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -314,16 +314,23 @@ DOMInterfaces = {
     'workers': True,
     'skipGen': True
 }],
 
 'DocumentFragment': {
     'resultNotAddRefed': [ 'querySelector' ]
 },
 
+'DOMException': {
+    'wantsQI': False,
+    'binaryNames': {
+        'message': 'messageMoz',
+    },
+},
+
 'DOMSettableTokenList': {
     'nativeType': 'nsDOMSettableTokenList',
 },
 
 'DOMStringMap': {
     'nativeType': 'nsDOMStringMap'
 },
 
@@ -386,16 +393,24 @@ DOMInterfaces = {
     'concrete': False,
     'jsImplParent': 'nsDOMEventTargetHelper'
 },
 {
     'workers': True,
     'concrete': False
 }],
 
+'Exception': {
+    'headerFile': 'mozilla/dom/DOMException.h',
+    'wantsQI': False,
+    'binaryNames': {
+        'message': 'messageMoz',
+    },
+},
+
 'FileHandle': {
     'nativeType': 'mozilla::dom::file::FileHandle'
 },
 
 'FileList': {
     'nativeType': 'nsDOMFileList',
     'headerFile': 'nsDOMFile.h',
     'resultNotAddRefed': [ 'item' ]
@@ -1807,16 +1822,18 @@ addExternalIface('nsIEditor', nativeType
 addExternalIface('nsIVariant', nativeType='nsIVariant', notflattened=True)
 addExternalIface('OutputStream', nativeType='nsIOutputStream',
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
 addExternalIface('PrintCallback', nativeType='nsIPrintCallback',
                  headerFile='nsIDOMHTMLCanvasElement.h')
 addExternalIface('Selection', nativeType='nsISelection')
+addExternalIface('StackFrame', nativeType='nsIStackFrame',
+                 headerFile='nsIException.h', notflattened=True)
 addExternalIface('StyleSheetList')
 addExternalIface('SVGLength')
 addExternalIface('SVGNumber')
 addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
                  notflattened=True)
 addExternalIface('UserDataHandler')
 addExternalIface('Window')
 addExternalIface('XPathResult', nativeType='nsISupports')
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -101,17 +101,17 @@ CallbackObject::CallSetup::CallSetup(JS:
   // Unmark the callable, and stick it in a Rooted before it can go gray again.
   // Nothing before us in this function can trigger a CC, so it's safe to wait
   // until here it do the unmark. This allows us to order the following two
   // operations _after_ the Push() above, which lets us take advantage of the
   // JSAutoRequest embedded in the pusher.
   //
   // We can do this even though we're not in the right compartment yet, because
   // Rooted<> does not care about compartments.
-  xpc_UnmarkGrayObject(aCallback);
+  JS::ExposeObjectToActiveJS(aCallback);
   mRootedCallable.construct(cx, aCallback);
 
   // Check that it's ok to run this callback at all.
   // FIXME: Bug 807371: we want a less silly check here.
   // Make sure to unwrap aCallback before passing it in, because
   // getting principals from wrappers is silly.
   nsresult rv = nsContentUtils::GetSecurityManager()->
     CheckFunctionAccess(cx, js::UncheckedUnwrap(aCallback), nullptr);
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -53,17 +53,17 @@ public:
 
   virtual ~CallbackObject()
   {
     DropCallback();
   }
 
   JS::Handle<JSObject*> Callback() const
   {
-    xpc_UnmarkGrayObject(mCallback);
+    JS::ExposeObjectToActiveJS(mCallback);
     return CallbackPreserveColor();
   }
 
   /*
    * This getter does not change the color of the JSObject meaning that the
    * object returned is not guaranteed to be kept alive past the next CC.
    *
    * This should only be called if you are certain that the return value won't
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1142,28 +1142,27 @@ class CGConstructNavigatorObject(CGAbstr
         return string.Template("""  GlobalObject global(aCx, aObj);
   if (global.Failed()) {
     return nullptr;
   }
   ErrorResult rv;
   nsRefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
   rv.WouldReportJSException();
   if (rv.Failed()) {
-    ThrowMethodFailedWithDetails<${mainThread}>(aCx, rv, "${descriptorName}", "navigatorConstructor");
+    ThrowMethodFailedWithDetails(aCx, rv, "${descriptorName}", "navigatorConstructor");
     return nullptr;
   }
   JS::Rooted<JS::Value> v(aCx);
   if (!WrapNewBindingObject(aCx, aObj, result, &v)) {
     MOZ_ASSERT(JS_IsExceptionPending(aCx));
     return nullptr;
   }
   return &v.toObject();""").substitute(
     {
         'descriptorName' : self.descriptor.name,
-        'mainThread' : toStringBool(not self.descriptor.workers),
     })
 
 class CGClassConstructHookHolder(CGGeneric):
     def __init__(self, descriptor):
         if descriptor.interface.ctor():
             constructHook = CONSTRUCT_HOOK_NAME
         else:
             constructHook = "ThrowingConstructor"
@@ -2131,23 +2130,17 @@ def CreateBindingJSObject(descriptor, pr
     return create % parent
 
 def GetAccessCheck(descriptor, object):
     """
     object is the name of a JSObject*
 
     returns a string
     """
-    accessCheck = "xpc::AccessCheck::isChrome(%s)" % object
-    if descriptor.workers:
-        # We sometimes set up worker things on the main thread, in which case we
-        # want to use the main-thread accessCheck above.  Otherwise, we want to
-        # check for a ChromeWorker.
-        accessCheck = "(NS_IsMainThread() ? %s : mozilla::dom::workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker())" % accessCheck
-    return accessCheck
+    return "ThreadsafeCheckIsChrome(aCx, %s)" % object
 
 def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturnValue=""):
     """
     properties is a PropertyArrays instance
     """
     failureReturn = "return"
     if len(failureReturnValue) > 0:
         failureReturn += " " + failureReturnValue
@@ -4924,19 +4917,18 @@ if (!${obj}) {
                             (err.typename,
                              self.descriptor.interface.identifier.name,
                              self.idlNode.identifier.name))
 
     def getErrorReport(self):
         jsImplemented = ""
         if self.descriptor.interface.isJSImplemented():
             jsImplemented = ", true"
-        return CGGeneric('return ThrowMethodFailedWithDetails<%s>(cx, rv, "%s", "%s"%s);'
-                         % (toStringBool(not self.descriptor.workers),
-                            self.descriptor.interface.identifier.name,
+        return CGGeneric('return ThrowMethodFailedWithDetails(cx, rv, "%s", "%s"%s);'
+                         % (self.descriptor.interface.identifier.name,
                             self.idlNode.identifier.name,
                             jsImplemented))
 
     def define(self):
         return (self.cgRoot.define() + "\n" + self.wrap_return_value())
 
 class CGSwitch(CGList):
     """
@@ -5571,17 +5563,17 @@ class CGEnumerateHook(CGAbstractBindingM
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
                 "nsAutoTArray<nsString, 8> names;\n"
                 "ErrorResult rv;\n"
                 "self->GetOwnPropertyNames(cx, names, rv);\n"
                 "rv.WouldReportJSException();\n"
                 "if (rv.Failed()) {\n"
-                '  return ThrowMethodFailedWithDetails<true>(cx, rv, "%s", "enumerate");\n'
+                '  return ThrowMethodFailedWithDetails(cx, rv, "%s", "enumerate");\n'
                 "}\n"
                 "JS::Rooted<JS::Value> dummy(cx);\n"
                 "for (uint32_t i = 0; i < names.Length(); ++i) {\n"
                 "  if (!JS_LookupUCProperty(cx, obj, names[i].get(), names[i].Length(), &dummy)) {\n"
                 "    return false;\n"
                 "  }\n"
                 "}\n"
                 "return true;"))
@@ -6992,17 +6984,17 @@ class CGEnumerateOwnPropertiesViaGetOwnP
                                          callArgs="")
     def generate_code(self):
         return CGIndenter(CGGeneric(
                 "nsAutoTArray<nsString, 8> names;\n"
                 "ErrorResult rv;\n"
                 "self->GetOwnPropertyNames(cx, names, rv);\n"
                 "rv.WouldReportJSException();\n"
                 "if (rv.Failed()) {\n"
-                '  return ThrowMethodFailedWithDetails<true>(cx, rv, "%s", "enumerate");\n'
+                '  return ThrowMethodFailedWithDetails(cx, rv, "%s", "enumerate");\n'
                 "}\n"
                 '// OK to pass null as "proxy" because it\'s ignored if\n'
                 "// shadowPrototypeProperties is true\n"
                 "return AppendNamedPropertyIds(cx, JS::NullPtr(), names, true, props);"))
 
 class CGPrototypeTraitsClass(CGClass):
     def __init__(self, descriptor, indent=''):
         templateArgs = [Argument('prototypes::ID', 'PrototypeID')]
new file mode 100644
--- /dev/null
+++ b/dom/bindings/Exceptions.cpp
@@ -0,0 +1,439 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/Exceptions.h"
+
+#include "js/GCAPI.h"
+#include "js/OldDebugAPI.h"
+#include "jsapi.h"
+#include "jsprf.h"
+#include "mozilla/CycleCollectedJSRuntime.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/DOMException.h"
+#include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
+#include "XPCWrapper.h"
+#include "WorkerPrivate.h"
+
+namespace {
+
+// We can't use nsContentUtils::IsCallerChrome because it might not exist in
+// xpcshell.
+bool
+IsCallerChrome()
+{
+  nsCOMPtr<nsIScriptSecurityManager> secMan;
+  secMan = XPCWrapper::GetSecurityManager();
+
+  if (!secMan) {
+    return false;
+  }
+
+  bool isChrome;
+  return NS_SUCCEEDED(secMan->SubjectPrincipalIsSystem(&isChrome)) && isChrome;
+}
+
+} // anonymous namespace
+
+namespace mozilla {
+namespace dom {
+
+bool
+ThrowExceptionObject(JSContext* aCx, nsIException* aException)
+{
+  // See if we really have an Exception.
+  nsCOMPtr<Exception> exception = do_QueryInterface(aException);
+  if (exception) {
+    return ThrowExceptionObject(aCx, exception);
+  }
+
+  // We only have an nsIException (probably an XPCWrappedJS).  Fall back on old
+  // wrapping.
+  MOZ_ASSERT(NS_IsMainThread());
+
+  JS::Rooted<JSObject*> glob(aCx, JS::CurrentGlobalOrNull(aCx));
+  if (!glob) {
+    return false;
+  }
+
+  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+  nsresult rv = nsContentUtils::XPConnect()->WrapNative(aCx, glob, aException,
+                                                        NS_GET_IID(nsIException),
+                                                        getter_AddRefs(holder));
+  if (NS_FAILED(rv) ||! holder) {
+    return false;
+  }
+
+  JS::RootedObject obj(aCx, holder->GetJSObject());
+  if (!obj) {
+    return false;
+  }
+
+  JS_SetPendingException(aCx, OBJECT_TO_JSVAL(obj));
+
+  return true;
+}
+
+bool
+ThrowExceptionObject(JSContext* aCx, Exception* aException)
+{
+  JS::Rooted<JS::Value> thrown(aCx);
+
+  // If we stored the original thrown JS value in the exception
+  // (see XPCConvert::ConstructException) and we are in a web context
+  // (i.e., not chrome), rethrow the original value. This only applies to JS
+  // implemented components so we only need to check for this on the main
+  // thread.
+  if (NS_IsMainThread() && !IsCallerChrome() &&
+      aException->StealJSVal(thrown.address())) {
+    if (!JS_WrapValue(aCx, thrown.address())) {
+      return false;
+    }
+    JS_SetPendingException(aCx, thrown);
+    return true;
+  }
+
+  JS::Rooted<JSObject*> glob(aCx, JS::CurrentGlobalOrNull(aCx));
+  if (!glob) {
+    return false;
+  }
+
+  if (!WrapNewBindingObject(aCx, glob, aException, &thrown)) {
+    return false;
+  }
+
+  JS_SetPendingException(aCx, thrown);
+  return true;
+}
+
+bool
+Throw(JSContext* aCx, nsresult aRv, const char* aMessage)
+{
+  if (JS_IsExceptionPending(aCx)) {
+    // Don't clobber the existing exception.
+    return false;
+  }
+
+  CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
+  nsCOMPtr<nsIException> existingException = runtime->GetPendingException();
+  if (existingException) {
+    nsresult nr;
+    if (NS_SUCCEEDED(existingException->GetResult(&nr)) && 
+        aRv == nr) {
+      // Just reuse the existing exception.
+      return false;
+    }
+  }
+
+  nsRefPtr<Exception> finalException;
+
+  // Do we use DOM exceptions for this error code?
+  switch (NS_ERROR_GET_MODULE(aRv)) {
+  case NS_ERROR_MODULE_DOM:
+  case NS_ERROR_MODULE_SVG:
+  case NS_ERROR_MODULE_DOM_XPATH:
+  case NS_ERROR_MODULE_DOM_INDEXEDDB:
+  case NS_ERROR_MODULE_DOM_FILEHANDLE:
+    finalException = DOMException::Create(aRv);
+    break;
+
+  default:
+      break;
+  }
+
+  // If not, use the default.
+  if (!finalException) {
+    finalException = new Exception(aMessage, aRv, nullptr, nullptr, nullptr);
+  }
+
+  MOZ_ASSERT(finalException);
+  if (!ThrowExceptionObject(aCx, finalException)) {
+    // If we weren't able to throw an exception we're
+    // most likely out of memory
+    JS_ReportOutOfMemory(aCx);
+  }
+
+  return false;
+}
+
+already_AddRefed<nsIStackFrame>
+GetCurrentJSStack()
+{
+  // is there a current context available?
+  JSContext* cx = nullptr;
+
+  if (NS_IsMainThread()) {
+    // We can't call nsContentUtils::ThreadsafeGetCurrentJSContext, since in
+    // xpcshell nsContentUtils is never initialized, but we still need to
+    // report exceptions.
+    nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
+    cx = xpc->GetCurrentJSContext();
+  } else {
+    cx = workers::GetCurrentThreadJSContext();
+  }
+
+  if (!cx) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIStackFrame> stack = exceptions::CreateStack(cx);
+  if (!stack) {
+    return nullptr;
+  }
+
+  // peel off native frames...
+  uint32_t language;
+  nsCOMPtr<nsIStackFrame> caller;
+  while (stack &&
+         NS_SUCCEEDED(stack->GetLanguage(&language)) &&
+         language != nsIProgrammingLanguage::JAVASCRIPT &&
+         NS_SUCCEEDED(stack->GetCaller(getter_AddRefs(caller))) &&
+         caller) {
+    stack = caller;
+  }
+  return stack.forget();
+}
+
+namespace exceptions {
+
+class JSStackFrame : public nsIStackFrame
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISTACKFRAME
+
+  JSStackFrame();
+  virtual ~JSStackFrame();
+
+  static already_AddRefed<nsIStackFrame>
+  CreateStack(JSContext* cx);
+  static already_AddRefed<nsIStackFrame>
+  CreateStackFrameLocation(uint32_t aLanguage,
+                           const char* aFilename,
+                           const char* aFunctionName,
+                           int32_t aLineNumber,
+                           nsIStackFrame* aCaller);
+
+private:
+  bool IsJSFrame() const {
+    return mLanguage == nsIProgrammingLanguage::JAVASCRIPT;
+  }
+
+  nsCOMPtr<nsIStackFrame> mCaller;
+
+  char* mFilename;
+  char* mFunname;
+  int32_t mLineno;
+  uint32_t mLanguage;
+};
+
+JSStackFrame::JSStackFrame()
+  : mFilename(nullptr),
+    mFunname(nullptr),
+    mLineno(0),
+    mLanguage(nsIProgrammingLanguage::UNKNOWN)
+{}
+
+JSStackFrame::~JSStackFrame()
+{
+  if (mFilename) {
+    nsMemory::Free(mFilename);
+  }
+  if (mFunname) {
+    nsMemory::Free(mFunname);
+  }
+}
+
+NS_IMPL_ISUPPORTS1(JSStackFrame, nsIStackFrame)
+
+/* readonly attribute uint32_t language; */
+NS_IMETHODIMP JSStackFrame::GetLanguage(uint32_t* aLanguage)
+{
+  *aLanguage = mLanguage;
+  return NS_OK;
+}
+
+/* readonly attribute string languageName; */
+NS_IMETHODIMP JSStackFrame::GetLanguageName(char** aLanguageName)
+{
+  static const char js[] = "JavaScript";
+  static const char cpp[] = "C++";
+
+  if (IsJSFrame()) {
+    *aLanguageName = (char*) nsMemory::Clone(js, sizeof(js));
+  } else {
+    *aLanguageName = (char*) nsMemory::Clone(cpp, sizeof(cpp));
+  }
+
+  return NS_OK;
+}
+
+/* readonly attribute string filename; */
+NS_IMETHODIMP JSStackFrame::GetFilename(char** aFilename)
+{
+  NS_ENSURE_ARG_POINTER(aFilename);
+
+  if (mFilename) {
+    *aFilename = (char*) nsMemory::Clone(mFilename,
+                                         sizeof(char)*(strlen(mFilename)+1));
+  } else {
+    *aFilename = nullptr;
+  }
+
+  return NS_OK;
+}
+
+/* readonly attribute string name; */
+NS_IMETHODIMP JSStackFrame::GetName(char** aFunction)
+{
+  NS_ENSURE_ARG_POINTER(aFunction);
+
+  if (mFunname) {
+    *aFunction = (char*) nsMemory::Clone(mFunname,
+                                         sizeof(char)*(strlen(mFunname)+1));
+  } else {
+    *aFunction = nullptr;
+  }
+
+  return NS_OK;
+}
+
+/* readonly attribute int32_t lineNumber; */
+NS_IMETHODIMP JSStackFrame::GetLineNumber(int32_t* aLineNumber)
+{
+  *aLineNumber = mLineno;
+  return NS_OK;
+}
+
+/* readonly attribute string sourceLine; */
+NS_IMETHODIMP JSStackFrame::GetSourceLine(char** aSourceLine)
+{
+  *aSourceLine = nullptr;
+  return NS_OK;
+}
+
+/* readonly attribute nsIStackFrame caller; */
+NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
+{
+  NS_IF_ADDREF(*aCaller = mCaller);
+  return NS_OK;
+}
+
+/* string toString (); */
+NS_IMETHODIMP JSStackFrame::ToString(char** _retval)
+{
+  const char* frametype = IsJSFrame() ? "JS" : "native";
+  const char* filename = mFilename ? mFilename : "<unknown filename>";
+  const char* funname = mFunname ? mFunname : "<TOP_LEVEL>";
+  static const char format[] = "%s frame :: %s :: %s :: line %d";
+  int len = sizeof(char)*
+              (strlen(frametype) + strlen(filename) + strlen(funname)) +
+            sizeof(format) + 3 * sizeof(mLineno);
+
+  char* buf = (char*) nsMemory::Alloc(len);
+  JS_snprintf(buf, len, format, frametype, filename, funname, mLineno);
+  *_retval = buf;
+  return NS_OK;
+}
+
+/* static */ already_AddRefed<nsIStackFrame>
+JSStackFrame::CreateStack(JSContext* cx)
+{
+  static const unsigned MAX_FRAMES = 100;
+
+  nsRefPtr<JSStackFrame> first = new JSStackFrame();
+  nsRefPtr<JSStackFrame> self = first;
+
+  JS::StackDescription* desc = JS::DescribeStack(cx, MAX_FRAMES);
+  if (!desc) {
+    return nullptr;
+  }
+
+  for (size_t i = 0; i < desc->nframes && self; i++) {
+    self->mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
+
+    JSAutoCompartment ac(cx, desc->frames[i].script);
+    const char* filename = JS_GetScriptFilename(cx, desc->frames[i].script);
+    if (filename) {
+      self->mFilename =
+        (char*)nsMemory::Clone(filename, sizeof(char)*(strlen(filename)+1));
+    }
+
+    self->mLineno = desc->frames[i].lineno;
+
+    JSFunction* fun = desc->frames[i].fun;
+    if (fun) {
+      JS::RootedString funid(cx, JS_GetFunctionDisplayId(fun));
+      if (funid) {
+        size_t length = JS_GetStringEncodingLength(cx, funid);
+        if (length != size_t(-1)) {
+          self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
+          if (self->mFunname) {
+            JS_EncodeStringToBuffer(cx, funid, self->mFunname, length);
+            self->mFunname[length] = '\0';
+          }
+        }
+      }
+    }
+
+    nsRefPtr<JSStackFrame> frame = new JSStackFrame();
+    self->mCaller = frame;
+    self.swap(frame);
+  }
+
+  JS::FreeStackDescription(cx, desc);
+
+  return first.forget();
+}
+
+/* static */ already_AddRefed<nsIStackFrame>
+JSStackFrame::CreateStackFrameLocation(uint32_t aLanguage,
+                                       const char* aFilename,
+                                       const char* aFunctionName,
+                                       int32_t aLineNumber,
+                                       nsIStackFrame* aCaller)
+{
+  nsRefPtr<JSStackFrame> self = new JSStackFrame();
+
+  self->mLanguage = aLanguage;
+  self->mLineno = aLineNumber;
+
+  if (aFilename) {
+    self->mFilename =
+      (char*)nsMemory::Clone(aFilename, sizeof(char)*(strlen(aFilename)+1));
+  }
+
+  if (aFunctionName) {
+    self->mFunname = 
+      (char*)nsMemory::Clone(aFunctionName,
+                             sizeof(char)*(strlen(aFunctionName)+1));
+  }
+
+  self->mCaller = aCaller;
+
+  return self.forget();
+}
+
+already_AddRefed<nsIStackFrame>
+CreateStack(JSContext* cx)
+{
+  return JSStackFrame::CreateStack(cx);
+}
+
+already_AddRefed<nsIStackFrame>
+CreateStackFrameLocation(uint32_t aLanguage,
+                         const char* aFilename,
+                         const char* aFunctionName,
+                         int32_t aLineNumber,
+                         nsIStackFrame* aCaller)
+{
+  return JSStackFrame::CreateStackFrameLocation(aLanguage, aFilename,
+                                                aFunctionName, aLineNumber,
+                                                aCaller);
+}
+
+} // namespace exceptions
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/bindings/Exceptions.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_Exceptions_h__
+#define mozilla_dom_Exceptions_h__
+
+// DOM exception throwing machinery (for both main thread and workers).
+
+#include <stdint.h>
+#include "jspubtd.h"
+#include "nsIException.h"
+
+class nsIStackFrame;
+template <class T>
+class already_AddRefed;
+
+namespace mozilla {
+namespace dom {
+
+class Exception;
+
+bool
+Throw(JSContext* cx, nsresult rv, const char* sz = nullptr);
+
+bool
+ThrowExceptionObject(JSContext* aCx, Exception* aException);
+
+bool
+ThrowExceptionObject(JSContext* aCx, nsIException* aException);
+
+already_AddRefed<nsIStackFrame>
+GetCurrentJSStack();
+
+// Internal stuff not intended to be widely used.
+namespace exceptions {
+
+already_AddRefed<nsIStackFrame>
+CreateStack(JSContext* cx);
+
+already_AddRefed<nsIStackFrame>
+CreateStackFrameLocation(uint32_t aLanguage,
+                         const char* aFilename,
+                         const char* aFunctionName,
+                         int32_t aLineNumber,
+                         nsIStackFrame* aCaller);
+
+} // namespace exceptions
+} // namespace dom
+} // namespace mozilla
+
+#endif
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -55,16 +55,17 @@ ifneq (export TestExampleInterface-examp
 CPPSRCS = \
   $(linked_binding_cpp_files) \
   $(filter %.cpp, $(globalgen_targets)) \
   BindingUtils.cpp \
   CallbackInterface.cpp \
   CallbackObject.cpp \
   DOMJSProxyHandler.cpp \
   Date.cpp \
+  Exceptions.cpp \
   $(NULL)
 endif
 
 LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \
   -I$(topsrcdir)/js/xpconnect/wrappers \
   -I$(topsrcdir)/js/ipc \
   -I$(topsrcdir)/content/canvas/src \
   -I$(topsrcdir)/content/html/content/src \
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -16,16 +16,17 @@ EXPORTS.mozilla.dom += [
     'BindingUtils.h',
     'CallbackFunction.h',
     'CallbackInterface.h',
     'CallbackObject.h',
     'DOMJSClass.h',
     'DOMJSProxyHandler.h',
     'Date.h',
     'Errors.msg',
+    'Exceptions.h',
     'JSSlots.h',
     'NonRefcountedDOMObject.h',
     'Nullable.h',
     'PrimitiveConversions.h',
     'TypedArray.h',
 ]
 
 FAIL_ON_WARNINGS = True
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -416,29 +416,31 @@ JS::Value
 BluetoothAdapter::GetDevices(JSContext* aContext, ErrorResult& aRv)
 {
   if (!mJsDeviceAddresses) {
     NS_WARNING("Devices not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
     return JS::NullValue();
   }
 
-  return JS::ObjectValue(*xpc_UnmarkGrayObject(mJsDeviceAddresses));
+  JS::ExposeObjectToActiveJS(mJsDeviceAddresses);
+  return JS::ObjectValue(*mJsDeviceAddresses);
 }
 
 JS::Value
 BluetoothAdapter::GetUuids(JSContext* aContext, ErrorResult& aRv)
 {
   if (!mJsUuids) {
     NS_WARNING("UUIDs not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
     return JS::NullValue();
   }
 
-  return JS::ObjectValue(*xpc_UnmarkGrayObject(mJsUuids));
+  JS::ExposeObjectToActiveJS(mJsUuids);
+  return JS::ObjectValue(*mJsUuids);
 }
 
 already_AddRefed<DOMRequest>
 BluetoothAdapter::SetName(const nsAString& aName, ErrorResult& aRv)
 {
   if (mName.Equals(aName)) {
     return FirePropertyAlreadySet(GetOwner(), aRv);
   }
--- a/dom/bluetooth/BluetoothDevice.cpp
+++ b/dom/bluetooth/BluetoothDevice.cpp
@@ -201,28 +201,30 @@ JS::Value
 BluetoothDevice::GetUuids(JSContext* aCx, ErrorResult& aRv)
 {
   if (!mJsUuids) {
     NS_WARNING("UUIDs not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
     return JS::NullValue();
   }
 
-  return JS::ObjectValue(*xpc_UnmarkGrayObject(mJsUuids));
+  JS::ExposeObjectToActiveJS(mJsUuids);
+  return JS::ObjectValue(*mJsUuids);
 }
 
 JS::Value
 BluetoothDevice::GetServices(JSContext* aCx, ErrorResult& aRv)
 {
   if (!mJsServices) {
     NS_WARNING("Services not yet set!\n");
     aRv.Throw(NS_ERROR_FAILURE);
     return JS::Value(JSVAL_NULL);
   }
 
-  return JS::ObjectValue(*xpc_UnmarkGrayObject(mJsServices));
+  JS::ExposeObjectToActiveJS(mJsServices);
+  return JS::ObjectValue(*mJsServices);
 }
 
 JSObject*
 BluetoothDevice::WrapObject(JSContext* aContext, JS::Handle<JSObject*> aScope)
 {
   return BluetoothDeviceBinding::Wrap(aContext, aScope, this);
 }
--- a/dom/indexedDB/IDBEvents.cpp
+++ b/dom/indexedDB/IDBEvents.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IDBEvents.h"
 
-#include "nsDOMException.h"
 #include "nsJSON.h"
 #include "nsThreadUtils.h"
 
 #include "IDBRequest.h"
 #include "IDBTransaction.h"
 
 USING_INDEXEDDB_NAMESPACE
 using namespace mozilla::dom;
--- a/dom/src/notification/DesktopNotification.h
+++ b/dom/src/notification/DesktopNotification.h
@@ -9,16 +9,17 @@
 #include "nsIAlertsService.h"
 #include "nsIContentPermissionPrompt.h"
 
 #include "nsIObserver.h"
 #include "nsString.h"
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMWindow.h"
+#include "nsIScriptObjectPrincipal.h"
 #include "nsThreadUtils.h"
 
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMEvent.h"
 #include "nsIDocument.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
--- a/dom/tests/mochitest/bugs/test_bug291377.html
+++ b/dom/tests/mochitest/bugs/test_bug291377.html
@@ -15,26 +15,26 @@ https://bugzilla.mozilla.org/show_bug.cg
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 /** Test for Bug 291377 **/
 /* Do something that causes an XPConnect exception */
 var threw = true;
 try {
-  SpecialPowers.Cc["@mozilla.org/network/io-service;1"].getService(SpecialPowers.Ci.nsIIOService).newURI();  /* Not enough arguments */
+  window.location.port = -2;
   threw = false;
 } catch (e) {
   /* Check that we can touch various properties */
   isnot(e.lineNumber, undefined, "Unexpected line number"); //This line number is dependent on the implementation of the SpecialPowers API
-  is(e.name, "NS_ERROR_XPC_NOT_ENOUGH_ARGS", "Unexpected exception name");
+  is(e.name, "NS_ERROR_MALFORMED_URI", "Unexpected exception name");
   isnot(e.message, "", "Should have a message");
   isnot(e.result, 0, "Should have a result");
   
-  is(e.result, SpecialPowers.Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+  is(e.result, SpecialPowers.Cr.NS_ERROR_MALFORMED_URI);
 }
 
 is(threw, true, "Not enough arguments to a call should throw");
 </script>
 </pre>
 </body>
 </html>
 
new file mode 100644
--- /dev/null
+++ b/dom/webidl/DOMException.webidl
@@ -0,0 +1,97 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://dom.spec.whatwg.org/#exception-domexception
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+
+// This is the WebIDL version of nsIException.  This is mostly legacy stuff.
+
+interface StackFrame;
+
+[NoInterfaceObject]
+interface ExceptionMembers
+{
+  // A custom message set by the thrower.
+  readonly attribute DOMString               message;
+  // The nsresult associated with this exception.
+  readonly attribute unsigned long           result;
+  // The name of the error code (ie, a string repr of |result|)
+  readonly attribute DOMString               name;
+
+  // Filename location.  This is the location that caused the
+  // error, which may or may not be a source file location.
+  // For example, standard language errors would generally have
+  // the same location as their top stack entry.  File
+  // parsers may put the location of the file they were parsing,
+  // etc.
+
+  // null indicates "no data"
+  readonly attribute DOMString               filename;
+  // Valid line numbers begin at '1'. '0' indicates unknown.
+  readonly attribute unsigned long           lineNumber;
+  // Valid column numbers begin at 0. 
+  // We don't have an unambiguous indicator for unknown.
+  readonly attribute unsigned long           columnNumber;
+
+  // A stack trace, if available.  nsIStackFrame does not have classinfo so
+  // this was only ever usefully available to chrome JS.
+  [ChromeOnly]
+  readonly attribute StackFrame?             location;
+  // An inner exception that triggered this, if available.
+  readonly attribute nsISupports?            inner;
+
+  // Arbitary data for the implementation.
+  readonly attribute nsISupports?            data;
+
+  // A generic formatter - make it suitable to print, etc.
+  stringifier;
+};
+
+[NoInterfaceObject]
+interface Exception {
+};
+
+Exception implements ExceptionMembers;
+
+// XXXkhuey this is an 'exception', not an interface, but we don't have any
+// parser or codegen mechanisms for dealing with exceptions.
+interface DOMException {
+  const unsigned short INDEX_SIZE_ERR = 1;
+  const unsigned short DOMSTRING_SIZE_ERR = 2; // historical
+  const unsigned short HIERARCHY_REQUEST_ERR = 3;
+  const unsigned short WRONG_DOCUMENT_ERR = 4;
+  const unsigned short INVALID_CHARACTER_ERR = 5;
+  const unsigned short NO_DATA_ALLOWED_ERR = 6; // historical
+  const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7;
+  const unsigned short NOT_FOUND_ERR = 8;
+  const unsigned short NOT_SUPPORTED_ERR = 9;
+  const unsigned short INUSE_ATTRIBUTE_ERR = 10; // historical
+  const unsigned short INVALID_STATE_ERR = 11;
+  const unsigned short SYNTAX_ERR = 12;
+  const unsigned short INVALID_MODIFICATION_ERR = 13;
+  const unsigned short NAMESPACE_ERR = 14;
+  const unsigned short INVALID_ACCESS_ERR = 15;
+  const unsigned short VALIDATION_ERR = 16; // historical
+  const unsigned short TYPE_MISMATCH_ERR = 17; // historical; use JavaScript's TypeError instead
+  const unsigned short SECURITY_ERR = 18;
+  const unsigned short NETWORK_ERR = 19;
+  const unsigned short ABORT_ERR = 20;
+  const unsigned short URL_MISMATCH_ERR = 21;
+  const unsigned short QUOTA_EXCEEDED_ERR = 22;
+  const unsigned short TIMEOUT_ERR = 23;
+  const unsigned short INVALID_NODE_TYPE_ERR = 24;
+  const unsigned short DATA_CLONE_ERR = 25;
+
+  readonly attribute unsigned short code;
+};
+
+// XXXkhuey copy all of Gecko's non-standard stuff onto DOMException, but leave
+// the prototype chain sane.
+DOMException implements ExceptionMembers;
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -64,16 +64,17 @@ webidl_files = \
   DesktopNotification.webidl \
   DeviceMotionEvent.webidl \
   DeviceStorage.webidl \
   Document.webidl \
   DocumentFragment.webidl \
   DocumentType.webidl \
   DOMCursor.webidl \
   DOMError.webidl \
+  DOMException.webidl \
   DOMImplementation.webidl \
   DOMMMIError.webidl \
   DOMParser.webidl \
   DOMRequest.webidl \
   DOMSettableTokenList.webidl \
   DOMStringMap.webidl \
   DOMTokenList.webidl \
   DOMTransaction.webidl \
deleted file mode 100644
--- a/dom/workers/Exceptions.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "Exceptions.h"
-
-#include "jsapi.h"
-#include "jsfriendapi.h"
-#include "mozilla/Util.h"
-#include "nsDOMException.h"
-#include "nsTraceRefcnt.h"
-
-#include "WorkerInlines.h"
-
-#define PROPERTY_FLAGS \
-  (JSPROP_ENUMERATE | JSPROP_SHARED)
-
-#define CONSTANT_FLAGS \
-  JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_PERMANENT | JSPROP_READONLY
-
-using namespace mozilla;
-USING_WORKERS_NAMESPACE
-
-namespace {
-
-class DOMException : public PrivatizableBase
-{
-  static JSClass sClass;
-  static const JSPropertySpec sProperties[];
-  static const JSFunctionSpec sFunctions[];
-  static const JSPropertySpec sStaticProperties[];
-
-  enum SLOT {
-    SLOT_code = 0,
-    SLOT_name,
-    SLOT_message,
-
-    SLOT_COUNT
-  };
-
-public:
-  static JSObject*
-  InitClass(JSContext* aCx, JSObject* aObj)
-  {
-    JS::Rooted<JSObject*> proto(aCx, JS_InitClass(aCx, aObj, nullptr, &sClass, Construct, 0,
-                                                  sProperties, sFunctions, sStaticProperties,
-                                                  nullptr));
-    if (proto && !JS_DefineProperties(aCx, proto, sStaticProperties)) {
-      return NULL;
-    }
-
-    return proto;
-  }
-
-  static JSObject*
-  Create(JSContext* aCx, nsresult aNSResult);
-
-private:
-  DOMException()
-  {
-    MOZ_COUNT_CTOR(mozilla::dom::workers::exceptions::DOMException);
-  }
-
-  ~DOMException()
-  {
-    MOZ_COUNT_DTOR(mozilla::dom::workers::exceptions::DOMException);
-  }
-
-  static bool
-  Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
-  {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
-                         sClass.name);
-    return false;
-  }
-
-  static void
-  Finalize(JSFreeOp* aFop, JSObject* aObj)
-  {
-    JS_ASSERT(JS_GetClass(aObj) == &sClass);
-    delete GetJSPrivateSafeish<DOMException>(aObj);
-  }
-
-  static bool
-  ToString(JSContext* aCx, unsigned aArgc, jsval* aVp)
-  {
-    JS::Rooted<JSObject*> obj(aCx, JS_THIS_OBJECT(aCx, aVp));
-    if (!obj) {
-      return false;
-    }
-
-    JSClass* classPtr = JS_GetClass(obj);
-    if (classPtr != &sClass) {
-      JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
-                           JSMSG_INCOMPATIBLE_PROTO, sClass.name, "toString",
-                           classPtr->name);
-      return false;
-    }
-
-    JS::Rooted<JS::Value> name(aCx, JS_GetReservedSlot(obj, SLOT_name));
-    JS_ASSERT(name.isString());
-
-    JSString *colon = JS_NewStringCopyN(aCx, ": ", 2);
-    if (!colon){
-      return false;
-    }
-
-    JSString* out = JS_ConcatStrings(aCx, name.toString(), colon);
-    if (!out) {
-      return false;
-    }
-
-    jsval message = JS_GetReservedSlot(obj, SLOT_message);
-    JS_ASSERT(message.isString());
-
-    out = JS_ConcatStrings(aCx, out, message.toString());
-    if (!out) {
-      return false;
-    }
-
-    JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(out));
-    return true;
-  }
-
-  static bool
-  GetProperty(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aIdval,
-              JS::MutableHandle<JS::Value> aVp)
-  {
-    JS_ASSERT(JSID_IS_INT(aIdval));
-
-    int32_t slot = JSID_TO_INT(aIdval);
-
-    JSClass* classPtr = JS_GetClass(aObj);
-
-    if (classPtr != &sClass || !GetJSPrivateSafeish<DOMException>(aObj)) {
-      JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
-                           JSMSG_INCOMPATIBLE_PROTO, sClass.name,
-                           sProperties[slot].name, classPtr->name);
-      return false;
-    }
-
-    aVp.set(JS_GetReservedSlot(aObj, slot));
-    return true;
-  }
-
-  static bool
-  GetConstant(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> idval,
-              JS::MutableHandle<JS::Value> aVp)
-  {
-    JS_ASSERT(JSID_IS_INT(idval));
-    aVp.set(INT_TO_JSVAL(JSID_TO_INT(idval)));
-    return true;
-  }
-};
-
-JSClass DOMException::sClass = {
-  "DOMException",
-  JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
-  JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
-};
-
-const JSPropertySpec DOMException::sProperties[] = {
-  { "code", SLOT_code, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
-    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
-  { "name", SLOT_name, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
-    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
-  { "message", SLOT_message, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
-    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
-  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
-};
-
-const JSFunctionSpec DOMException::sFunctions[] = {
-  JS_FN("toString", ToString, 0, 0),
-  JS_FS_END
-};
-
-const JSPropertySpec DOMException::sStaticProperties[] = {
-
-#define EXCEPTION_ENTRY(_name) \
-  { #_name, _name, CONSTANT_FLAGS, JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
-
-  EXCEPTION_ENTRY(INDEX_SIZE_ERR)
-  EXCEPTION_ENTRY(DOMSTRING_SIZE_ERR)
-  EXCEPTION_ENTRY(HIERARCHY_REQUEST_ERR)
-  EXCEPTION_ENTRY(WRONG_DOCUMENT_ERR)
-  EXCEPTION_ENTRY(INVALID_CHARACTER_ERR)
-  EXCEPTION_ENTRY(NO_DATA_ALLOWED_ERR)
-  EXCEPTION_ENTRY(NO_MODIFICATION_ALLOWED_ERR)
-  EXCEPTION_ENTRY(NOT_FOUND_ERR)
-  EXCEPTION_ENTRY(NOT_SUPPORTED_ERR)
-  EXCEPTION_ENTRY(INUSE_ATTRIBUTE_ERR)
-  EXCEPTION_ENTRY(INVALID_STATE_ERR)
-  EXCEPTION_ENTRY(SYNTAX_ERR)
-  EXCEPTION_ENTRY(INVALID_MODIFICATION_ERR)
-  EXCEPTION_ENTRY(NAMESPACE_ERR)
-  EXCEPTION_ENTRY(INVALID_ACCESS_ERR)
-  EXCEPTION_ENTRY(VALIDATION_ERR)
-  EXCEPTION_ENTRY(TYPE_MISMATCH_ERR)
-  EXCEPTION_ENTRY(SECURITY_ERR)
-  EXCEPTION_ENTRY(NETWORK_ERR)
-  EXCEPTION_ENTRY(ABORT_ERR)
-  EXCEPTION_ENTRY(URL_MISMATCH_ERR)
-  EXCEPTION_ENTRY(QUOTA_EXCEEDED_ERR)
-  EXCEPTION_ENTRY(TIMEOUT_ERR)
-  EXCEPTION_ENTRY(INVALID_NODE_TYPE_ERR)
-  EXCEPTION_ENTRY(DATA_CLONE_ERR)
-
-#undef EXCEPTION_ENTRY
-
-  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
-};
-
-// static
-JSObject*
-DOMException::Create(JSContext* aCx, nsresult aNSResult)
-{
-  JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, &sClass, NULL, NULL));
-  if (!obj) {
-    return NULL;
-  }
-
-  const char* name;
-  const char* message;
-  uint16_t code;
-  if (NS_FAILED(NS_GetNameAndMessageForDOMNSResult(aNSResult, &name, &message,
-                                                   &code))) {
-    JS_ReportError(aCx, "Exception thrown (nsresult = 0x%x).", aNSResult);
-    return NULL;
-  }
-
-  JS::Rooted<JSString*> jsname(aCx, JS_NewStringCopyZ(aCx, name));
-  if (!jsname) {
-    return NULL;
-  }
-
-  JS::Rooted<JSString*> jsmessage(aCx, JS_NewStringCopyZ(aCx, message));
-  if (!jsmessage) {
-    return NULL;
-  }
-
-  JS_SetReservedSlot(obj, SLOT_code, INT_TO_JSVAL(code));
-  JS_SetReservedSlot(obj, SLOT_name, STRING_TO_JSVAL(jsname));
-  JS_SetReservedSlot(obj, SLOT_message, STRING_TO_JSVAL(jsmessage));
-
-  DOMException* priv = new DOMException();
-  SetJSPrivateSafeish(obj, priv);
-
-  return obj;
-}
-
-} // anonymous namespace
-
-BEGIN_WORKERS_NAMESPACE
-
-namespace exceptions {
-
-bool
-InitClasses(JSContext* aCx, JSObject* aGlobal)
-{
-  return DOMException::InitClass(aCx, aGlobal);
-}
-
-void
-ThrowDOMExceptionForNSResult(JSContext* aCx, nsresult aNSResult)
-{
-  JSObject* exception = DOMException::Create(aCx, aNSResult);
-  if (!exception) {
-    return;
-  }
-
-  JS_SetPendingException(aCx, OBJECT_TO_JSVAL(exception));
-}
-
-} // namespace exceptions
-
-END_WORKERS_NAMESPACE
deleted file mode 100644
--- a/dom/workers/Exceptions.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_workers_exceptions_h__
-#define mozilla_dom_workers_exceptions_h__
-
-#include "Workers.h"
-
-// DOMException Codes.
-#define INDEX_SIZE_ERR 1
-#define DOMSTRING_SIZE_ERR 2
-#define HIERARCHY_REQUEST_ERR 3
-#define WRONG_DOCUMENT_ERR 4
-#define INVALID_CHARACTER_ERR 5
-#define NO_DATA_ALLOWED_ERR 6
-#define NO_MODIFICATION_ALLOWED_ERR 7
-#define NOT_FOUND_ERR 8
-#define NOT_SUPPORTED_ERR 9
-#define INUSE_ATTRIBUTE_ERR 10
-#define INVALID_STATE_ERR 11
-#define SYNTAX_ERR 12
-#define INVALID_MODIFICATION_ERR 13
-#define NAMESPACE_ERR 14
-#define INVALID_ACCESS_ERR 15
-#define VALIDATION_ERR 16
-#define TYPE_MISMATCH_ERR 17
-#define SECURITY_ERR 18
-#define NETWORK_ERR 19
-#define ABORT_ERR 20
-#define URL_MISMATCH_ERR 21
-#define QUOTA_EXCEEDED_ERR 22
-#define TIMEOUT_ERR 23
-#define INVALID_NODE_TYPE_ERR 24
-#define DATA_CLONE_ERR 25
-
-BEGIN_WORKERS_NAMESPACE
-
-namespace exceptions {
-
-bool
-InitClasses(JSContext* aCx, JSObject* aGlobal);
-
-} // namespace exceptions
-
-END_WORKERS_NAMESPACE
-
-#endif // mozilla_dom_workers_exceptions_h__
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -11,26 +11,25 @@
 #include "nsError.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsCOMPtr.h"
 #include "nsJSUtils.h"
 #include "nsStringGlue.h"
 
-#include "Exceptions.h"
+#include "mozilla/dom/Exceptions.h"
 #include "WorkerInlines.h"
 #include "WorkerPrivate.h"
 
 #define PROPERTY_FLAGS \
   (JSPROP_ENUMERATE | JSPROP_SHARED)
 
 USING_WORKERS_NAMESPACE
-
-using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
+using mozilla::dom::Throw;
 
 namespace {
 
 class Blob
 {
   // Blob should never be instantiated.
   Blob();
   ~Blob();
@@ -85,18 +84,17 @@ private:
   }
 
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     nsRefPtr<nsDOMMultipartFile> file = new nsDOMMultipartFile();
     nsresult rv = file->InitBlob(aCx, aArgc, JS_ARGV(aCx, aVp), Unwrap);
     if (NS_FAILED(rv)) {
-      ThrowDOMExceptionForNSResult(aCx, rv);
-      return false;
+      return Throw(aCx, rv);
     }
 
     JSObject* obj = file::CreateBlob(aCx, file);
     if (!obj) {
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(obj));
@@ -118,18 +116,17 @@ private:
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "size");
     if (!blob) {
       return false;
     }
 
     uint64_t size;
     if (NS_FAILED(blob->GetSize(&size))) {
-      ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
-      return false;
+      return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
     }
 
     aVp.set(JS_NumberValue(double(size)));
 
     return true;
   }
 
   static bool
@@ -138,18 +135,17 @@ private:
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "type");
     if (!blob) {
       return false;
     }
 
     nsString type;
     if (NS_FAILED(blob->GetType(type))) {
-      ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
-      return false;
+      return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
     }
 
     JSString* jsType = JS_NewUCStringCopyN(aCx, type.get(), type.Length());
     if (!jsType) {
       return false;
     }
 
     aVp.set(STRING_TO_JSVAL(jsType));
@@ -183,18 +179,17 @@ private:
     }
 
     uint8_t optionalArgc = aArgc;
     nsCOMPtr<nsIDOMBlob> rtnBlob;
     if (NS_FAILED(blob->Slice(static_cast<uint64_t>(start),
                               static_cast<uint64_t>(end),
                               contentType, optionalArgc,
                               getter_AddRefs(rtnBlob)))) {
-      ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
-      return false;
+      return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
     }
 
     JSObject* rtnObj = file::CreateBlob(aCx, rtnBlob);
     if (!rtnObj) {
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(rtnObj));
@@ -311,18 +306,17 @@ private:
     if (!file) {
       return false;
     }
 
     nsString fullPath;
 
     if (GetWorkerPrivateFromContext(aCx)->UsesSystemPrincipal() &&
         NS_FAILED(file->GetMozFullPathInternal(fullPath))) {
-      ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
-      return false;
+      return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
     }
 
     JSString* jsFullPath = JS_NewUCStringCopyN(aCx, fullPath.get(),
                                                fullPath.Length());
     if (!jsFullPath) {
       return false;
     }
 
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -1107,28 +1107,40 @@ WorkerCrossThreadDispatcher::PostTask(Wo
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   return static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(JS_GetRuntime(aCx)))->mWorkerPrivate;
 }
 
-bool
-IsCurrentThreadRunningChromeWorker()
+WorkerPrivate*
+GetCurrentThreadWorkerPrivate()
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
-  CycleCollectedJSRuntime* ccrt = nsCycleCollector_currentJSRuntime();
+  MOZ_ASSERT(!NS_IsMainThread(), "Wrong thread!");
+  CycleCollectedJSRuntime* ccrt = CycleCollectedJSRuntime::Get();
   if (!ccrt) {
-    return false;
+    return nullptr;
   }
 
   JSRuntime* rt = ccrt->Runtime();
   return static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(rt))->
-    mWorkerPrivate->UsesSystemPrincipal();
+    mWorkerPrivate;
+}
+
+bool
+IsCurrentThreadRunningChromeWorker()
+{
+  return GetCurrentThreadWorkerPrivate()->UsesSystemPrincipal();
+}
+
+JSContext*
+GetCurrentThreadJSContext()
+{
+  return GetCurrentThreadWorkerPrivate()->GetJSContext();
 }
 
 END_WORKERS_NAMESPACE
 
 // This is only touched on the main thread. Initialized in Init() below.
 JSSettings RuntimeService::sDefaultJSSettings;
 
 RuntimeService::RuntimeService()
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -26,17 +26,17 @@
 #include "nsNetUtil.h"
 #include "nsScriptLoader.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOM.h"
 #include "xpcpublic.h"
 
-#include "Exceptions.h"
+#include "mozilla/dom/Exceptions.h"
 #include "Principal.h"
 #include "WorkerFeature.h"
 #include "WorkerPrivate.h"
 
 #define MAX_CONCURRENT_SCRIPTS 1000
 
 BEGIN_WORKERS_NAMESPACE
 
@@ -54,17 +54,17 @@ ChannelFromScriptURL(nsIPrincipal* princ
                      nsIChannel** aChannel);
 
 } // namespace scriptloader
 
 END_WORKERS_NAMESPACE
 
 USING_WORKERS_NAMESPACE
 
-using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
+using mozilla::dom::Throw;
 
 namespace {
 
 class ScriptLoaderRunnable;
 
 struct ScriptLoadInfo
 {
   ScriptLoadInfo()
@@ -875,22 +875,17 @@ void ReportLoadError(JSContext* aCx, con
 
     case NS_ERROR_FILE_NOT_FOUND:
     case NS_ERROR_NOT_AVAILABLE:
       JS_ReportError(aCx, "Script file not found: %s", url.get());
       break;
 
     case NS_ERROR_DOM_SECURITY_ERR:
     case NS_ERROR_DOM_SYNTAX_ERR:
-      if (aIsMainThread) {
-        AssertIsOnMainThread();
-        xpc::Throw(aCx, aLoadResult);
-      } else {
-        ThrowDOMExceptionForNSResult(aCx, aLoadResult);
-      }
+      Throw(aCx, aLoadResult);
       break;
 
     default:
       JS_ReportError(aCx, "Failed to load script: %s (nsresult = 0x%x)",
                      url.get(), aLoadResult);
   }
 }
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WorkerPrivate.h"
 
 #include "amIAddonManager.h"
 #include "nsIClassInfo.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIConsoleService.h"
+#include "nsIDOMDOMException.h"
 #include "nsIDOMFile.h"
 #include "nsIDocument.h"
 #include "nsIDocShell.h"
 #include "nsIMemoryReporter.h"
 #include "nsIPermissionManager.h"
 #include "nsIScriptError.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
@@ -50,17 +51,17 @@
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 #include "Events.h"
-#include "Exceptions.h"
+#include "mozilla/dom/Exceptions.h"
 #include "File.h"
 #include "Principal.h"
 #include "RuntimeService.h"
 #include "ScriptLoader.h"
 #include "Worker.h"
 #include "WorkerFeature.h"
 #include "WorkerScope.h"
 
@@ -68,17 +69,17 @@
 #define NORMAL_GC_TIMER_DELAY_MS 30000
 
 // GC will run five seconds after the last event is processed.
 #define IDLE_GC_TIMER_DELAY_MS 5000
 
 using mozilla::MutexAutoLock;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
-using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
+using mozilla::dom::Throw;
 using mozilla::AutoPushJSContext;
 using mozilla::AutoSafeJSContext;
 
 USING_WORKERS_NAMESPACE
 using namespace mozilla::dom::workers::events;
 using namespace mozilla::dom;
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf)
@@ -272,17 +273,17 @@ struct WorkerStructuredCloneCallbacks
 
     Error(aCx, 0);
     return false;
   }
 
   static void
   Error(JSContext* aCx, uint32_t /* aErrorId */)
   {
-    ThrowDOMExceptionForNSResult(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
+    Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
   }
 };
 
 JSStructuredCloneCallbacks gWorkerStructuredCloneCallbacks = {
   WorkerStructuredCloneCallbacks::Read,
   WorkerStructuredCloneCallbacks::Write,
   WorkerStructuredCloneCallbacks::Error
 };
@@ -317,17 +318,17 @@ struct MainThreadWorkerStructuredCloneCa
         // nsIDOMFiles should be threadsafe, thus we will use the same instance
         // on the main thread.
         JS::Rooted<JS::Value> wrappedFile(aCx);
         JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
         nsresult rv = nsContentUtils::WrapNative(aCx, global, file,
                                                  &NS_GET_IID(nsIDOMFile),
                                                  wrappedFile.address());
         if (NS_FAILED(rv)) {
-          Error(aCx, DATA_CLONE_ERR);
+          Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR);
           return nullptr;
         }
 
         return &wrappedFile.toObject();
       }
     }
     // See if object is a nsIDOMBlob pointer.
     else if (aTag == DOMWORKER_SCTAG_BLOB) {
@@ -351,17 +352,17 @@ struct MainThreadWorkerStructuredCloneCa
         // nsIDOMBlobs should be threadsafe, thus we will use the same instance
         // on the main thread.
         JS::Rooted<JS::Value> wrappedBlob(aCx);
         JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
         nsresult rv = nsContentUtils::WrapNative(aCx, global, blob,
                                                  &NS_GET_IID(nsIDOMBlob),
                                                  wrappedBlob.address());
         if (NS_FAILED(rv)) {
-          Error(aCx, DATA_CLONE_ERR);
+          Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR);
           return nullptr;
         }
 
         return &wrappedBlob.toObject();
       }
     }
 
     JS_ClearPendingException(aCx);
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -966,16 +966,19 @@ private:
 };
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx);
 
 bool
 IsCurrentThreadRunningChromeWorker();
 
+JSContext*
+GetCurrentThreadJSContext();
+
 enum WorkerStructuredDataType
 {
   DOMWORKER_SCTAG_FILE = SCTAG_DOM_MAX,
   DOMWORKER_SCTAG_BLOB,
 
   DOMWORKER_SCTAG_END
 };
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -7,39 +7,40 @@
 #include "WorkerScope.h"
 
 #include "jsapi.h"
 #include "js/OldDebugAPI.h"
 #include "mozilla/Util.h"
 #include "mozilla/dom/DOMJSClass.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/FileReaderSyncBinding.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ImageDataBinding.h"
 #include "mozilla/dom/TextDecoderBinding.h"
 #include "mozilla/dom/TextEncoderBinding.h"
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "mozilla/dom/XMLHttpRequestUploadBinding.h"
 #include "mozilla/dom/URLBinding.h"
 #include "mozilla/dom/WorkerLocationBinding.h"
 #include "mozilla/dom/WorkerNavigatorBinding.h"
 #include "mozilla/OSFileConstants.h"
+#include "nsIGlobalObject.h"
 #include "nsTraceRefcnt.h"
 #include "xpcpublic.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 #include "ChromeWorkerScope.h"
 #include "Events.h"
 #include "EventListenerManager.h"
 #include "EventTarget.h"
-#include "Exceptions.h"
 #include "File.h"
 #include "FileReaderSync.h"
 #include "Location.h"
 #include "Navigator.h"
 #include "Principal.h"
 #include "ScriptLoader.h"
 #include "Worker.h"
 #include "WorkerPrivate.h"
@@ -54,17 +55,18 @@
   JSPROP_ENUMERATE
 
 using namespace mozilla;
 using namespace mozilla::dom;
 USING_WORKERS_NAMESPACE
 
 namespace {
 
-class WorkerGlobalScope : public workers::EventTarget
+class WorkerGlobalScope : public workers::EventTarget,
+                          public nsIGlobalObject
 {
   static JSClass sClass;
   static const JSPropertySpec sProperties[];
   static const JSFunctionSpec sFunctions[];
 
   enum
   {
     SLOT_wrappedScope = 0,
@@ -122,16 +124,25 @@ protected:
     }
   }
 
   ~WorkerGlobalScope()
   {
     MOZ_COUNT_DTOR(mozilla::dom::workers::WorkerGlobalScope);
   }
 
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIGlobalObject
+  virtual JSObject* GetGlobalJSObject() MOZ_OVERRIDE
+  {
+    mWorker->AssertIsOnWorkerThread();
+    return GetJSObject();
+  }
+
   virtual void
   _trace(JSTracer* aTrc) MOZ_OVERRIDE
   {
     for (int32_t i = 0; i < SLOT_COUNT; i++) {
       JS_CallHeapValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot");
     }
     mWorker->TraceInternal(aTrc);
     EventTarget::_trace(aTrc);
@@ -605,16 +616,24 @@ private:
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, result);
     return true;
   }
 };
 
+NS_IMPL_ADDREF_INHERITED(WorkerGlobalScope, workers::EventTarget)
+NS_IMPL_RELEASE_INHERITED(WorkerGlobalScope, workers::EventTarget)
+
+NS_INTERFACE_MAP_BEGIN(WorkerGlobalScope)
+  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, DOMBindingBase)
+NS_INTERFACE_MAP_END
+
 JSClass WorkerGlobalScope::sClass = {
   "WorkerGlobalScope",
   0,
   JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 const JSPropertySpec WorkerGlobalScope::sProperties[] = {
@@ -1029,23 +1048,23 @@ CreateDedicatedWorkerGlobalScope(JSConte
         !DefineChromeWorkerFunctions(aCx, global) ||
         !DefineOSFileConstants(aCx, global)) {
       return NULL;
     }
   }
 
   // Init other classes we care about.
   if (!events::InitClasses(aCx, global, false) ||
-      !file::InitClasses(aCx, global) ||
-      !exceptions::InitClasses(aCx, global)) {
+      !file::InitClasses(aCx, global)) {
     return NULL;
   }
 
   // Init other paris-bindings.
-  if (!FileReaderSyncBinding_workers::GetConstructorObject(aCx, global) ||
+  if (!DOMExceptionBinding::GetConstructorObject(aCx, global) ||
+      !FileReaderSyncBinding_workers::GetConstructorObject(aCx, global) ||
       !ImageDataBinding::GetConstructorObject(aCx, global) ||
       !TextDecoderBinding::GetConstructorObject(aCx, global) ||
       !TextEncoderBinding::GetConstructorObject(aCx, global) ||
       !XMLHttpRequestBinding_workers::GetConstructorObject(aCx, global) ||
       !XMLHttpRequestUploadBinding_workers::GetConstructorObject(aCx, global) ||
       !URLBinding_workers::GetConstructorObject(aCx, global) ||
       !WorkerLocationBinding_workers::GetConstructorObject(aCx, global) ||
       !WorkerNavigatorBinding_workers::GetConstructorObject(aCx, global)) {
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -17,33 +17,31 @@
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 #include "nsXMLHttpRequest.h"
 
 #include "Events.h"
 #include "EventTarget.h"
-#include "Exceptions.h"
+#include "mozilla/dom/Exceptions.h"
 #include "File.h"
 #include "RuntimeService.h"
 #include "WorkerPrivate.h"
 #include "XMLHttpRequestUpload.h"
 
 #include "DOMBindingInlines.h"
 #include "mozilla/Attributes.h"
 #include "nsComponentManagerUtils.h"
 
 using namespace mozilla;
 
 using namespace mozilla::dom;
 USING_WORKERS_NAMESPACE
 
-using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
-
 // XXX Need to figure this out...
 #define UNCATCHABLE_EXCEPTION NS_ERROR_OUT_OF_MEMORY
 
 /**
  *  XMLHttpRequest in workers
  *
  *  XHR in workers is implemented by proxying calls/events/etc between the
  *  worker thread and an nsXMLHttpRequest on the main thread.  The glue
@@ -798,17 +796,17 @@ private:
     {
       NS_ASSERTION(aProxy, "Don't hand me a null proxy!");
     }
 
     bool
     WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
     {
       if (NS_FAILED(mErrorCode)) {
-        ThrowDOMExceptionForNSResult(aCx, mErrorCode);
+        Throw(aCx, mErrorCode);
         aWorkerPrivate->StopSyncLoop(mSyncQueueKey, false);
       }
       else {
         aWorkerPrivate->StopSyncLoop(mSyncQueueKey, true);
       }
 
       return true;
     }
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -29,17 +29,16 @@ EXPORTS.mozilla.dom.workers.bindings += 
 ]
 
 CPP_SOURCES += [
     'ChromeWorkerScope.cpp',
     'DOMBindingBase.cpp',
     'EventListenerManager.cpp',
     'EventTarget.cpp',
     'Events.cpp',
-    'Exceptions.cpp',
     'File.cpp',
     'FileReaderSync.cpp',
     'Location.cpp',
     'Navigator.cpp',
     'Principal.cpp',
     'RuntimeService.cpp',
     'ScriptLoader.cpp',
     'URL.cpp',
--- a/embedding/test/test_nsFind.html
+++ b/embedding/test/test_nsFind.html
@@ -31,49 +31,65 @@ https://bugzilla.mozilla.org/show_bug.cg
   var startPt = searchRange;
   var endPt = searchRange;
 
   // Check |null| detection on |aPatText| parameter.
   try {
     rf.Find(null, searchRange, startPt, endPt);
 
     ok(false, "Missing NS_ERROR_NULL_POINTER exception");
-  } catch (e if (e instanceof SpecialPowers.Ci.nsIException &&
-                 e.result == SpecialPowers.Cr.NS_ERROR_NULL_POINTER)) {
-    ok(true, null);
+  } catch (e) {
+    e = SpecialPowers.wrap(e);
+    if (e.result == SpecialPowers.Cr.NS_ERROR_NULL_POINTER) {
+      ok(true, null);
+    } else {
+      throw e;
+    }
   }
 
   // Check |null| detection on |aSearchRange| parameter.
   try {
     rf.Find("", null, startPt, endPt);
 
     ok(false, "Missing NS_ERROR_ILLEGAL_VALUE exception");
-  } catch (e if (e instanceof SpecialPowers.Ci.nsIException &&
-                 e.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE)) {
-    ok(true, null);
+  } catch (e) {
+    e = SpecialPowers.wrap(e);
+    if (e.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE) {
+      ok(true, null);
+    } else {
+      throw e;
+    }
   }
 
   // Check |null| detection on |aStartPoint| parameter.
   try {
     rf.Find("", searchRange, null, endPt);
 
     ok(false, "Missing NS_ERROR_ILLEGAL_VALUE exception");
-  } catch (e if (e instanceof SpecialPowers.Ci.nsIException &&
-                 e.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE)) {
-    ok(true, null);
+  } catch (e) {
+    e = SpecialPowers.wrap(e);
+    if (e.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE) {
+      ok(true, null);
+    } else {
+      throw e;
+    }
   }
 
   // Check |null| detection on |aEndPoint| parameter.
   try {
     rf.Find("", searchRange, startPt, null);
 
     ok(false, "Missing NS_ERROR_ILLEGAL_VALUE exception");
-  } catch (e if (e instanceof SpecialPowers.Ci.nsIException &&
-                 e.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE)) {
-    ok(true, null);
+  } catch (e) {
+    e = SpecialPowers.wrap(e);
+    if (e.result == SpecialPowers.Cr.NS_ERROR_ILLEGAL_VALUE) {
+      ok(true, null);
+    } else {
+      throw e;
+    }
   }
 
   var searchValue, retRange;
 
   rf.findBackwards = false;
 
   rf.caseSensitive = false;
 
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_COMPOSITOR_H
 #define MOZILLA_GFX_COMPOSITOR_H
 
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "Units.h"                      // for ScreenPoint
 #include "gfxPoint.h"                   // for gfxIntSize
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for TemporaryRef, RefCounted
 #include "mozilla/gfx/Point.h"          // for IntSize, Point
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for Float
 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticTypes, etc
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_LAYERS_H
 #define GFX_LAYERS_H
 
 #include <stdint.h>                     // for uint32_t, uint64_t, uint8_t
 #include <stdio.h>                      // for FILE
 #include <sys/types.h>                  // for int32_t, int64_t
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "Units.h"                      // for LayerMargin, LayerPoint
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "gfxColor.h"                   // for gfxRGBA
 #include "gfxMatrix.h"                  // for gfxMatrix
 #include "gfxPattern.h"                 // for gfxPattern, etc
 #include "gfxPoint.h"                   // for gfxPoint, gfxIntSize
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -1,14 +1,13 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "./../mozilla-config.h"        // for MOZ_X11
 #include "BasicLayersImpl.h"            // for FillWithMask, etc
 #include "ImageContainer.h"             // for AutoLockImage, etc
 #include "ImageLayers.h"                // for ImageLayer
 #include "Layers.h"                     // for Layer (ptr only), etc
 #include "basic/BasicImplData.h"        // for BasicImplData
 #include "basic/BasicLayers.h"          // for BasicLayerManager
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "gfxContext.h"                 // for gfxContext
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -201,26 +201,22 @@ DeprecatedCanvasClientSurfaceStream::Upd
     SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
     mDeprecatedTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
 #else
     printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
     MOZ_ASSERT(false);
 #endif
   } else {
     SurfaceStreamHandle handle = stream->GetShareHandle();
-    SurfaceDescriptor *desc = mDeprecatedTextureClient->GetDescriptor();
-    if (desc->type() != SurfaceDescriptor::TSurfaceStreamDescriptor ||
-        desc->get_SurfaceStreamDescriptor().handle() != handle) {
-      *desc = SurfaceStreamDescriptor(handle, false);
+    mDeprecatedTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
 
-      // Bug 894405
-      //
-      // Ref this so the SurfaceStream doesn't disappear unexpectedly. The
-      // Compositor will need to unref it when finished.
-      aLayer->mGLContext->AddRef();
-    }
+    // Bug 894405
+    //
+    // Ref this so the SurfaceStream doesn't disappear unexpectedly. The
+    // Compositor will need to unref it when finished.
+    aLayer->mGLContext->AddRef();
   }
 
   aLayer->Painted();
 }
 
 }
 }
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_BUFFERHOST_H
 #define MOZILLA_GFX_BUFFERHOST_H
 
 #include <stdint.h>                     // for uint64_t
 #include <stdio.h>                      // for FILE
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "gfxPoint.h"                   // for gfxSize
 #include "gfxRect.h"                    // for gfxRect
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr, RefCounted, etc
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Filter
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ContainerLayerComposite.h"
 #include <algorithm>                    // for min
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "Units.h"                      // for LayerRect, LayerPixel, etc
 #include "gfx2DGlue.h"                  // for ToMatrix4x4
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxMatrix.h"                  // for gfxMatrix
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "gfxUtils.h"                   // for gfxUtils, etc
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -2,17 +2,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_IMAGEHOST_H
 #define MOZILLA_GFX_IMAGEHOST_H
 
 #include <stdio.h>                      // for FILE, NULL
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "CompositableHost.h"           // for CompositableHost
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Filter
 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ImageLayerComposite.h"
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "CompositableHost.h"           // for CompositableHost
 #include "Layers.h"                     // for WriteSnapshotToDumpFile, etc
 #include "gfx2DGlue.h"                  // for ToFilter, ToMatrix4x4
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxPoint.h"                   // for gfxIntSize
 #include "gfxRect.h"                    // for gfxRect
 #include "gfxUtils.h"                   // for gfxUtils, etc
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -180,22 +180,16 @@ public:
   /**
    * Setup World transform matrix.
    * Transform will be ignored if it is not PreservesAxisAlignedRectangles
    * or has non integer scale
    */
   void SetWorldTransform(const gfxMatrix& aMatrix);
   gfxMatrix& GetWorldTransform(void);
 
-  static bool AddMaskEffect(Layer* aMaskLayer,
-                            EffectChain& aEffect,
-                            bool aIs3D = false);
-
-  static void RemoveMaskEffect(Layer* aMaskLayer);
-
   /**
    * RAII helper class to add a mask effect with the compositable from aMaskLayer
    * to the EffectChain aEffect and notify the compositable when we are done.
    */
   class AutoAddMaskEffect
   {
   public:
     AutoAddMaskEffect(Layer* aMaskLayer,
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -3,17 +3,16 @@
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_TEXTUREHOST_H
 #define MOZILLA_GFX_TEXTUREHOST_H
 
 #include <stddef.h>                     // for size_t
 #include <stdint.h>                     // for uint64_t, uint32_t, uint8_t
-#include "./../mozilla-config.h"        // for MOZ_DUMP_PAINTING
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef, etc
 #include "mozilla/gfx/2D.h"             // for DataSourceSurface
 #include "mozilla/gfx/Point.h"          // for IntSize, IntPoint
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat, etc
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags, etc
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ThebesLayerComposite.h"
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "CompositableHost.h"           // for TiledLayerProperties, etc
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "Units.h"                      // for CSSRect, LayerPixel, etc
 #include "gfx2DGlue.h"                  // for ToMatrix4x4
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -55,18 +55,19 @@ struct DeviceAttachmentsD3D11
   RefPtr<ID3D11SamplerState> mLinearSamplerState;
   RefPtr<ID3D11SamplerState> mPointSamplerState;
   RefPtr<ID3D11BlendState> mPremulBlendState;
   RefPtr<ID3D11BlendState> mNonPremulBlendState;
   RefPtr<ID3D11BlendState> mComponentBlendState;
 };
 
 CompositorD3D11::CompositorD3D11(nsIWidget* aWidget)
-  : mWidget(aWidget)
-  , mAttachments(nullptr)
+  : mAttachments(nullptr)
+  , mWidget(aWidget)
+  , mHwnd(nullptr)
 {
   sBackend = LAYERS_D3D11;
 }
 
 CompositorD3D11::~CompositorD3D11()
 {
   if (mDevice) {
     int referenceCount = 0;
@@ -103,16 +104,18 @@ CompositorD3D11::Initialize()
   }
 
   mDevice->GetImmediateContext(byRef(mContext));
 
   if (!mContext) {
     return false;
   }
 
+  mHwnd = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
+
   memset(&mVSConstants, 0, sizeof(VertexShaderConstants));
 
   int referenceCount = 0;
   UINT size = sizeof(referenceCount);
   // If this isn't there yet it'll fail, count will remain 0, which is correct.
   mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
   referenceCount++;
   mDevice->SetPrivateData(sLayerManagerCount,
@@ -297,17 +300,17 @@ CompositorD3D11::Initialize()
     swapDesc.BufferDesc.Height = 0;
     swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     swapDesc.BufferDesc.RefreshRate.Numerator = 60;
     swapDesc.BufferDesc.RefreshRate.Denominator = 1;
     swapDesc.SampleDesc.Count = 1;
     swapDesc.SampleDesc.Quality = 0;
     swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
     swapDesc.BufferCount = 1;
-    swapDesc.OutputWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
+    swapDesc.OutputWindow = mHwnd;
     swapDesc.Windowed = TRUE;
     // We don't really need this flag, however it seems on some NVidia hardware
     // smaller area windows do not present properly without this flag. This flag
     // should have no negative consequences by itself. See bug 613790. This flag
     // is broken on optimus devices. As a temporary solution we don't set it
     // there, the only way of reliably detecting we're on optimus is looking for
     // the DLL. See Bug 623807.
     if (gfxWindowsPlatform::IsOptimus()) {
@@ -619,16 +622,25 @@ CompositorD3D11::DrawQuad(const gfx::Rec
 
 void
 CompositorD3D11::BeginFrame(const Rect* aClipRectIn,
                             const gfxMatrix& aTransform,
                             const Rect& aRenderBounds,
                             Rect* aClipRectOut,
                             Rect* aRenderBoundsOut)
 {
+  // Don't composite if we are minimised. Other than for the sake of efficency,
+  // this is important because resizing our buffers when mimised will fail and
+  // cause a crash when we're restored.
+  NS_ASSERTION(mHwnd, "Couldn't find an HWND when initialising?");
+  if (::IsIconic(mHwnd)) {
+    *aRenderBoundsOut = Rect();
+    return;
+  }
+
   UpdateRenderTarget();
 
   // Failed to create a render target.
   if (!mDefaultRT ||
       mSize.width == 0 || mSize.height == 0) {
     *aRenderBoundsOut = Rect();
     return;
   }
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -115,16 +115,17 @@ DeprecatedTextureClientD3D11::EnsureAllo
   RefPtr<IDXGIResource> resource;
   mTexture->QueryInterface((IDXGIResource**)byRef(resource));
 
   HANDLE sharedHandle;
   hr = resource->GetSharedHandle(&sharedHandle);
 
   if (FAILED(hr)) {
     LOGD3D11("Error getting shared handle for texture.");
+    return false;
   }
 
   mDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle,
                                        aType == gfxASurface::CONTENT_COLOR_ALPHA);
 
   mContentType = aType;
   return true;
 }
@@ -169,19 +170,20 @@ DeprecatedTextureClientD3D11::SetDescrip
 
   if (aDescriptor.type() == SurfaceDescriptor::T__None) {
     return;
   }
 
   MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorD3D10);
   ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
 
-  device->OpenSharedResource((HANDLE)aDescriptor.get_SurfaceDescriptorD3D10().handle(),
-                             __uuidof(ID3D10Texture2D),
-                             (void**)(ID3D10Texture2D**)byRef(mTexture));
+  HRESULT hr = device->OpenSharedResource((HANDLE)aDescriptor.get_SurfaceDescriptorD3D10().handle(),
+                                          __uuidof(ID3D10Texture2D),
+                                          (void**)(ID3D10Texture2D**)byRef(mTexture));
+  NS_WARN_IF_FALSE(mTexture && SUCCEEDED(hr), "Could not open shared resource");
 }
 
 void
 DeprecatedTextureClientD3D11::EnsureSurface()
 {
   if (mSurface) {
     return;
   }
@@ -416,39 +418,51 @@ DeprecatedTextureHostDXGID3D11::Unlock()
 
 void
 DeprecatedTextureHostDXGID3D11::UpdateImpl(const SurfaceDescriptor& aImage,
                                            nsIntRegion* aRegion,
                                            nsIntPoint* aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorD3D10);
 
-  mDevice->OpenSharedResource((HANDLE)aImage.get_SurfaceDescriptorD3D10().handle(),
-                              __uuidof(ID3D11Texture2D),
-                              (void**)(ID3D11Texture2D**)byRef(mTextures[0]));
+  HRESULT hr =mDevice->OpenSharedResource((HANDLE)aImage.get_SurfaceDescriptorD3D10().handle(),
+                                          __uuidof(ID3D11Texture2D),
+                                          (void**)(ID3D11Texture2D**)byRef(mTextures[0]));
+  if (!mTextures[0] || FAILED(hr)) {
+    NS_WARNING("Could not open shared resource");
+    mSize = IntSize(0, 0);
+    return;
+  }
+
   mFormat = aImage.get_SurfaceDescriptorD3D10().hasAlpha() ? FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8;
 
   D3D11_TEXTURE2D_DESC desc;
   mTextures[0]->GetDesc(&desc);
 
   mSize = IntSize(desc.Width, desc.Height);
 }
 
 void
 DeprecatedTextureHostDXGID3D11::LockTexture()
 {
+  if (!mTextures[0]) {
+    return;
+  }
   RefPtr<IDXGIKeyedMutex> mutex;
   mTextures[0]->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
 
   mutex->AcquireSync(0, INFINITE);
 }
 
 void
 DeprecatedTextureHostDXGID3D11::ReleaseTexture()
 {
+  if (!mTextures[0]) {
+    return;
+  }
   RefPtr<IDXGIKeyedMutex> mutex;
   mTextures[0]->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
 
   mutex->ReleaseSync(0);
 }
 
 void
 DeprecatedTextureHostYCbCrD3D11::SetCompositor(Compositor* aCompositor)
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CompositorParent.h"
 #include <stdio.h>                      // for fprintf, stdout
 #include <stdint.h>                     // for uint64_t
 #include <map>                          // for _Rb_tree_iterator, etc
 #include <utility>                      // for pair
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "AutoOpenSurface.h"            // for AutoOpenSurface
 #include "LayerTransactionParent.h"     // for LayerTransactionParent
 #include "RenderTrace.h"                // for RenderTraceLayers
 #include "base/message_loop.h"          // for MessageLoop
 #include "base/process.h"               // for ProcessHandle
 #include "base/process_util.h"          // for OpenProcessHandle
 #include "base/task.h"                  // for CancelableTask, etc
 #include "base/thread.h"                // for Thread
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -14,17 +14,16 @@
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxPoint.h"                   // for gfxIntSize
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "opengl/LayerManagerOGLProgram.h"  // for ShaderProgramType, etc
-#include "./../mozilla-config.h"        // for GL_PROVIDER_GLX
 #if defined(GL_PROVIDER_GLX)
 #include "GLXLibrary.h"
 #include "mozilla/X11Util.h"
 #endif
 
 struct nsIntPoint;
 
 
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.h
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_COMPOSITINGRENDERTARGETOGL_H
 #define MOZILLA_GFX_COMPOSITINGRENDERTARGETOGL_H
 
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "GLContextTypes.h"             // for GLContext
 #include "GLDefs.h"                     // for GLenum, LOCAL_GL_FRAMEBUFFER, etc
 #include "gfxMatrix.h"                  // for gfxMatrix
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef
 #include "mozilla/gfx/Point.h"          // for IntSize, IntSizeTyped
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat, etc
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_COMPOSITOROGL_H
 #define MOZILLA_GFX_COMPOSITOROGL_H
 
-#include "./../mozilla-config.h"        // for MOZ_DUMP_PAINTING
 #include "GLContextTypes.h"             // for GLContext, etc
 #include "GLDefs.h"                     // for GLuint, LOCAL_GL_TEXTURE_2D, etc
 #include "LayerManagerOGLProgram.h"     // for ShaderProgramOGL, etc
 #include "Units.h"                      // for ScreenPoint
 #include "gfxContext.h"                 // for gfxContext
 #include "gfxPoint.h"                   // for gfxIntSize
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE, MOZ_FINAL
--- a/gfx/layers/opengl/ContainerLayerOGL.cpp
+++ b/gfx/layers/opengl/ContainerLayerOGL.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ContainerLayerOGL.h"
 #include <stdint.h>                     // for uint32_t
 #include <algorithm>                    // for min
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "GLContext.h"
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxMatrix.h"                  // for gfxMatrix
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "mozilla/layers/CompositorTypes.h"  // for MaskType, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "LayerManagerOGL.h"
 #include <stddef.h>                     // for size_t
 #include <stdint.h>                     // for uint32_t, uint8_t, etc
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "CanvasLayerOGL.h"             // for CanvasLayerOGL
 #include "ColorLayerOGL.h"              // for ColorLayerOGL
 #include "Composer2D.h"                 // for Composer2D
 #include "ContainerLayerOGL.h"          // for ContainerLayerOGL
 #include "FPSCounter.h"                 // for FPSState, FPSCounter
 #include "GLContext.h"                  // for GLContext, etc
 #include "GLContextProvider.h"          // for GLContextProvider
 #include "GeckoProfiler.h"              // for PROFILER_LABEL
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -635,21 +635,18 @@ SurfaceStreamHostOGL::UpdateImpl(const S
 
   // Bug 894405
   //
   // The SurfaceStream's GLContext was refed before being passed up to us, so
   // we need to ensure it gets unrefed when we are finished.
   const SurfaceStreamDescriptor& streamDesc =
       aImage.get_SurfaceStreamDescriptor();
 
-  SurfaceStream *stream = SurfaceStream::FromHandle(streamDesc.handle());
-  if (stream == mStream) {
-    return;
-  }
-  mStream = stream;
+
+  mStream = SurfaceStream::FromHandle(streamDesc.handle());
   MOZ_ASSERT(mStream);
   mStreamGL = dont_AddRef(mStream->GLContext());
 }
 
 void
 SurfaceStreamHostOGL::Unlock()
 {
   // We don't know what this is unless we're locked
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ThebesLayerOGL.h"
 #include <stdint.h>                     // for uint32_t
 #include <sys/types.h>                  // for int32_t
-#include "mozilla-config.h"             // for MOZ_DUMP_PAINTING
 #include "GLContext.h"                  // for GLContext, etc
 #include "GLContextTypes.h"             // for GLenum
 #include "GLDefs.h"                     // for LOCAL_GL_ONE, LOCAL_GL_BGRA, etc
 #include "GLTextureImage.h"             // for TextureImage, etc
 #include "ThebesLayerBuffer.h"          // for ThebesLayerBuffer, etc
 #include "gfx3DMatrix.h"                // for gfx3DMatrix
 #include "gfxASurface.h"                // for gfxASurface, etc
 #include "gfxColor.h"                   // for gfxRGBA
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -285,11 +285,17 @@ ExposeGCThingToActiveJS(void *thing, JSG
 
 static JS_ALWAYS_INLINE void
 ExposeValueToActiveJS(const Value &v)
 {
     if (v.isMarkable())
         ExposeGCThingToActiveJS(v.toGCThing(), v.gcKind());
 }
 
+static JS_ALWAYS_INLINE void
+ExposeObjectToActiveJS(JSObject *obj)
+{
+    ExposeGCThingToActiveJS(obj, JSTRACE_OBJECT);
+}
+
 } /* namespace JS */
 
 #endif /* js_GCAPI_h */
--- a/js/xpconnect/idl/xpcexception.idl
+++ b/js/xpconnect/idl/xpcexception.idl
@@ -2,38 +2,27 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIException.idl"
 
-%{ C++
-#include "js/TypeDecls.h"
-%}
-
-[ptr] native xpcexJSContextPtr(JSContext);
-      native xpcexJSVal(JS::Value);
-
-[scriptable, uuid(cac29630-7bf2-4e22-811b-46855a7d5af0)]
+[scriptable, uuid(ce83229c-0a82-4ba4-937b-7fd4cd45f34b)]
 interface nsIXPCException : nsIException
 {
     // inherits methods from nsIException
 
     void initialize(in string           aMessage,
                     in nsresult         aResult,
                     in string           aName,
                     in nsIStackFrame    aLocation,
                     in nsISupports      aData,
                     in nsIException     aInner);
-
-    [noscript] xpcexJSVal stealJSVal();
-    [noscript] void stowJSVal(in xpcexJSContextPtr cx,
-                              in xpcexJSVal val);
 };
 
 /* this goes into the C++ header verbatim. */
 %{ C++
 /********************************************************/
 // {5632BF70-51EC-11d3-9896-006008962422}
 #define NS_XPCEXCEPTION_CID  \
 { 0x5632bf70, 0x51ec, 0x11d3, \
--- a/js/xpconnect/public/SandboxPrivate.h
+++ b/js/xpconnect/public/SandboxPrivate.h
@@ -1,23 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __SANDBOXPRIVATE_H__
 #define __SANDBOXPRIVATE_H__
 
 #include "nsIGlobalObject.h"
+#include "nsIScriptObjectPrincipal.h"
 #include "nsIPrincipal.h"
 #include "nsWeakReference.h"
 
 // This interface is public only because it is used in jsd.
 // Once jsd is gone this file should be moved back to xpconnect/src.
 
 class SandboxPrivate : public nsIGlobalObject,
+                       public nsIScriptObjectPrincipal,
                        public nsSupportsWeakReference
 {
 public:
     SandboxPrivate(nsIPrincipal *principal, JSObject *global)
         : mPrincipal(principal)
         , mGlobalJSObject(global)
     {
     }
--- a/js/xpconnect/src/BackstagePass.h
+++ b/js/xpconnect/src/BackstagePass.h
@@ -4,18 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef BackstagePass_h__
 #define BackstagePass_h__
 
 #include "nsISupports.h"
 #include "nsWeakReference.h"
 #include "nsIGlobalObject.h"
+#include "nsIScriptObjectPrincipal.h"
 
 class BackstagePass : public nsIGlobalObject,
+                      public nsIScriptObjectPrincipal,
                       public nsIXPCScriptable,
                       public nsIClassInfo,
                       public nsSupportsWeakReference
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIXPCSCRIPTABLE
   NS_DECL_NSICLASSINFO
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -34,21 +34,24 @@
 #include "mozilla/Attributes.h"
 #include "nsIScriptContext.h"
 #include "nsJSEnvironment.h"
 #include "nsXMLHttpRequest.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 #include "nsDOMClassInfoID.h"
 #include "nsGlobalWindow.h"
+#include "mozilla/dom/DOMException.h"
+#include "mozilla/dom/DOMExceptionBinding.h"
 
 using namespace mozilla;
 using namespace JS;
 using namespace js;
 using namespace xpc;
+using mozilla::dom::Exception;
 
 /***************************************************************************/
 // stuff used by all
 
 nsresult
 xpc::ThrowAndFail(nsresult errNum, JSContext *cx, bool *retval)
 {
     XPCThrower::Throw(errNum, cx);
@@ -1940,32 +1943,30 @@ nsXPCComponents_Exception::CallOrConstru
                                            JSContext *cx, HandleObject obj,
                                            const CallArgs &args, bool *_retval)
 {
     nsXPConnect* xpc = nsXPConnect::XPConnect();
 
     // Do the security check if necessary
 
     nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
-    if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCException::GetCID()))) {
+    if (sm && NS_FAILED(sm->CanCreateInstance(cx, Exception::GetCID()))) {
         // the security manager vetoed. It should have set an exception.
         *_retval = false;
         return NS_OK;
     }
 
     // Parse the arguments to the Exception constructor.
     ExceptionArgParser parser(cx, xpc);
     if (!parser.parse(args))
         return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
-    nsCOMPtr<nsIException> e;
-    nsXPCException::NewException(parser.eMsg, parser.eResult, parser.eStack,
-                                 parser.eData, getter_AddRefs(e));
-    if (!e)
-        return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
+    nsCOMPtr<nsIException> e = new Exception(parser.eMsg, parser.eResult,
+                                             nullptr, parser.eStack,
+                                             parser.eData);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     RootedObject newObj(cx);
 
     if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
                                   getter_AddRefs(holder))) || !holder ||
         // Assign, not compare
         !(newObj = holder->GetJSObject())) {
@@ -1978,19 +1979,24 @@ nsXPCComponents_Exception::CallOrConstru
 
 /* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
 NS_IMETHODIMP
 nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper,
                                        JSContext * cx, JSObject * obj,
                                        const jsval &val, bool *bp,
                                        bool *_retval)
 {
+    using namespace mozilla::dom;
+
     RootedValue v(cx, val);
-    if (bp)
-        *bp = JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException));
+    if (bp) {
+        Exception* e;
+        *bp = NS_SUCCEEDED(UNWRAP_OBJECT(Exception, cx, v.toObjectOrNull(), e)) ||
+              JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException));
+    }
     return NS_OK;
 }
 
 /***************************************************************************/
 // This class is for the thing returned by "new Component.Constructor".
 
 // XXXjband we use this CID for security check, but security system can't see
 // it since it has no registed factory. Security really kicks in when we try
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -22,16 +22,17 @@
 #include "nsWrapperCacheInlines.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jsprf.h"
 #include "JavaScriptParent.h"
 
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 
 using namespace xpc;
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace JS;
 
 //#define STRICT_CHECK_OF_UNICODE
@@ -1075,27 +1076,27 @@ XPCConvert::ConstructException(nsresult 
         }
     }
     if (!msg)
         if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &msg) || ! msg)
             msg = "<error>";
     if (ifaceName && methodName)
         msg = sz = JS_smprintf(format, msg, ifaceName, methodName);
 
-    nsresult res = nsXPCException::NewException(msg, rv, nullptr, data, exceptn);
+    nsRefPtr<Exception> e = new Exception(msg, rv, nullptr, nullptr, data);
 
-    if (NS_SUCCEEDED(res) && cx && jsExceptionPtr && *exceptn) {
-        nsCOMPtr<nsIXPCException> xpcEx = do_QueryInterface(*exceptn);
-        if (xpcEx)
-            xpcEx->StowJSVal(cx, *jsExceptionPtr);
+    if (cx && jsExceptionPtr) {
+        e->StowJSVal(*jsExceptionPtr);
     }
 
+    e.forget(exceptn);
+
     if (sz)
         JS_smprintf_free(sz);
-    return res;
+    return NS_OK;
 }
 
 /********************************/
 
 class MOZ_STACK_CLASS AutoExceptionRestorer
 {
 public:
     AutoExceptionRestorer(JSContext *cx, Value v)
--- a/js/xpconnect/src/XPCException.cpp
+++ b/js/xpconnect/src/XPCException.cpp
@@ -2,19 +2,17 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* An implementaion of nsIException. */
 
 #include "xpcprivate.h"
-#include "jsprf.h"
 #include "nsError.h"
-#include "nsIUnicodeDecoder.h"
 
 /***************************************************************************/
 /* Quick and dirty mapping of well known result codes to strings. We only
 *  call this when building an exception object, so iterating the short array
 *  is not too bad.
 *
 *  It sure would be nice to have exceptions declared in idl and available
 *  in some more global way at runtime.
@@ -75,370 +73,8 @@ nsXPCException::IterateNSResults(nsresul
 }
 
 // static
 uint32_t
 nsXPCException::GetNSResultCount()
 {
     return RESULT_COUNT;
 }
-
-/***************************************************************************/
-
-NS_IMPL_CLASSINFO(nsXPCException, NULL, nsIClassInfo::DOM_OBJECT,
-                  NS_XPCEXCEPTION_CID)
-NS_INTERFACE_MAP_BEGIN(nsXPCException)
-  NS_INTERFACE_MAP_ENTRY(nsIException)
-  NS_INTERFACE_MAP_ENTRY(nsIXPCException)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
-  NS_IMPL_QUERY_CLASSINFO(nsXPCException)
-NS_INTERFACE_MAP_END_THREADSAFE
-
-NS_IMPL_ADDREF(nsXPCException)
-NS_IMPL_RELEASE(nsXPCException)
-
-NS_IMPL_CI_INTERFACE_GETTER1(nsXPCException, nsIXPCException)
-
-nsXPCException::nsXPCException()
-    : mMessage(nullptr),
-      mResult(NS_OK),
-      mName(nullptr),
-      mLocation(nullptr),
-      mData(nullptr),
-      mFilename(nullptr),
-      mLineNumber(0),
-      mInner(nullptr),
-      mInitialized(false)
-{
-    MOZ_COUNT_CTOR(nsXPCException);
-}
-
-nsXPCException::~nsXPCException()
-{
-    MOZ_COUNT_DTOR(nsXPCException);
-    Reset();
-}
-
-/* [noscript] xpcexJSVal stealJSVal (); */
-NS_IMETHODIMP
-nsXPCException::StealJSVal(jsval *vp)
-{
-    if (mThrownJSVal.IsHeld()) {
-        *vp = mThrownJSVal.Release();
-        return NS_OK;
-    }
-    return NS_ERROR_FAILURE;
-}
-
-/* [noscript] void stowJSVal (in xpcexJSContextPtr cx, in xpcexJSVal val); */
-NS_IMETHODIMP
-nsXPCException::StowJSVal(JSContext* cx, jsval v)
-{
-    if (mThrownJSVal.Hold(cx)) {
-        mThrownJSVal = v;
-        return NS_OK;
-    }
-    return NS_ERROR_FAILURE;
-}
-
-void
-nsXPCException::Reset()
-{
-    if (mMessage) {
-        nsMemory::Free(mMessage);
-        mMessage = nullptr;
-    }
-    if (mName) {
-        nsMemory::Free(mName);
-        mName = nullptr;
-    }
-    if (mFilename) {
-        nsMemory::Free(mFilename);
-        mFilename = nullptr;
-    }
-    mLineNumber = (uint32_t)-1;
-    NS_IF_RELEASE(mLocation);
-    NS_IF_RELEASE(mData);
-    NS_IF_RELEASE(mInner);
-}
-
-/* readonly attribute string message; */
-NS_IMETHODIMP
-nsXPCException::GetMessageMoz(char * *aMessage)
-{
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    XPC_STRING_GETTER_BODY(aMessage, mMessage);
-}
-
-/* readonly attribute nsresult result; */
-NS_IMETHODIMP
-nsXPCException::GetResult(nsresult *aResult)
-{
-    if (!aResult)
-        return NS_ERROR_NULL_POINTER;
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    *aResult = mResult;
-    return NS_OK;
-}
-
-/* readonly attribute string name; */
-NS_IMETHODIMP
-nsXPCException::GetName(char * *aName)
-{
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-
-    const char* name = mName;
-    if (!name)
-        NameAndFormatForNSResult(mResult, &name, nullptr);
-
-    XPC_STRING_GETTER_BODY(aName, name);
-}
-
-/* readonly attribute string filename; */
-NS_IMETHODIMP nsXPCException::GetFilename(char * *aFilename)
-{
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    XPC_STRING_GETTER_BODY(aFilename, mFilename);
-}
-
-/* readonly attribute uint32_t lineNumber; */
-NS_IMETHODIMP nsXPCException::GetLineNumber(uint32_t *aLineNumber)
-{
-    if (!aLineNumber)
-        return NS_ERROR_NULL_POINTER;
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    *aLineNumber = mLineNumber;
-    return NS_OK;
-}
-
-/* readonly attribute uint32_t columnNumber; */
-NS_IMETHODIMP nsXPCException::GetColumnNumber(uint32_t *aColumnNumber)
-{
-    NS_ENSURE_ARG_POINTER(aColumnNumber);
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    *aColumnNumber = 0;
-    return NS_OK;
-}
-
-/* readonly attribute nsIStackFrame location; */
-NS_IMETHODIMP
-nsXPCException::GetLocation(nsIStackFrame * *aLocation)
-{
-    if (!aLocation)
-        return NS_ERROR_NULL_POINTER;
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    *aLocation = mLocation;
-    NS_IF_ADDREF(mLocation);
-    return NS_OK;
-}
-
-/* readonly attribute nsISupports data; */
-NS_IMETHODIMP
-nsXPCException::GetData(nsISupports * *aData)
-{
-    if (!aData)
-        return NS_ERROR_NULL_POINTER;
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    *aData = mData;
-    NS_IF_ADDREF(mData);
-    return NS_OK;
-}
-
-/* readonly attribute nsIException inner; */
-NS_IMETHODIMP
-nsXPCException::GetInner(nsIException* *aException)
-{
-    if (!aException)
-        return NS_ERROR_NULL_POINTER;
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-    *aException = mInner;
-    NS_IF_ADDREF(mInner);
-    return NS_OK;
-}
-
-/* void initialize (in string aMessage, in nsresult aResult, in string aName, in nsIStackFrame aLocation, in nsISupports aData, in nsIException aInner); */
-NS_IMETHODIMP
-nsXPCException::Initialize(const char *aMessage, nsresult aResult, const char *aName, nsIStackFrame *aLocation, nsISupports *aData, nsIException *aInner)
-{
-    if (mInitialized)
-        return NS_ERROR_ALREADY_INITIALIZED;
-
-    Reset();
-
-    if (aMessage) {
-        if (!(mMessage = (char*) nsMemory::Clone(aMessage,
-                                                 sizeof(char)*(strlen(aMessage)+1))))
-            return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    if (aName) {
-        if (!(mName = (char*) nsMemory::Clone(aName,
-                                              sizeof(char)*(strlen(aName)+1))))
-            return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    mResult = aResult;
-
-    if (aLocation) {
-        mLocation = aLocation;
-        NS_ADDREF(mLocation);
-        // For now, fill in our location details from our stack frame.
-        // Later we may allow other locations?
-        nsresult rc;
-        if (NS_FAILED(rc = aLocation->GetFilename(&mFilename)))
-            return rc;
-        if (NS_FAILED(rc = aLocation->GetLineNumber(&mLineNumber)))
-            return rc;
-    } else {
-        nsresult rv;
-        nsXPConnect* xpc = nsXPConnect::XPConnect();
-        rv = xpc->GetCurrentJSStack(&mLocation);
-        if (NS_FAILED(rv))
-            return rv;
-    }
-
-    if (aData) {
-        mData = aData;
-        NS_ADDREF(mData);
-    }
-    if (aInner) {
-        mInner = aInner;
-        NS_ADDREF(mInner);
-    }
-
-    mInitialized = true;
-    return NS_OK;
-}
-
-/* string toString (); */
-NS_IMETHODIMP
-nsXPCException::ToString(char **_retval)
-{
-    if (!_retval)
-        return NS_ERROR_NULL_POINTER;
-    if (!mInitialized)
-        return NS_ERROR_NOT_INITIALIZED;
-
-    static const char defaultMsg[] = "<no message>";
-    static const char defaultLocation[] = "<unknown>";
-    static const char format[] =
- "[Exception... \"%s\"  nsresult: \"0x%x (%s)\"  location: \"%s\"  data: %s]";
-
-    char* indicatedLocation = nullptr;
-
-    if (mLocation) {
-        // we need to free this if it does not fail
-        nsresult rv = mLocation->ToString(&indicatedLocation);
-        if (NS_FAILED(rv))
-            return rv;
-    }
-
-    const char* msg = mMessage ? mMessage : nullptr;
-    const char* location = indicatedLocation ?
-                                indicatedLocation : defaultLocation;
-    const char* resultName = mName;
-    if (!resultName && !NameAndFormatForNSResult(mResult, &resultName,
-                                                 (!msg) ? &msg : nullptr)) {
-        if (!msg)
-            msg = defaultMsg;
-        resultName = "<unknown>";
-    }
-    const char* data = mData ? "yes" : "no";
-
-    char* temp = JS_smprintf(format, msg, mResult, resultName, location, data);
-    if (indicatedLocation)
-        nsMemory::Free(indicatedLocation);
-
-    char* final = nullptr;
-    if (temp) {
-        final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1));
-        JS_smprintf_free(temp);
-    }
-
-    *_retval = final;
-    return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-bool nsXPCException::sEverMadeOneFromFactory = false;
-
-// static
-nsresult
-nsXPCException::NewException(const char *aMessage,
-                             nsresult aResult,
-                             nsIStackFrame *aLocation,
-                             nsISupports *aData,
-                             nsIException** exceptn)
-{
-    // A little hack... The nsIGenericModule nsIClassInfo scheme relies on there
-    // having been at least one instance made via the factory. Otherwise, the
-    // shared factory/classinsance object never gets created and our QI getter
-    // for our instance's pointer to our nsIClassInfo will always return null.
-    // This is bad because it means that wrapped exceptions will never have a
-    // shared prototype. So... We force one to be created via the factory
-    // *once* and then go about our business.
-    if (!sEverMadeOneFromFactory) {
-        nsCOMPtr<nsIXPCException> e =
-            do_CreateInstance(XPC_EXCEPTION_CONTRACTID);
-        sEverMadeOneFromFactory = true;
-    }
-
-    nsresult rv;
-    nsXPCException* e = new nsXPCException();
-    if (e) {
-        NS_ADDREF(e);
-
-        nsIStackFrame* location;
-        if (aLocation) {
-            location = aLocation;
-            NS_ADDREF(location);
-        } else {
-            nsXPConnect* xpc = nsXPConnect::XPConnect();
-            rv = xpc->GetCurrentJSStack(&location);
-            if (NS_FAILED(rv)) {
-                NS_RELEASE(e);
-                return NS_ERROR_FAILURE;
-            }
-            // it is legal for there to be no active JS stack, if C++ code
-            // is operating on a JS-implemented interface pointer without
-            // having been called in turn by JS.  This happens in the JS
-            // component loader, and will become more common as additional
-            // components are implemented in JS.
-        }
-        // We want to trim off any leading native 'dataless' frames
-        if (location)
-            while (1) {
-                uint32_t language;
-                int32_t lineNumber;
-                if (NS_FAILED(location->GetLanguage(&language)) ||
-                    language == nsIProgrammingLanguage::JAVASCRIPT ||
-                    NS_FAILED(location->GetLineNumber(&lineNumber)) ||
-                    lineNumber) {
-                    break;
-                }
-                nsCOMPtr<nsIStackFrame> caller;
-                if (NS_FAILED(location->GetCaller(getter_AddRefs(caller))) || !caller)
-                    break;
-                NS_RELEASE(location);
-                caller->QueryInterface(NS_GET_IID(nsIStackFrame), (void **)&location);
-            }
-        // at this point we have non-null location with one extra addref,
-        // or no location at all
-        rv = e->Initialize(aMessage, aResult, nullptr, location, aData, nullptr);
-        NS_IF_RELEASE(location);
-        if (NS_FAILED(rv))
-            NS_RELEASE(e);
-    }
-
-    if (!e)
-        return NS_ERROR_FAILURE;
-
-    *exceptn = static_cast<nsIXPCException*>(e);
-    return NS_OK;
-}
--- a/js/xpconnect/src/XPCForwards.h
+++ b/js/xpconnect/src/XPCForwards.h
@@ -12,17 +12,16 @@
 // forward declarations of interally used classes...
 
 class nsXPConnect;
 class XPCJSRuntime;
 class XPCContext;
 class XPCCallContext;
 
 class XPCJSThrower;
-class XPCJSStack;
 
 class nsXPCWrappedJS;
 class nsXPCWrappedJSClass;
 
 class XPCNativeMember;
 class XPCNativeInterface;
 class XPCNativeSet;
 
--- a/js/xpconnect/src/XPCInlines.h
+++ b/js/xpconnect/src/XPCInlines.h
@@ -483,17 +483,19 @@ JSObject* XPCWrappedNativeTearOff::GetJS
 {
     return reinterpret_cast<JSObject *>(reinterpret_cast<uintptr_t>(mJSObject) & ~1);
 }
 
 inline
 JSObject* XPCWrappedNativeTearOff::GetJSObject()
 {
     JSObject *obj = GetJSObjectPreserveColor();
-    xpc_UnmarkGrayObject(obj);
+    if (obj) {
+      JS::ExposeObjectToActiveJS(obj);
+    }
     return obj;
 }
 
 inline
 void XPCWrappedNativeTearOff::SetJSObject(JSObject*  JSObj)
 {
     MOZ_ASSERT(!IsMarked());
     mJSObject = JSObj;
--- a/js/xpconnect/src/XPCJSContextStack.cpp
+++ b/js/xpconnect/src/XPCJSContextStack.cpp
@@ -166,18 +166,18 @@ XPCJSContextStack::GetSafeJSContext()
         MOZ_CRASH();
 
     // Make sure the context is associated with a proper compartment
     // and not the default compartment.
     js::SetDefaultObjectForContext(mSafeJSContext, glob);
 
     // Note: make sure to set the private before calling
     // InitClasses
-    nsCOMPtr<nsIScriptObjectPrincipal> sop = new SandboxPrivate(principal, glob);
-    JS_SetPrivate(glob, sop.forget().get());
+    nsRefPtr<SandboxPrivate> sp = new SandboxPrivate(principal, glob);
+    JS_SetPrivate(glob, sp.forget().get());
 
     // After this point either glob is null and the
     // nsIScriptObjectPrincipal ownership is either handled by the
     // nsCOMPtr or dealt with, or we'll release in the finalize
     // hook.
     if (NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
         MOZ_CRASH();
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1388,16 +1388,20 @@ void XPCJSRuntime::SystemIsBeingShutDown
 
     if (mDetachedWrappedNativeProtoMap)
         mDetachedWrappedNativeProtoMap->
             Enumerate(DetachedWrappedNativeProtoShutdownMarker, nullptr);
 }
 
 XPCJSRuntime::~XPCJSRuntime()
 {
+    // Clear any pending exception.  It might be an XPCWrappedJS, and if we try
+    // to destroy it later we will crash.
+    SetPendingException(nullptr);
+
     JS::SetGCSliceCallback(Runtime(), mPrevGCSliceCallback);
 
     xpc_DelocalizeRuntime(Runtime());
 
     if (mWatchdogManager->GetWatchdog())
         mWatchdogManager->StopWatchdog();
 
     if (mCallContext)
@@ -2893,18 +2897,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
    mWrappedJSToReleaseArray(),
    mNativesToReleaseArray(),
    mDoingFinalization(false),
    mVariantRoots(nullptr),
    mWrappedJSRoots(nullptr),
    mObjectHolderRoots(nullptr),
    mWatchdogManager(new WatchdogManager(this)),
    mJunkScope(nullptr),
-   mAsyncSnowWhiteFreer(new AsyncFreeSnowWhite()),
-   mExceptionManagerNotAvailable(false)
+   mAsyncSnowWhiteFreer(new AsyncFreeSnowWhite())
 {
 #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
     DEBUG_WrappedNativeHashtable =
         PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
                          sizeof(PLDHashEntryStub), 128);
 #endif
 
     DOM_InitInterfaces();
--- a/js/xpconnect/src/XPCModule.cpp
+++ b/js/xpconnect/src/XPCModule.cpp
@@ -6,17 +6,16 @@
 
 #define XPCONNECT_MODULE
 #include "xpcprivate.h"
 
 nsresult
 xpcModuleCtor()
 {
     nsXPConnect::InitStatics();
-    nsXPCException::InitStatics();
     XPCWrappedNativeScope::InitStatics();
 
     return NS_OK;
 }
 
 void
 xpcModuleDtor()
 {
--- a/js/xpconnect/src/XPCModule.h
+++ b/js/xpconnect/src/XPCModule.h
@@ -16,17 +16,16 @@
 // {FE4F7592-C1FC-4662-AC83-538841318803}
 #define SCRIPTABLE_INTERFACES_CID                                             \
     {0xfe4f7592, 0xc1fc, 0x4662,                                              \
       { 0xac, 0x83, 0x53, 0x88, 0x41, 0x31, 0x88, 0x3 } }
 
 #define MOZJSSUBSCRIPTLOADER_CONTRACTID "@mozilla.org/moz/jssubscript-loader;1"
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSID)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCException)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIXPConnect,
                                          nsXPConnect::GetSingleton)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptError)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(mozJSComponentLoader)
 NS_GENERIC_FACTORY_CONSTRUCTOR(mozJSSubScriptLoader)
 
 NS_DEFINE_NAMED_CID(NS_JS_ID_CID);
@@ -34,27 +33,25 @@ NS_DEFINE_NAMED_CID(NS_XPCONNECT_CID);
 NS_DEFINE_NAMED_CID(NS_XPCEXCEPTION_CID);
 NS_DEFINE_NAMED_CID(NS_SCRIPTERROR_CID);
 NS_DEFINE_NAMED_CID(MOZJSCOMPONENTLOADER_CID);
 NS_DEFINE_NAMED_CID(MOZ_JSSUBSCRIPTLOADER_CID);
 
 #define XPCONNECT_CIDENTRIES                                                  \
   { &kNS_JS_ID_CID, false, NULL,  nsJSIDConstructor },                        \
   { &kNS_XPCONNECT_CID, false, NULL,  nsIXPConnectConstructor },              \
-  { &kNS_XPCEXCEPTION_CID, false, NULL, nsXPCExceptionConstructor },          \
   { &kNS_SCRIPTERROR_CID, false, NULL, nsScriptErrorConstructor },            \
   { &kMOZJSCOMPONENTLOADER_CID, false, NULL, mozJSComponentLoaderConstructor },\
   { &kMOZ_JSSUBSCRIPTLOADER_CID, false, NULL, mozJSSubScriptLoaderConstructor },
 
 #define XPCONNECT_CONTRACTS                                                   \
   { XPC_ID_CONTRACTID, &kNS_JS_ID_CID },                                      \
   { XPC_XPCONNECT_CONTRACTID, &kNS_XPCONNECT_CID },                           \
   { XPC_CONTEXT_STACK_CONTRACTID, &kNS_XPCONNECT_CID },                       \
   { XPC_RUNTIME_CONTRACTID, &kNS_XPCONNECT_CID },                             \
-  { XPC_EXCEPTION_CONTRACTID, &kNS_XPCEXCEPTION_CID },                        \
   { NS_SCRIPTERROR_CONTRACTID, &kNS_SCRIPTERROR_CID },                        \
   { MOZJSCOMPONENTLOADER_CONTRACTID, &kMOZJSCOMPONENTLOADER_CID },            \
   { MOZJSSUBSCRIPTLOADER_CONTRACTID, &kMOZ_JSSUBSCRIPTLOADER_CID },
 
 #define XPCONNECT_CATEGORIES \
   { "module-loader", "js", MOZJSCOMPONENTLOADER_CONTRACTID },
 
 nsresult xpcModuleCtor();
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -8,16 +8,17 @@
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jsprf.h"
 #include "nsCOMPtr.h"
 #include "xpcprivate.h"
 #include "XPCInlines.h"
 #include "XPCQuickStubs.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/Exceptions.h"
 
 using namespace mozilla;
 using namespace JS;
 
 extern const char* xpc_qsStringTable;
 
 static const xpc_qsHashEntry *
 LookupEntry(uint32_t tableSize, const xpc_qsHashEntry *table, const nsID &iid)
@@ -245,17 +246,17 @@ ThrowCallFailed(JSContext *cx, nsresult 
         && name) {
         sz = JS_smprintf("%s 0x%x (%s) [%s.%s]",
                          format, rv, name, ifaceName, memberName);
     } else {
         sz = JS_smprintf("%s 0x%x [%s.%s]",
                          format, rv, ifaceName, memberName);
     }
 
-    XPCThrower::BuildAndThrowException(cx, rv, sz);
+    dom::Throw(cx, rv, sz);
 
     if (sz)
         JS_smprintf_free(sz);
 
     return false;
 }
 
 bool
@@ -331,17 +332,17 @@ ThrowBadArg(JSContext *cx, nsresult rv, 
     if (!memberName) {
         memberName = JSID_IS_STRING(memberId)
                      ? memberNameBytes.encodeLatin1(cx, JSID_TO_STRING(memberId))
                      : "unknown";
     }
     sz = JS_smprintf("%s arg %u [%s.%s]",
                      format, (unsigned int) paramnum, ifaceName, memberName);
 
-    XPCThrower::BuildAndThrowException(cx, rv, sz);
+    dom::Throw(cx, rv, sz);
 
     if (sz)
         JS_smprintf_free(sz);
 }
 
 void
 xpc_qsThrowBadArg(JSContext *cx, nsresult rv, jsval *vp, unsigned paramnum)
 {
deleted file mode 100644
--- a/js/xpconnect/src/XPCStack.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Implements nsIStackFrame. */
-
-#include "xpcprivate.h"
-#include "jsprf.h"
-#include "js/OldDebugAPI.h"
-
-class XPCJSStackFrame : public nsIStackFrame
-{
-public:
-    NS_DECL_THREADSAFE_ISUPPORTS
-    NS_DECL_NSISTACKFRAME
-
-    static nsresult CreateStack(JSContext* cx, XPCJSStackFrame** stack);
-
-    static nsresult CreateStackFrameLocation(uint32_t aLanguage,
-                                             const char* aFilename,
-                                             const char* aFunctionName,
-                                             int32_t aLineNumber,
-                                             nsIStackFrame* aCaller,
-                                             XPCJSStackFrame** stack);
-
-    XPCJSStackFrame();
-    virtual ~XPCJSStackFrame();
-
-    bool IsJSFrame() const
-        {return mLanguage == nsIProgrammingLanguage::JAVASCRIPT;}
-
-private:
-    nsCOMPtr<nsIStackFrame> mCaller;
-
-    char* mFilename;
-    char* mFunname;
-    int32_t mLineno;
-    uint32_t mLanguage;
-};
-
-/**********************************************/
-
-// static
-
-nsresult
-XPCJSStack::CreateStack(JSContext* cx, nsIStackFrame** stack)
-{
-    if (!cx)
-        return NS_ERROR_FAILURE;
-
-    return XPCJSStackFrame::CreateStack(cx, (XPCJSStackFrame**) stack);
-}
-
-// static
-nsresult
-XPCJSStack::CreateStackFrameLocation(uint32_t aLanguage,
-                                     const char* aFilename,
-                                     const char* aFunctionName,
-                                     int32_t aLineNumber,
-                                     nsIStackFrame* aCaller,
-                                     nsIStackFrame** stack)
-{
-    return XPCJSStackFrame::CreateStackFrameLocation(aLanguage,
-                                                     aFilename,
-                                                     aFunctionName,
-                                                     aLineNumber,
-                                                     aCaller,
-                                                     (XPCJSStackFrame**) stack);
-}
-
-
-/**********************************************/
-
-XPCJSStackFrame::XPCJSStackFrame()
-    :   mFilename(nullptr),
-        mFunname(nullptr),
-        mLineno(0),
-        mLanguage(nsIProgrammingLanguage::UNKNOWN)
-{
-}
-
-XPCJSStackFrame::~XPCJSStackFrame()
-{
-    if (mFilename)
-        nsMemory::Free(mFilename);
-    if (mFunname)
-        nsMemory::Free(mFunname);
-}
-
-NS_IMPL_ISUPPORTS1(XPCJSStackFrame, nsIStackFrame)
-
-nsresult
-XPCJSStackFrame::CreateStack(JSContext* cx, XPCJSStackFrame** stack)
-{
-    static const unsigned MAX_FRAMES = 100;
-
-    nsRefPtr<XPCJSStackFrame> first = new XPCJSStackFrame();
-    nsRefPtr<XPCJSStackFrame> self = first;
-
-    JS::StackDescription* desc = JS::DescribeStack(cx, MAX_FRAMES);
-    if (!desc)
-        return NS_ERROR_FAILURE;
-
-    for (size_t i = 0; i < desc->nframes && self; i++) {
-        self->mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
-
-	JSAutoCompartment ac(cx, desc->frames[i].script);
-        const char* filename = JS_GetScriptFilename(cx, desc->frames[i].script);
-        if (filename) {
-            self->mFilename = (char*)
-                nsMemory::Clone(filename,
-                                sizeof(char)*(strlen(filename)+1));
-        }
-
-        self->mLineno = desc->frames[i].lineno;
-
-        JSFunction* fun = desc->frames[i].fun;
-        if (fun) {
-            JS::RootedString funid(cx, JS_GetFunctionDisplayId(fun));
-            if (funid) {
-                size_t length = JS_GetStringEncodingLength(cx, funid);
-                if (length != size_t(-1)) {
-                    self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
-                    if (self->mFunname) {
-                        JS_EncodeStringToBuffer(cx, funid, self->mFunname, length);
-                        self->mFunname[length] = '\0';
-                    }
-                }
-            }
-        }
-
-        XPCJSStackFrame* frame = new XPCJSStackFrame();
-        self->mCaller = frame;
-        self = frame;
-    }
-
-    JS::FreeStackDescription(cx, desc);
-
-    *stack = first.forget().get();
-    return NS_OK;
-}
-
-// static
-nsresult
-XPCJSStackFrame::CreateStackFrameLocation(uint32_t aLanguage,
-                                          const char* aFilename,
-                                          const char* aFunctionName,
-                                          int32_t aLineNumber,
-                                          nsIStackFrame* aCaller,
-                                          XPCJSStackFrame** stack)
-{
-    bool failed = false;
-    XPCJSStackFrame* self = new XPCJSStackFrame();
-    if (self)
-        NS_ADDREF(self);
-    else
-        failed = true;
-
-    if (!failed) {
-        self->mLanguage = aLanguage;
-        self->mLineno = aLineNumber;
-    }
-
-    if (!failed && aFilename) {
-        self->mFilename = (char*)
-                nsMemory::Clone(aFilename,
-                                sizeof(char)*(strlen(aFilename)+1));
-        if (!self->mFilename)
-            failed = true;
-    }
-
-    if (!failed && aFunctionName) {
-        self->mFunname = (char*)
-                nsMemory::Clone(aFunctionName,
-                                sizeof(char)*(strlen(aFunctionName)+1));
-        if (!self->mFunname)
-            failed = true;
-    }
-
-    if (!failed && aCaller) {
-        self->mCaller = aCaller;
-    }
-
-    if (failed && self) {
-        NS_RELEASE(self);   // sets self to nullptr
-    }
-
-    *stack = self;
-    return self ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-/* readonly attribute uint32_t language; */
-NS_IMETHODIMP XPCJSStackFrame::GetLanguage(uint32_t *aLanguage)
-{
-    *aLanguage = mLanguage;
-    return NS_OK;
-}
-
-/* readonly attribute string languageName; */
-NS_IMETHODIMP XPCJSStackFrame::GetLanguageName(char * *aLanguageName)
-{
-    static const char js[] = "JavaScript";
-    static const char cpp[] = "C++";
-    char* temp;
-
-    if (IsJSFrame())
-        *aLanguageName = temp = (char*) nsMemory::Clone(js, sizeof(js));
-    else
-        *aLanguageName = temp = (char*) nsMemory::Clone(cpp, sizeof(cpp));
-
-    return temp ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-/* readonly attribute string filename; */
-NS_IMETHODIMP XPCJSStackFrame::GetFilename(char * *aFilename)
-{
-    XPC_STRING_GETTER_BODY(aFilename, mFilename);
-}
-
-/* readonly attribute string name; */
-NS_IMETHODIMP XPCJSStackFrame::GetName(char * *aFunction)
-{
-    XPC_STRING_GETTER_BODY(aFunction, mFunname);
-}
-
-/* readonly attribute int32_t lineNumber; */
-NS_IMETHODIMP XPCJSStackFrame::GetLineNumber(int32_t *aLineNumber)
-{
-    *aLineNumber = mLineno;
-    return NS_OK;
-}
-
-/* readonly attribute string sourceLine; */
-NS_IMETHODIMP XPCJSStackFrame::GetSourceLine(char * *aSourceLine)
-{
-    *aSourceLine = nullptr;
-    return NS_OK;
-}
-
-/* readonly attribute nsIStackFrame caller; */
-NS_IMETHODIMP XPCJSStackFrame::GetCaller(nsIStackFrame * *aCaller)
-{
-    NS_IF_ADDREF(*aCaller = mCaller);
-    return NS_OK;
-}
-
-/* string toString (); */
-NS_IMETHODIMP XPCJSStackFrame::ToString(char **_retval)
-{
-    const char* frametype = IsJSFrame() ? "JS" : "native";
-    const char* filename = mFilename ? mFilename : "<unknown filename>";
-    const char* funname = mFunname ? mFunname : "<TOP_LEVEL>";
-    static const char format[] = "%s frame :: %s :: %s :: line %d";
-    int len = sizeof(char)*
-                (strlen(frametype) + strlen(filename) + strlen(funname)) +
-              sizeof(format) + 6 /* space for lineno */;
-
-    char* buf = (char*) nsMemory::Alloc(len);
-    if (!buf)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    JS_snprintf(buf, len, format, frametype, filename, funname, mLineno);
-    *_retval = buf;
-    return NS_OK;
-}
-
--- a/js/xpconnect/src/XPCThrower.cpp
+++ b/js/xpconnect/src/XPCThrower.cpp
@@ -5,29 +5,34 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Code for throwing errors into JavaScript. */
 
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "XPCWrapper.h"
 #include "jsprf.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/Exceptions.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
 
 bool XPCThrower::sVerbose = true;
 
 // static
 void
 XPCThrower::Throw(nsresult rv, JSContext* cx)
 {
     const char* format;
     if (JS_IsExceptionPending(cx))
         return;
     if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
         format = "";
-    BuildAndThrowException(cx, rv, format);
+    dom::Throw(cx, rv, format);
 }
 
 namespace xpc {
 
 bool
 Throw(JSContext *cx, nsresult rv)
 {
     XPCThrower::Throw(rv, cx);
@@ -40,18 +45,17 @@ Throw(JSContext *cx, nsresult rv)
  * If there has already been an exception thrown, see if we're throwing the
  * same sort of exception, and if we are, don't clobber the old one. ccx
  * should be the current call context.
  */
 // static
 bool
 XPCThrower::CheckForPendingException(nsresult result, JSContext *cx)
 {
-    nsCOMPtr<nsIException> e;
-    XPCJSRuntime::Get()->GetPendingException(getter_AddRefs(e));
+    nsCOMPtr<nsIException> e = XPCJSRuntime::Get()->GetPendingException();
     if (!e)
         return false;
     XPCJSRuntime::Get()->SetPendingException(nullptr);
 
     nsresult e_result;
     if (NS_FAILED(e->GetResult(&e_result)) || e_result != result)
         return false;
 
@@ -73,17 +77,17 @@ XPCThrower::Throw(nsresult rv, XPCCallCo
     if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
         format = "";
 
     sz = (char*) format;
 
     if (sz && sVerbose)
         Verbosify(ccx, &sz, false);
 
-    BuildAndThrowException(ccx, rv, sz);
+    dom::Throw(ccx, rv, sz);
 
     if (sz && sz != format)
         JS_smprintf_free(sz);
 }
 
 
 // static
 void
@@ -111,17 +115,17 @@ XPCThrower::ThrowBadResult(nsresult rv, 
     if (nsXPCException::NameAndFormatForNSResult(result, &name, nullptr) && name)
         sz = JS_smprintf("%s 0x%x (%s)", format, result, name);
     else
         sz = JS_smprintf("%s 0x%x", format, result);
 
     if (sz && sVerbose)
         Verbosify(ccx, &sz, true);
 
-    BuildAndThrowException(ccx, result, sz);
+    dom::Throw(ccx, result, sz);
 
     if (sz)
         JS_smprintf_free(sz);
 }
 
 // static
 void
 XPCThrower::ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx)
@@ -132,17 +136,17 @@ XPCThrower::ThrowBadParam(nsresult rv, u
     if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
         format = "";
 
     sz = JS_smprintf("%s arg %d", format, paramNum);
 
     if (sz && sVerbose)
         Verbosify(ccx, &sz, true);
 
-    BuildAndThrowException(ccx, rv, sz);
+    dom::Throw(ccx, rv, sz);
 
     if (sz)
         JS_smprintf_free(sz);
 }
 
 
 // static
 void
@@ -163,102 +167,8 @@ XPCThrower::Verbosify(XPCCallContext& cc
     }
 
     if (sz) {
         if (own)
             JS_smprintf_free(*psz);
         *psz = sz;
     }
 }
-
-// static
-void
-XPCThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz)
-{
-    bool success = false;
-
-    /* no need to set an expection if the security manager already has */
-    if (rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO && JS_IsExceptionPending(cx))
-        return;
-    nsCOMPtr<nsIException> finalException;
-    nsCOMPtr<nsIException> defaultException;
-    nsXPCException::NewException(sz, rv, nullptr, nullptr, getter_AddRefs(defaultException));
-
-    nsIExceptionManager * exceptionManager = XPCJSRuntime::Get()->GetExceptionManager();
-    if (exceptionManager) {
-        // Ask the provider for the exception, if there is no provider
-        // we expect it to set e to null
-        exceptionManager->GetExceptionFromProvider(rv,
-                                                   defaultException,
-                                                   getter_AddRefs(finalException));
-        // We should get at least the defaultException back,
-        // but just in case
-        if (finalException == nullptr) {
-            finalException = defaultException;
-        }
-    }
-
-    // XXX Should we put the following test and call to JS_ReportOutOfMemory
-    // inside this test?
-    if (finalException)
-        success = ThrowExceptionObject(cx, finalException);
-    // If we weren't able to build or throw an exception we're
-    // most likely out of memory
-    if (!success)
-        JS_ReportOutOfMemory(cx);
-}
-
-static bool
-IsCallerChrome(JSContext* cx)
-{
-    nsresult rv;
-
-    nsCOMPtr<nsIScriptSecurityManager> secMan;
-    secMan = XPCWrapper::GetSecurityManager();
-
-    if (!secMan)
-        return false;
-
-    bool isChrome;
-    rv = secMan->SubjectPrincipalIsSystem(&isChrome);
-    return NS_SUCCEEDED(rv) && isChrome;
-}
-
-// static
-bool
-XPCThrower::ThrowExceptionObject(JSContext* cx, nsIException* e)
-{
-    bool success = false;
-    if (e) {
-        nsCOMPtr<nsIXPCException> xpcEx;
-        JS::RootedValue thrown(cx);
-        nsXPConnect* xpc;
-
-        // If we stored the original thrown JS value in the exception
-        // (see XPCConvert::ConstructException) and we are in a web
-        // context (i.e., not chrome), rethrow the original value.
-        if (!IsCallerChrome(cx) &&
-            (xpcEx = do_QueryInterface(e)) &&
-            NS_SUCCEEDED(xpcEx->StealJSVal(thrown.address()))) {
-            if (!JS_WrapValue(cx, thrown.address()))
-                return false;
-            JS_SetPendingException(cx, thrown);
-            success = true;
-        } else if ((xpc = nsXPConnect::XPConnect())) {
-            JS::RootedObject glob(cx, JS::CurrentGlobalOrNull(cx));
-            if (!glob)
-                return false;
-
-            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-            nsresult rv = xpc->WrapNative(cx, glob, e,
-                                          NS_GET_IID(nsIException),
-                                          getter_AddRefs(holder));
-            if (NS_SUCCEEDED(rv) && holder) {
-                JS::RootedObject obj(cx, holder->GetJSObject());
-                if (obj) {
-                    JS_SetPendingException(cx, OBJECT_TO_JSVAL(obj));
-                    success = true;
-                }
-            }
-        }
-    }
-    return success;
-}
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -241,17 +241,18 @@ nsXPCWrappedJS::GetWeakReference(nsIWeak
         return mRoot->GetWeakReference(aInstancePtr);
 
     return nsSupportsWeakReference::GetWeakReference(aInstancePtr);
 }
 
 JSObject*
 nsXPCWrappedJS::GetJSObject()
 {
-    return xpc_UnmarkGrayObject(mJSObj);
+    JS::ExposeObjectToActiveJS(mJSObj);
+    return mJSObj;
 }
 
 static bool
 CheckMainThreadOnly(nsXPCWrappedJS *aWrapper)
 {
     if(aWrapper->IsMainThreadOnly())
         return NS_IsMainThread();
 
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -11,16 +11,19 @@
 #include "jsprf.h"
 #include "nsArrayEnumerator.h"
 #include "nsContentUtils.h"
 #include "nsWrapperCache.h"
 #include "XPCWrapper.h"
 #include "AccessCheck.h"
 #include "nsJSUtils.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/DOMException.h"
+#include "mozilla/dom/DOMExceptionBinding.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 
 using namespace xpc;
 using namespace JS;
 
 NS_IMPL_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
@@ -256,31 +259,24 @@ nsXPCWrappedJSClass::CallQueryInterfaceO
 
             RootedValue jsexception(cx, NullValue());
 
             if (JS_GetPendingException(cx, jsexception.address())) {
                 nsresult rv;
                 if (jsexception.isObject()) {
                     // XPConnect may have constructed an object to represent a
                     // C++ QI failure. See if that is the case.
-                    nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
-
-                    nsXPConnect::XPConnect()->
-                        GetWrappedNativeOfJSObject(cx,
-                                                   &jsexception.toObject(),
-                                                   getter_AddRefs(wrapper));
+                    using namespace mozilla::dom;
+                    Exception *e = nullptr;
+                    UNWRAP_OBJECT(Exception, cx, &jsexception.toObject(), e);
 
-                    if (wrapper) {
-                        nsCOMPtr<nsIException> exception =
-                            do_QueryWrappedNative(wrapper);
-                        if (exception &&
-                            NS_SUCCEEDED(exception->GetResult(&rv)) &&
-                            rv == NS_NOINTERFACE) {
-                            JS_ClearPendingException(cx);
-                        }
+                    if (e &&
+                        NS_SUCCEEDED(e->GetResult(&rv)) &&
+                        rv == NS_NOINTERFACE) {
+                        JS_ClearPendingException(cx);
                     }
                 } else if (JSVAL_IS_NUMBER(jsexception)) {
                     // JS often throws an nsresult.
                     if (JSVAL_IS_DOUBLE(jsexception))
                         // Visual Studio 9 doesn't allow casting directly from
                         // a double to an enumeration type, contrary to
                         // 5.2.9(10) of C++11, so add an intermediate cast.
                         rv = (nsresult)(uint32_t)(JSVAL_TO_DOUBLE(jsexception));
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -286,17 +286,17 @@ XPCWrappedNativeScope::AllowXBLScope()
 namespace xpc {
 JSObject *GetXBLScope(JSContext *cx, JSObject *contentScopeArg)
 {
     JS::RootedObject contentScope(cx, contentScopeArg);
     JSAutoCompartment ac(cx, contentScope);
     JSObject *scope = EnsureCompartmentPrivate(contentScope)->scope->EnsureXBLScope(cx);
     NS_ENSURE_TRUE(scope, nullptr); // See bug 858642.
     scope = js::UncheckedUnwrap(scope);
-    xpc_UnmarkGrayObject(scope);
+    JS::ExposeObjectToActiveJS(scope);
     return scope;
 }
 
 bool AllowXBLScope(JSCompartment *c)
 {
   XPCWrappedNativeScope *scope = EnsureCompartmentPrivate(c)->scope;
   return scope && scope->AllowXBLScope();
 }
--- a/js/xpconnect/src/moz.build
+++ b/js/xpconnect/src/moz.build
@@ -29,17 +29,16 @@ CPP_SOURCES += [
     'XPCJSRuntime.cpp',
     'XPCJSWeakReference.cpp',
     'XPCLocale.cpp',
     'XPCLog.cpp',
     'XPCMaps.cpp',
     'XPCModule.cpp',
     'XPCQuickStubs.cpp',
     'XPCRuntimeService.cpp',
-    'XPCStack.cpp',
     'XPCString.cpp',
     'XPCThrower.cpp',
     'XPCVariant.cpp',
     'XPCWrappedJS.cpp',
     'XPCWrappedJSClass.cpp',
     'XPCWrappedNative.cpp',
     'XPCWrappedNativeInfo.cpp',
     'XPCWrappedNativeJSOps.cpp',
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -31,16 +31,17 @@
 
 #ifdef MOZ_JSDEBUGGER
 #include "jsdIDebuggerService.h"
 #endif
 
 #include "XPCQuickStubs.h"
 
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/IDBIndexBinding.h"
 #include "mozilla/dom/IDBObjectStoreBinding.h"
 #include "mozilla/dom/IDBOpenDBRequestBinding.h"
 #include "mozilla/dom/IDBRequestBinding.h"
 #include "mozilla/dom/IDBTransactionBinding.h"
 #include "mozilla/dom/IDBVersionChangeEventBinding.h"
 #include "mozilla/dom/TextDecoderBinding.h"
 #include "mozilla/dom/TextEncoderBinding.h"
@@ -858,49 +859,35 @@ nsXPConnect::CreateStackFrameLocation(ui
                                       const char *aFilename,
                                       const char *aFunctionName,
                                       int32_t aLineNumber,
                                       nsIStackFrame *aCaller,
                                       nsIStackFrame **_retval)
 {
     MOZ_ASSERT(_retval, "bad param");
 
-    return XPCJSStack::CreateStackFrameLocation(aLanguage,
-                                                aFilename,
-                                                aFunctionName,
-                                                aLineNumber,
-                                                aCaller,
-                                                _retval);
+    nsCOMPtr<nsIStackFrame> stackFrame =
+        exceptions::CreateStackFrameLocation(aLanguage,
+                                             aFilename,
+                                             aFunctionName,
+                                             aLineNumber,
+                                             aCaller);
+    stackFrame.forget(_retval);
+    return NS_OK;
 }
 
 /* readonly attribute nsIStackFrame CurrentJSStack; */
 NS_IMETHODIMP
 nsXPConnect::GetCurrentJSStack(nsIStackFrame * *aCurrentJSStack)
 {
     MOZ_ASSERT(aCurrentJSStack, "bad param");
-    *aCurrentJSStack = nullptr;
 
-    // is there a current context available?
-    if (JSContext *cx = GetCurrentJSContext()) {
-        nsCOMPtr<nsIStackFrame> stack;
-        XPCJSStack::CreateStack(cx, getter_AddRefs(stack));
-        if (stack) {
-            // peel off native frames...
-            uint32_t language;
-            nsCOMPtr<nsIStackFrame> caller;
-            while (stack &&
-                   NS_SUCCEEDED(stack->GetLanguage(&language)) &&
-                   language != nsIProgrammingLanguage::JAVASCRIPT &&
-                   NS_SUCCEEDED(stack->GetCaller(getter_AddRefs(caller))) &&
-                   caller) {
-                stack = caller;
-            }
-            NS_IF_ADDREF(*aCurrentJSStack = stack);
-        }
-    }
+    nsCOMPtr<nsIStackFrame> currentStack = dom::GetCurrentJSStack();
+    currentStack.forget(aCurrentJSStack);
+
     return NS_OK;
 }
 
 /* readonly attribute nsIXPCNativeCallContext CurrentNativeCallContext; */
 NS_IMETHODIMP
 nsXPConnect::GetCurrentNativeCallContext(nsAXPCNativeCallContext * *aCurrentNativeCallContext)
 {
     MOZ_ASSERT(aCurrentNativeCallContext, "bad param");
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -127,17 +127,17 @@
 #include "nsXPIDLString.h"
 #include "nsAutoJSValHolder.h"
 
 #include "nsThreadUtils.h"
 #include "nsIJSEngineTelemetryStats.h"
 
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
-#include "nsIExceptionService.h"
+#include "nsIException.h"
 
 #include "nsVariant.h"
 #include "nsIPropertyBag.h"
 #include "nsIProperty.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsBaseHashtable.h"
 #include "nsHashKeys.h"
@@ -734,60 +734,16 @@ public:
     void DebugDump(int16_t depth);
 
     void SystemIsBeingShutDown();
 
     PRThread* GetThreadRunningGC() const {return mThreadRunningGC;}
 
     ~XPCJSRuntime();
 
-    nsresult GetPendingException(nsIException** aException)
-    {
-        if (EnsureExceptionManager())
-            return mExceptionManager->GetCurrentException(aException);
-        nsCOMPtr<nsIException> out = mPendingException;
-        out.forget(aException);
-        return NS_OK;
-    }
-
-    nsresult SetPendingException(nsIException* aException)
-    {
-        if (EnsureExceptionManager())
-            return mExceptionManager->SetCurrentException(aException);
-
-        mPendingException = aException;
-        return NS_OK;
-    }
-
-    nsIExceptionManager* GetExceptionManager()
-    {
-        if (EnsureExceptionManager())
-            return mExceptionManager;
-        return nullptr;
-    }
-
-    bool EnsureExceptionManager()
-    {
-        if (mExceptionManager)
-            return true;
-
-        if (mExceptionManagerNotAvailable)
-            return false;
-
-        nsCOMPtr<nsIExceptionService> xs =
-            do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
-        if (xs)
-            xs->GetCurrentExceptionManager(getter_AddRefs(mExceptionManager));
-        if (mExceptionManager)
-            return true;
-
-        mExceptionManagerNotAvailable = true;
-        return false;
-    }
-
     XPCReadableJSStringWrapper *NewStringWrapper(const PRUnichar *str, uint32_t len);
     void DeleteString(nsAString *string);
 
 #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
    void DEBUG_AddWrappedNative(nsIXPConnectWrappedNative* wrapper)
         {XPCAutoLock lock(GetMapLock());
          PLDHashEntryHdr *entry =
             PL_DHashTableOperate(DEBUG_WrappedNativeHashtable,
@@ -859,20 +815,16 @@ private:
     nsTArray<xpcContextCallback> extraContextCallbacks;
     nsRefPtr<WatchdogManager> mWatchdogManager;
     JS::GCSliceCallback mPrevGCSliceCallback;
     JSObject* mJunkScope;
     nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
 
     mozilla::TimeStamp mSlowScriptCheckpoint;
 
-    nsCOMPtr<nsIException>   mPendingException;
-    nsCOMPtr<nsIExceptionManager> mExceptionManager;
-    bool mExceptionManagerNotAvailable;
-
 #define XPCCCX_STRING_CACHE_SIZE 2
 
     // String wrapper entry, holds a string, and a boolean that tells
     // whether the string is in use or not.
     //
     // NB: The string is not stored by value so that we avoid the cost of
     // construction/destruction.
     struct StringWrapperEntry
@@ -1295,18 +1247,20 @@ public:
     nsXPCComponents*
     GetComponents() const {return mComponents;}
 
     // Returns the JS object reflection of the Components object.
     JSObject*
     GetComponentsJSObject();
 
     JSObject*
-    GetGlobalJSObject() const
-        {return xpc_UnmarkGrayObject(mGlobalJSObject);}
+    GetGlobalJSObject() const {
+        JS::ExposeObjectToActiveJS(mGlobalJSObject);
+        return mGlobalJSObject;
+    }
 
     JSObject*
     GetGlobalJSObjectPreserveColor() const {return mGlobalJSObject;}
 
     nsIPrincipal*
     GetPrincipal() const {
         JSCompartment *c = js::GetObjectCompartment(mGlobalJSObject);
         return nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
@@ -2024,17 +1978,20 @@ public:
 
     XPCWrappedNativeScope*
     GetScope()   const {return mScope;}
 
     XPCJSRuntime*
     GetRuntime() const {return mScope->GetRuntime();}
 
     JSObject*
-    GetJSProtoObject() const {return xpc_UnmarkGrayObject(mJSProtoObject);}
+    GetJSProtoObject() const {
+        JS::ExposeObjectToActiveJS(mJSProtoObject);
+        return mJSProtoObject;
+    }
 
     nsIClassInfo*
     GetClassInfo()     const {return mClassInfo;}
 
     XPCNativeSet*
     GetSet()           const {return mSet;}
 
     XPCNativeScriptableInfo*
@@ -2290,18 +2247,20 @@ public:
     GetIdentityObject() const {return mIdentity;}
 
     /**
      * This getter clears the gray bit before handing out the JSObject which
      * means that the object is guaranteed to be kept alive past the next CC.
      */
     JSObject*
     GetFlatJSObject() const
-        {xpc_UnmarkGrayObject(mFlatJSObject);
-         return mFlatJSObject;}
+    {
+        JS::ExposeObjectToActiveJS(mFlatJSObject);
+        return mFlatJSObject;
+    }
 
     /**
      * This getter does not change the color of the JSObject meaning that the
      * object returned is not guaranteed to be kept alive past the next CC.
      *
      * This should only be called if you are certain that the return value won't
      * be passed into a JS API function and that it won't be stored without
      * being rooted (or otherwise signaling the stored value to the CC).
@@ -2480,17 +2439,17 @@ public:
     void SetNeedsCOW() { mWrapper.setFlags(WRAPPER_NEEDS_COW); }
 
     JSObject* GetWrapperPreserveColor() const { return mWrapper.getPtr(); }
 
     JSObject* GetWrapper()
     {
         JSObject* wrapper = GetWrapperPreserveColor();
         if (wrapper) {
-            xpc_UnmarkGrayObject(wrapper);
+            JS::ExposeObjectToActiveJS(wrapper);
             // Call this to unmark mFlatJSObject.
             GetFlatJSObject();
         }
         return wrapper;
     }
     void SetWrapper(JSObject *obj)
     {
         JS::IncrementalObjectBarrier(GetWrapperPreserveColor());
@@ -2954,109 +2913,53 @@ public:
 private:
     XPCConvert(); // not implemented
 
 };
 
 /***************************************************************************/
 // code for throwing exceptions into JS
 
+class nsXPCException;
+
 class XPCThrower
 {
 public:
     static void Throw(nsresult rv, JSContext* cx);
     static void Throw(nsresult rv, XPCCallContext& ccx);
     static void ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx);
     static void ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx);
     static bool SetVerbosity(bool state)
         {bool old = sVerbose; sVerbose = state; return old;}
 
-    static void BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz);
     static bool CheckForPendingException(nsresult result, JSContext *cx);
 
 private:
     static void Verbosify(XPCCallContext& ccx,
                           char** psz, bool own);
 
-    static bool ThrowExceptionObject(JSContext* cx, nsIException* e);
-
 private:
     static bool sVerbose;
 };
 
-
 /***************************************************************************/
 
-class XPCJSStack
+class nsXPCException
 {
 public:
-    static nsresult
-    CreateStack(JSContext* cx, nsIStackFrame** stack);
-
-    static nsresult
-    CreateStackFrameLocation(uint32_t aLanguage,
-                             const char* aFilename,
-                             const char* aFunctionName,
-                             int32_t aLineNumber,
-                             nsIStackFrame* aCaller,
-                             nsIStackFrame** stack);
-private:
-    XPCJSStack();   // not implemented
-};
-
-/***************************************************************************/
-
-class nsXPCException :
-            public nsIXPCException
-{
-public:
-    NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCEXCEPTION_CID)
-
-    NS_DECL_THREADSAFE_ISUPPORTS
-    NS_DECL_NSIEXCEPTION
-    NS_DECL_NSIXPCEXCEPTION
-
-    static nsresult NewException(const char *aMessage,
-                                 nsresult aResult,
-                                 nsIStackFrame *aLocation,
-                                 nsISupports *aData,
-                                 nsIException** exception);
-
     static bool NameAndFormatForNSResult(nsresult rv,
                                          const char** name,
                                          const char** format);
 
     static const void* IterateNSResults(nsresult* rv,
                                         const char** name,
                                         const char** format,
                                         const void** iterp);
 
     static uint32_t GetNSResultCount();
-
-    nsXPCException();
-    virtual ~nsXPCException();
-
-    static void InitStatics() { sEverMadeOneFromFactory = false; }
-
-protected:
-    void Reset();
-private:
-    char*           mMessage;
-    nsresult        mResult;
-    char*           mName;
-    nsIStackFrame*  mLocation;
-    nsISupports*    mData;
-    char*           mFilename;
-    int             mLineNumber;
-    nsIException*   mInner;
-    bool            mInitialized;
-
-    nsAutoJSValHolder mThrownJSVal;
-
-    static bool sEverMadeOneFromFactory;
 };
 
 /***************************************************************************/
 /*
 * nsJSID implements nsIJSID. It is also used by nsJSIID and nsJSCID as a
 * member (as a hidden implementaion detail) to which they delegate many calls.
 */
 
@@ -3566,20 +3469,21 @@ public:
 
     static XPCVariant* newVariant(JSContext* cx, jsval aJSVal);
 
     /**
      * This getter clears the gray bit before handing out the jsval if the jsval
      * represents a JSObject. That means that the object is guaranteed to be
      * kept alive past the next CC.
      */
-    jsval GetJSVal() const
-        {if (!JSVAL_IS_PRIMITIVE(mJSVal))
-             xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(mJSVal));
-         return mJSVal;}
+    jsval GetJSVal() const {
+        if (!JSVAL_IS_PRIMITIVE(mJSVal))
+            JS::ExposeObjectToActiveJS(&mJSVal.toObject());
+        return mJSVal;
+    }
 
     /**
      * This getter does not change the color of the jsval (if it represents a
      * JSObject) meaning that the value returned is not guaranteed to be kept
      * alive past the next CC.
      *
      * This should only be called if you are certain that the return value won't
      * be passed into a JS API function and that it won't be stored without
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -132,33 +132,16 @@ xpc_IsGrayGCThing(void *thing)
     return JS::GCThingIsMarkedGray(thing);
 }
 
 // The cycle collector only cares about some kinds of GCthings that are
 // reachable from an XPConnect root. Implemented in nsXPConnect.cpp.
 extern bool
 xpc_GCThingIsGrayCCThing(void *thing);
 
-// Unmark gray for known-nonnull cases
-MOZ_ALWAYS_INLINE void
-xpc_UnmarkNonNullGrayObject(JSObject *obj)
-{
-    JS::ExposeGCThingToActiveJS(obj, JSTRACE_OBJECT);
-}
-
-// Remove the gray color from the given JSObject and any other objects that can
-// be reached through it.
-MOZ_ALWAYS_INLINE JSObject *
-xpc_UnmarkGrayObject(JSObject *obj)
-{
-    if (obj)
-        xpc_UnmarkNonNullGrayObject(obj);
-    return obj;
-}
-
 inline JSScript *
 xpc_UnmarkGrayScript(JSScript *script)
 {
     if (script)
         JS::ExposeGCThingToActiveJS(script, JSTRACE_SCRIPT);
 
     return script;
 }
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -54,17 +54,22 @@ WrapperFactory::GetXrayWaiver(JSObject *
     // Object should come fully unwrapped but outerized.
     MOZ_ASSERT(obj == UncheckedUnwrap(obj));
     MOZ_ASSERT(!js::GetObjectClass(obj)->ext.outerObject);
     XPCWrappedNativeScope *scope = GetObjectScope(obj);
     MOZ_ASSERT(scope);
 
     if (!scope->mWaiverWrapperMap)
         return NULL;
-    return xpc_UnmarkGrayObject(scope->mWaiverWrapperMap->Find(obj));
+
+    JSObject* xrayWaiver = scope->mWaiverWrapperMap->Find(obj);
+    if (xrayWaiver)
+        JS::ExposeObjectToActiveJS(xrayWaiver);
+
+    return xrayWaiver;
 }
 
 JSObject *
 WrapperFactory::CreateXrayWaiver(JSContext *cx, HandleObject obj)
 {
     // The caller is required to have already done a lookup.
     // NB: This implictly performs the assertions of GetXrayWaiver.
     MOZ_ASSERT(!GetXrayWaiver(obj));
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -63,33 +63,33 @@
 #include "nsXMLHttpRequest.h"
 #include "nsChannelPolicy.h"
 
 // view stuff
 #include "nsContentCreatorFunctions.h"
 
 // DOM includes
 #include "nsDOMBlobBuilder.h"
-#include "nsDOMException.h"
 #include "nsDOMFileReader.h"
 
 #include "nsFormData.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsHostObjectURI.h"
 #include "nsGlobalWindowCommands.h"
 #include "nsIControllerCommandTable.h"
 #include "nsJSProtocolHandler.h"
 #include "nsScriptNameSpaceManager.h"
 #include "nsIControllerContext.h"
 #include "nsDOMScriptObjectFactory.h"
 #include "DOMStorageManager.h"
 #include "nsJSON.h"
 #include "mozIApplicationClearPrivateDataParams.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Activity.h"
+#include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMRequest.h"
 #include "mozilla/dom/EventSource.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "mozilla/dom/network/TCPSocketChild.h"
 #include "mozilla/dom/network/TCPSocketParent.h"
 #include "mozilla/dom/network/TCPServerSocketChild.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/OSFileConstants.h"
@@ -270,16 +270,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(Activity)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDOMFileReader, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormData)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBlobProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaStreamProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaSourceProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontTableProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURI)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMParser)
+NS_GENERIC_FACTORY_CONSTRUCTOR(Exception)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMSessionStorageManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(DOMLocalStorageManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsChannelPolicy)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(IndexedDatabaseManager,
                                          IndexedDatabaseManager::FactoryCreate)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DOMRequestService,
                                          DOMRequestService::FactoryCreate)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(QuotaManager,
@@ -1022,16 +1023,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_MEDIASTREAMPROTOCOLHANDLER_CID, false, NULL, nsMediaStreamProtocolHandlerConstructor },
   { &kNS_MEDIASOURCEPROTOCOLHANDLER_CID, false, NULL, nsMediaSourceProtocolHandlerConstructor },
   { &kNS_FONTTABLEPROTOCOLHANDLER_CID, false, NULL, nsFontTableProtocolHandlerConstructor },
   { &kNS_HOSTOBJECTURI_CID, false, NULL, nsHostObjectURIConstructor },
   { &kNS_XMLHTTPREQUEST_CID, false, NULL, nsXMLHttpRequestConstructor },
   { &kNS_EVENTSOURCE_CID, false, NULL, EventSourceConstructor },
   { &kNS_DOMACTIVITY_CID, false, NULL, ActivityConstructor },
   { &kNS_DOMPARSER_CID, false, NULL, DOMParserConstructor },
+  { &kNS_XPCEXCEPTION_CID, false, NULL, ExceptionConstructor },
   { &kNS_DOMSESSIONSTORAGEMANAGER_CID, false, NULL, DOMSessionStorageManagerConstructor },
   { &kNS_DOMLOCALSTORAGEMANAGER_CID, false, NULL, DOMLocalStorageManagerConstructor },
   { &kNS_DOMJSON_CID, false, NULL, NS_NewJSON },
   { &kNS_TEXTEDITOR_CID, false, NULL, nsPlaintextEditorConstructor },
   { &kINDEXEDDB_MANAGER_CID, false, NULL, IndexedDatabaseManagerConstructor },
   { &kDOMREQUEST_SERVICE_CID, false, NULL, DOMRequestServiceConstructor },
   { &kQUOTA_MANAGER_CID, false, NULL, QuotaManagerConstructor },
 #ifdef MOZ_B2G_RIL
@@ -1176,16 +1178,17 @@ static const mozilla::Module::ContractID
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX BLOBURI_SCHEME, &kNS_BLOBPROTOCOLHANDLER_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASTREAMURI_SCHEME, &kNS_MEDIASTREAMPROTOCOLHANDLER_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASOURCEURI_SCHEME, &kNS_MEDIASOURCEPROTOCOLHANDLER_CID },
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX FONTTABLEURI_SCHEME, &kNS_FONTTABLEPROTOCOLHANDLER_CID },
   { NS_XMLHTTPREQUEST_CONTRACTID, &kNS_XMLHTTPREQUEST_CID },
   { NS_EVENTSOURCE_CONTRACTID, &kNS_EVENTSOURCE_CID },
   { NS_DOMACTIVITY_CONTRACTID, &kNS_DOMACTIVITY_CID },
   { NS_DOMPARSER_CONTRACTID, &kNS_DOMPARSER_CID },
+  { XPC_EXCEPTION_CONTRACTID, &kNS_XPCEXCEPTION_CID },
   { "@mozilla.org/dom/localStorage-manager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },
   // Keeping the old ContractID for backward compatibility
   { "@mozilla.org/dom/storagemanager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },
   { "@mozilla.org/dom/sessionStorage-manager;1", &kNS_DOMSESSIONSTORAGEMANAGER_CID },
   { "@mozilla.org/dom/json;1", &kNS_DOMJSON_CID },
   { "@mozilla.org/editor/texteditor;1", &kNS_TEXTEDITOR_CID },
   { INDEXEDDB_MANAGER_CONTRACTID, &kINDEXEDDB_MANAGER_CID },
   { DOMREQUEST_SERVICE_CONTRACTID, &kDOMREQUEST_SERVICE_CID },
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -116,17 +116,17 @@ FontSizeInflationListMarginAdjustment(co
       // performing font inflation calculations, we add space equivalent to this,
       // but simply inflated at the same amount as the text, in app units.
       return nsPresContext::CSSPixelsToAppUnits(40) * (inflation - 1);
     }
   }
 
   return 0;
 }
-// Initialize a reflow state for a child frames reflow. Some state
+// Initialize a reflow state for a child frame's reflow. Some state
 // is copied from the parent reflow state; the remaining state is
 // computed.
 nsHTMLReflowState::nsHTMLReflowState(nsPresContext*           aPresContext,
                                      const nsHTMLReflowState& aParentReflowState,
                                      nsIFrame*                aFrame,
                                      const nsSize&            aAvailableSpace,
                                      nscoord                  aContainingBlockWidth,
                                      nscoord                  aContainingBlockHeight,
--- a/layout/inspector/tests/test_bug462787.html
+++ b/layout/inspector/tests/test_bug462787.html
@@ -23,53 +23,74 @@ function do_test() {
   const INVALID_POINTER = 0x80004003;
 
   var utils = SpecialPowers.Cc["@mozilla.org/inspector/dom-utils;1"]
                              .getService(SpecialPowers.Ci.inIDOMUtils);
   try {
     utils.getCSSStyleRules(null); 
     ok(false, "expected an exception"); 
   }
-  catch(e) { is(e.result, INVALID_POINTER, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, INVALID_POINTER, "got the expected exception");
+  }
 
   try {
     utils.getRuleLine(null); 
     ok(false, "expected an exception"); 
   }
-  catch(e) { is(e.result, INVALID_POINTER, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, INVALID_POINTER, "got the expected exception");
+  }
 
   try {
     utils.isIgnorableWhitespace(null);
     ok(false, "expected an exception");
   }
-  catch(e) { is(e.result, INVALID_POINTER, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, INVALID_POINTER, "got the expected exception");
+  }
 
   try {
     utils.getParentForNode(null, true); 
     ok(false, "expected an exception");
   }
-  catch(e) { is(e.result, INVALID_POINTER, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, INVALID_POINTER, "got the expected exception");
+  }
 
   try {
     utils.getBindingURLs(null); 
     ok(false, "expected an exception"); 
   }
-  catch(e) { is(e.result, INVALID_POINTER, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, INVALID_POINTER, "got the expected exception");
+  }
 
   try {
     utils.getContentState(null); 
     ok(false, "expected an exception"); 
   }
-  catch(e) { is(e.result, INVALID_POINTER, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, INVALID_POINTER, "got the expected exception");
+  }
 
   try {
     utils.setContentState(null, false); 
     ok(false, "expected an exception"); 
   }
-  catch(e) { is(e.result, INVALID_POINTER, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, INVALID_POINTER, "got the expected exception");
+  }
 
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(do_test);
 
 
--- a/layout/inspector/tests/test_bug462789.html
+++ b/layout/inspector/tests/test_bug462789.html
@@ -72,17 +72,20 @@ function do_test() {
     ok(true, "Should not throw"); 
   }
   catch(e) { ok(false, "Got an exception: " + e); }
 
   try {
     utils.setContentState(docElement, false);
     ok(false, "expected an exception"); 
   }
-  catch(e) { is(e.result, ERROR_FAILURE, "got the expected exception"); }
+  catch(e) {
+    e = SpecialPowers.wrap(e);
+    is(e.result, ERROR_FAILURE, "got the expected exception");
+  }
 
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(do_test);
 
 </script>
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -38,20 +38,18 @@ nsDOMCSSAttributeDeclaration::~nsDOMCSSA
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsDOMCSSAttributeDeclaration, mElement)
 
 // mElement holds a strong ref to us, so if it's going to be
 // skipped, the attribute declaration can't be part of a garbage
 // cycle.
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMCSSAttributeDeclaration)
   if (tmp->mElement && Element::CanSkip(tmp->mElement, true)) {
     if (tmp->PreservingWrapper()) {
-      // Not relying on GetWrapper to unmark us gray because the
-      // side-effect thing is pretty weird.
-      JSObject* o = tmp->GetWrapperPreserveColor();
-      xpc_UnmarkGrayObject(o);
+      // This marks the wrapper black.
+      tmp->GetWrapper();
     }
     return true;
   }
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDOMCSSAttributeDeclaration)
   return tmp->IsBlack() ||
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -46,16 +46,17 @@
 #include "nsJSPrincipals.h"
 #include "nsJSUtils.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIGenKeypairInfoDlg.h"
 #include "nsIDOMCryptoDialogs.h"
 #include "nsIFormSigningDialog.h"
 #include "nsIContentSecurityPolicy.h"
+#include "nsIURI.h"
 #include "jsapi.h"
 #include "js/OldDebugAPI.h"
 #include <ctype.h>
 #include "pk11func.h"
 #include "keyhi.h"
 #include "cryptohi.h"
 #include "seccomon.h"
 #include "secerr.h"
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -39,16 +39,17 @@ using mozilla::plugins::PluginInstancePa
 
 #include "LayerManagerOGL.h"
 #ifdef MOZ_ENABLE_D3D9_LAYER
 #include "LayerManagerD3D9.h"
 #endif
 #ifdef MOZ_ENABLE_D3D10_LAYER
 #include "LayerManagerD3D10.h"
 #endif
+#include "mozilla/layers/CompositorParent.h"
 
 #include "nsUXThemeData.h"
 #include "nsUXThemeConstants.h"
 #include "mozilla/gfx/2D.h"
 
 extern "C" {
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"
@@ -207,16 +208,23 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
       // could fail. Return without asserting since it's not our fault.
       NS_WARNING("Plugin failed to subclass our window");
     }
 
     ValidateRect(mWnd, NULL);
     return true;
   }
 
+  // Do an early async composite so that we at least have something on screen
+  // in the right place, even if the content is out of date.
+  if (GetLayerManager()->GetBackendType() == LAYERS_CLIENT &&
+      mCompositorParent) {
+    mCompositorParent->ScheduleRenderOnCompositorThread();
+  }
+
   nsIWidgetListener* listener = GetPaintListener();
   if (listener) {
     listener->WillPaintWindow(this);
   }
   // Re-get the listener since the will paint notification may have killed it.
   listener = GetPaintListener();
   if (!listener)
     return false;
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -59,16 +59,17 @@
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMJSClass.h"
 #include "jsprf.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollector.h"
 #include "nsDOMJSUtils.h"
+#include "nsIException.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace mozilla {
 
@@ -458,16 +459,19 @@ CycleCollectedJSRuntime::CycleCollectedJ
   nsCycleCollector_registerJSRuntime(this);
 }
 
 CycleCollectedJSRuntime::~CycleCollectedJSRuntime()
 {
   MOZ_ASSERT(!mDeferredFinalizerTable.Count());
   MOZ_ASSERT(!mDeferredSupports.Length());
 
+  // Clear mPendingException first, since it might be cycle collected.
+  mPendingException = nullptr;
+
   nsCycleCollector_forgetJSRuntime();
 
   JS_DestroyRuntime(mJSRuntime);
   mJSRuntime = nullptr;
 }
 
 size_t
 CycleCollectedJSRuntime::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
@@ -823,16 +827,29 @@ CycleCollectedJSRuntime::AssertNoObjects
 {
   nsScriptObjectTracer* tracer = mJSHolders.Get(aPossibleJSHolder);
   if (tracer) {
     tracer->Trace(aPossibleJSHolder, TraceCallbackFunc(AssertNoGcThing), nullptr);
   }
 }
 #endif
 
+already_AddRefed<nsIException>
+CycleCollectedJSRuntime::GetPendingException() const
+{
+  nsCOMPtr<nsIException> out = mPendingException;
+  return out.forget();
+}
+
+void
+CycleCollectedJSRuntime::SetPendingException(nsIException* aException)
+{
+  mPendingException = aException;
+}
+
 nsCycleCollectionParticipant*
 CycleCollectedJSRuntime::GCThingParticipant()
 {
     return &mGCThingCycleCollectorGlobal;
 }
 
 nsCycleCollectionParticipant*
 CycleCollectedJSRuntime::ZoneParticipant()
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -14,16 +14,17 @@
 #include "nsCycleCollector.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsTArray.h"
 
 class nsCycleCollectionNoteRootCallback;
 class nsScriptObjectTracer;
+class nsIException;
 
 namespace mozilla {
 
 class JSGCThingParticipant: public nsCycleCollectionParticipant
 {
 public:
   NS_IMETHOD Root(void *n)
   {
@@ -167,16 +168,19 @@ public:
   void AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
   void RemoveJSHolder(void* aHolder);
 #ifdef DEBUG
   bool IsJSHolder(void* aHolder);
   void SetObjectToUnlink(void* aObject) { mObjectToUnlink = aObject; }
   void AssertNoObjectsToTrace(void* aPossibleJSHolder);
 #endif
 
+  already_AddRefed<nsIException> GetPendingException() const;
+  void SetPendingException(nsIException* aException);
+
   nsCycleCollectionParticipant* GCThingParticipant();
   nsCycleCollectionParticipant* ZoneParticipant();
 
   nsresult BeginCycleCollection(nsCycleCollectionNoteRootCallback &aCb);
   bool UsefulToMergeZones() const;
   void FixWeakMappingGrayBits() const;
   bool NeedCollect() const;
   void Collect(uint32_t reason) const;
@@ -193,32 +197,39 @@ public:
   
   virtual void DispatchDeferredDeletion(bool aContinuation) = 0;
 
   JSRuntime* Runtime() const
   {
     MOZ_ASSERT(mJSRuntime);
     return mJSRuntime;
   }
+
+  // Get the current thread's CycleCollectedJSRuntime.  Returns null if there
+  // isn't one.
+  static CycleCollectedJSRuntime* Get();
+
 private:
   JSGCThingParticipant mGCThingCycleCollectorGlobal;
 
   JSZoneParticipant mJSZoneCycleCollectorGlobal;
 
   JSRuntime* mJSRuntime;
 
   nsDataHashtable<nsPtrHashKey<void>, nsScriptObjectTracer*> mJSHolders;
 
   nsTArray<nsISupports*> mDeferredSupports;
   typedef nsDataHashtable<nsFuncPtrHashKey<DeferredFinalizeFunction>, void*>
     DeferredFinalizerTable;
   DeferredFinalizerTable mDeferredFinalizerTable;
 
   nsRefPtr<IncrementalFinalizeRunnable> mFinalizeRunnable;
 
+  nsCOMPtr<nsIException> mPendingException;
+
 #ifdef DEBUG
   void* mObjectToUnlink;
 #endif
 };
 
 } // namespace mozilla
 
 #endif // mozilla_CycleCollectedJSRuntime_h__
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -8,17 +8,16 @@ XPIDL_SOURCES += [
     'nsIConsoleListener.idl',
     'nsIConsoleMessage.idl',
     'nsIConsoleService.idl',
     'nsICycleCollectorListener.idl',
     'nsIDebug.idl',
     'nsIDebug2.idl',
     'nsIErrorService.idl',
     'nsIException.idl',
-    'nsIExceptionService.idl',
     'nsIGZFileWriter.idl',
     'nsIInterfaceRequestor.idl',
     'nsIMemory.idl',
     'nsIMemoryInfoDumper.idl',
     'nsIMemoryReporter.idl',
     'nsIMessageLoop.idl',
     'nsIMutable.idl',
     'nsIProgrammingLanguage.idl',
@@ -90,17 +89,16 @@ CPP_SOURCES += [
     'CycleCollectedJSRuntime.cpp',
     'VisualEventTracer.cpp',
     'nsConsoleMessage.cpp',
     'nsConsoleService.cpp',
     'nsCycleCollector.cpp',
     'nsDebugImpl.cpp',
     'nsErrorAsserts.cpp',
     'nsErrorService.cpp',
-    'nsExceptionService.cpp',
     'nsGZFileWriter.cpp',
     'nsInterfaceRequestorAgg.cpp',
     'nsMemoryImpl.cpp',
     'nsMemoryInfoDumper.cpp',
     'nsMemoryReporterManager.cpp',
     'nsMessageLoop.cpp',
     'nsSecurityConsoleMessage.cpp',
     'nsStackWalk.cpp',
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -2898,18 +2898,18 @@ nsCycleCollector_forgetJSRuntime()
         data->mRuntime = nullptr;
     } else {
         data->mRuntime = nullptr;
         delete data;
         sCollectorData.set(nullptr);
     }
 }
 
-mozilla::CycleCollectedJSRuntime*
-nsCycleCollector_currentJSRuntime()
+/* static */ CycleCollectedJSRuntime*
+CycleCollectedJSRuntime::Get()
 {
     CollectorData* data = sCollectorData.get();
     if (data) {
         return data->mRuntime;
     }
     return nullptr;
 }
 
--- a/xpcom/base/nsCycleCollector.h
+++ b/xpcom/base/nsCycleCollector.h
@@ -59,17 +59,16 @@ void nsCycleCollector_collect(bool aManu
                               nsCycleCollectorResults *aResults,
                               nsICycleCollectorListener *aListener);
 uint32_t nsCycleCollector_suspectedCount();
 void nsCycleCollector_shutdown();
 
 // Helpers for interacting with JS
 void nsCycleCollector_registerJSRuntime(mozilla::CycleCollectedJSRuntime *aRt);
 void nsCycleCollector_forgetJSRuntime();
-mozilla::CycleCollectedJSRuntime* nsCycleCollector_currentJSRuntime();
 
 #define NS_CYCLE_COLLECTOR_LOGGER_CID \
 { 0x58be81b4, 0x39d2, 0x437c, \
 { 0x94, 0xea, 0xae, 0xde, 0x2c, 0x62, 0x08, 0xd3 } }
 
 extern nsresult
 nsCycleCollectorLoggerConstructor(nsISupports* outer,
                                   const nsIID& aIID,
deleted file mode 100644
--- a/xpcom/base/nsExceptionService.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsExceptionService.h"
-
-#include "mozilla/Attributes.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/Services.h"
-#include "nsCOMPtr.h"
-#include "nsDOMException.h"
-#include "nsIServiceManager.h"
-#include "nsISupports.h"
-#include "nsThreadUtils.h"
-#include "pratom.h"
-#include "prthread.h"
-
-using namespace mozilla;
-
-static const unsigned BAD_TLS_INDEX = (unsigned) -1;
-
-#define CHECK_SERVICE_USE_OK() if (!sLock) return NS_ERROR_NOT_INITIALIZED
-#define CHECK_MANAGER_USE_OK() if (!mService || !nsExceptionService::sLock) return NS_ERROR_NOT_INITIALIZED
-
-/** Exception Manager definition **/
-class nsExceptionManager MOZ_FINAL : public nsIExceptionManager
-{
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIEXCEPTIONMANAGER
-
-  nsExceptionManager(nsExceptionService *svc);
-  /* additional members */
-  nsCOMPtr<nsIException> mCurrentException;
-  nsExceptionManager *mNextThread; // not ref-counted.
-  nsExceptionService *mService; // not ref-counted
-#ifdef DEBUG
-  static Atomic<int32_t> totalInstances;
-#endif
-
-private:
-  ~nsExceptionManager();
-};
-
-
-#ifdef DEBUG
-Atomic<int32_t> nsExceptionManager::totalInstances;
-#endif
-
-// Note this object is single threaded - the service itself ensures
-// one per thread.
-// An exception if the destructor, which may be called on
-// the thread shutting down xpcom
-NS_IMPL_ISUPPORTS1(nsExceptionManager, nsIExceptionManager)
-
-nsExceptionManager::nsExceptionManager(nsExceptionService *svc) :
-  mNextThread(nullptr),
-  mService(svc)
-{
-  /* member initializers and constructor code */
-#ifdef DEBUG
-  ++totalInstances;
-#endif
-}
-
-nsExceptionManager::~nsExceptionManager()
-{
-  /* destructor code */
-#ifdef DEBUG
-  --totalInstances;
-#endif // DEBUG
-}
-
-/* void setCurrentException (in nsIException error); */
-NS_IMETHODIMP nsExceptionManager::SetCurrentException(nsIException *error)
-{
-    CHECK_MANAGER_USE_OK();
-    mCurrentException = error;
-    return NS_OK;
-}
-
-/* nsIException getCurrentException (); */
-NS_IMETHODIMP nsExceptionManager::GetCurrentException(nsIException **_retval)
-{
-    CHECK_MANAGER_USE_OK();
-    *_retval = mCurrentException;
-    NS_IF_ADDREF(*_retval);
-    return NS_OK;
-}
-
-/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
-NS_IMETHODIMP nsExceptionManager::GetExceptionFromProvider(nsresult rc, nsIException * defaultException, nsIException **_retval)
-{
-    CHECK_MANAGER_USE_OK();
-    // Just delegate back to the service with the provider map.
-    return mService->GetExceptionFromProvider(rc, defaultException, _retval);
-}
-
-/* The Exception Service */
-
-unsigned nsExceptionService::tlsIndex = BAD_TLS_INDEX;
-Mutex *nsExceptionService::sLock = nullptr;
-nsExceptionManager *nsExceptionService::firstThread = nullptr;
-
-#ifdef DEBUG
-Atomic<int32_t> nsExceptionService::totalInstances;
-#endif
-
-NS_IMPL_ISUPPORTS3(nsExceptionService,
-                   nsIExceptionService,
-                   nsIExceptionManager,
-                   nsIObserver)
-
-nsExceptionService::nsExceptionService()
-{
-#ifdef DEBUG
-  if (++totalInstances != 1) {
-    NS_ERROR("The nsExceptionService is a singleton!");
-  }
-#endif
-  /* member initializers and constructor code */
-  if (tlsIndex == BAD_TLS_INDEX) {
-    DebugOnly<PRStatus> status;
-    status = PR_NewThreadPrivateIndex( &tlsIndex, ThreadDestruct );
-    NS_ASSERTION(status==0, "ScriptErrorService could not allocate TLS storage.");
-  }
-  sLock = new Mutex("nsExceptionService.sLock");
-
-  // observe XPCOM shutdown.
-  nsCOMPtr<nsIObserverService> observerService =
-    mozilla::services::GetObserverService();
-  NS_ASSERTION(observerService, "Could not get observer service!");
-  if (observerService)
-    observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
-}
-
-nsExceptionService::~nsExceptionService()
-{
-  Shutdown();
-  /* destructor code */
-#ifdef DEBUG
-  --totalInstances;
-#endif
-}
-
-/*static*/
-void nsExceptionService::ThreadDestruct( void *data )
-{
-  if (!sLock) {
-    NS_WARNING("nsExceptionService ignoring thread destruction after shutdown");
-    return;
-  }
-  DropThread( (nsExceptionManager *)data );
-}
-
-
-void nsExceptionService::Shutdown()
-{
-  if (sLock) {
-    DropAllThreads();
-    delete sLock;
-    sLock = nullptr;
-  }
-  PR_SetThreadPrivate(tlsIndex, nullptr);
-}
-
-/* void setCurrentException (in nsIException error); */
-NS_IMETHODIMP nsExceptionService::SetCurrentException(nsIException *error)
-{
-    CHECK_SERVICE_USE_OK();
-    nsCOMPtr<nsIExceptionManager> sm;
-    nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
-    if (NS_FAILED(nr))
-        return nr;
-    return sm->SetCurrentException(error);
-}
-
-/* nsIException getCurrentException (); */
-NS_IMETHODIMP nsExceptionService::GetCurrentException(nsIException **_retval)
-{
-    CHECK_SERVICE_USE_OK();
-    nsCOMPtr<nsIExceptionManager> sm;
-    nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
-    if (NS_FAILED(nr))
-        return nr;
-    return sm->GetCurrentException(_retval);
-}
-
-/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
-NS_IMETHODIMP nsExceptionService::GetExceptionFromProvider(nsresult rc, 
-    nsIException * defaultException, nsIException **_retval)
-{
-    CHECK_SERVICE_USE_OK();
-    return DoGetExceptionFromProvider(rc, defaultException, _retval);
-}
-
-/* readonly attribute nsIExceptionManager currentExceptionManager; */
-NS_IMETHODIMP nsExceptionService::GetCurrentExceptionManager(nsIExceptionManager * *aCurrentScriptManager)
-{
-    CHECK_SERVICE_USE_OK();
-    nsExceptionManager *mgr = (nsExceptionManager *)PR_GetThreadPrivate(tlsIndex);
-    if (mgr == nullptr) {
-        // Stick the new exception object in with no reference count.
-        mgr = new nsExceptionManager(this);
-        PR_SetThreadPrivate(tlsIndex, mgr);
-        // The reference count is held in the thread-list
-        AddThread(mgr);
-    }
-    *aCurrentScriptManager = mgr;
-    NS_ADDREF(*aCurrentScriptManager);
-    return NS_OK;
-}
-
-// nsIObserver
-NS_IMETHODIMP nsExceptionService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
-{
-     Shutdown();
-     return NS_OK;
-}
-
-nsresult
-nsExceptionService::DoGetExceptionFromProvider(nsresult errCode, 
-                                               nsIException * defaultException,
-                                               nsIException **_exc)
-{
-    // Check for an existing exception
-    nsresult nr = GetCurrentException(_exc);
-    if (NS_SUCCEEDED(nr) && *_exc) {
-        (*_exc)->GetResult(&nr);
-        // If it matches our result then use it
-        if (nr == errCode)
-            return NS_OK;
-        NS_RELEASE(*_exc);
-    }
-
-    switch (NS_ERROR_GET_MODULE(errCode)) {
-    case NS_ERROR_MODULE_DOM:
-    case NS_ERROR_MODULE_SVG:
-    case NS_ERROR_MODULE_DOM_XPATH:
-    case NS_ERROR_MODULE_DOM_INDEXEDDB:
-    case NS_ERROR_MODULE_DOM_FILEHANDLE:
-        if (NS_IsMainThread()) {
-            return NS_NewDOMException(errCode, defaultException, _exc);
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // No provider so we'll return the default exception
-    *_exc = defaultException;
-    NS_IF_ADDREF(*_exc);
-    return NS_OK;
-}
-
-// thread management
-/*static*/ void nsExceptionService::AddThread(nsExceptionManager *thread)
-{
-    MutexAutoLock lock(*sLock);
-    thread->mNextThread = firstThread;
-    firstThread = thread;
-    NS_ADDREF(thread);
-}
-
-/*static*/ void nsExceptionService::DoDropThread(nsExceptionManager *thread)
-{
-    nsExceptionManager **emp = &firstThread;
-    while (*emp != thread) {
-        NS_ABORT_IF_FALSE(*emp, "Could not find the thread to drop!");
-        emp = &(*emp)->mNextThread;
-    }
-    *emp = thread->mNextThread;
-    NS_RELEASE(thread);
-}
-
-/*static*/ void nsExceptionService::DropThread(nsExceptionManager *thread)
-{
-    MutexAutoLock lock(*sLock);
-    DoDropThread(thread);
-}
-
-/*static*/ void nsExceptionService::DropAllThreads()
-{
-    MutexAutoLock lock(*sLock);
-    while (firstThread)
-        DoDropThread(firstThread);
-}
deleted file mode 100644
--- a/xpcom/base/nsExceptionService.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsExceptionService_h__
-#define nsExceptionService_h__
-
-#include "mozilla/Atomics.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/Mutex.h"
-
-#include "nsIException.h"
-#include "nsIExceptionService.h"
-#include "nsIObserverService.h"
-#include "nsHashtable.h"
-#include "nsIObserver.h"
-
-class nsExceptionManager;
-
-/** Exception Service definition **/
-class nsExceptionService MOZ_FINAL : public nsIExceptionService, public nsIObserver
-{
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIEXCEPTIONSERVICE
-  NS_DECL_NSIEXCEPTIONMANAGER
-  NS_DECL_NSIOBSERVER
-
-  nsExceptionService();
-
-  /* additional members */
-  nsresult DoGetExceptionFromProvider(nsresult errCode,
-                                      nsIException *defaultException,
-                                      nsIException **_richError);
-  void Shutdown();
-
-
-  /* thread management and cleanup */
-  static void AddThread(nsExceptionManager *);
-  static void DropThread(nsExceptionManager *);
-  static void DoDropThread(nsExceptionManager *thread);
-
-  static void DropAllThreads();
-  static nsExceptionManager *firstThread;
-
-  /* Protects the thread list. */
-  static mozilla::Mutex* sLock;
-
-  static unsigned tlsIndex;
-  static void ThreadDestruct( void *data );
-#ifdef DEBUG
-  static mozilla::Atomic<int32_t> totalInstances;
-#endif
-
-private:
-  ~nsExceptionService();
-};
-
-
-#endif // nsExceptionService_h__
deleted file mode 100644
--- a/xpcom/base/nsIExceptionService.idl
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-#include "nsIException.idl"
-
-// A ScriptErrorManager for a single thread.  These objects
-// are _not_ thread-safe.  Use the ScriptErrorService
-// to get a script error manager for your current thread.
-[scriptable, uuid(efc9d00b-231c-4feb-852c-ac017266a415)]
-interface nsIExceptionManager : nsISupports
-{
-    /** Sets (or clears with nullptr) the current error on the this thread. */
-    void setCurrentException( in nsIException error);
-
-    /** Gets the current error for the current thread, or NULL if no error */
-     nsIException getCurrentException();
-
-    /** Gets an exception from a registered exception provider..
-        This has no effect on the "current exception" */
-    nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException);
-};
-
-
-// The Exception Service.  Allows you to get an set exceptions in a thread
-// safe manner, or to get an ExceptionManager for your specific thread.
-[scriptable, uuid(8f9ccabb-a68b-43e3-b570-dd8c3179d2fb)]
-interface nsIExceptionService : nsIExceptionManager
-{
-    /** Obtains an exception manager for the current thread. */
-    readonly attribute nsIExceptionManager currentExceptionManager;
-};
-
-
-%{ C++
-// {35A88F54-F267-4414-92A7-191F6454AB52}
-#define NS_EXCEPTIONSERVICE_CID \
-{ 0x35a88f54, 0xf267, 0x4414, { 0x92, 0xa7, 0x19, 0x1f, 0x64, 0x54, 0xab, 0x52 } }
-#define NS_EXCEPTIONSERVICE_CONTRACTID "@mozilla.org/exceptionservice;1"
-%}
--- a/xpcom/build/XPCOM.h
+++ b/xpcom/build/XPCOM.h
@@ -68,17 +68,16 @@
 #include "nsIConsoleMessage.h"
 #include "nsIConsoleService.h"
 #include "nsIDebug.h"
 #include "nsIDirectoryEnumerator.h"
 #include "nsIEnvironment.h"
 #include "nsIErrorService.h"
 #include "nsIEventTarget.h"
 #include "nsIException.h"
-#include "nsIExceptionService.h"
 #include "nsIFactory.h"
 #include "nsIFile.h"
 #include "nsIHashable.h"
 #include "nsIINIParser.h"
 #include "nsIInputStream.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsILineInputStream.h"
 #include "nsIMemory.h"
--- a/xpcom/build/XPCOMModule.inc
+++ b/xpcom/build/XPCOMModule.inc
@@ -14,17 +14,16 @@
 
     COMPONENT(PROPERTIES, nsPropertiesConstructor)
 
     COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create)
 
     COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create)
     COMPONENT(ARRAY, nsArray::XPCOMConstructor)
     COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor)
-    COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor)
     COMPONENT(ATOMSERVICE, nsAtomServiceConstructor)
     COMPONENT(OBSERVERSERVICE, nsObserverService::Create)
 #ifdef MOZ_VISUAL_EVENT_TRACER
     COMPONENT(VISUALEVENTTRACER, VisualEventTracerConstructor)
 #endif
 
     COMPONENT(TIMER, nsTimerImplConstructor)
 
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -32,17 +32,16 @@
 #include "nsTraceRefcntImpl.h"
 #include "nsErrorService.h"
 
 #include "nsSupportsArray.h"
 #include "nsArray.h"
 #include "nsINIParserImpl.h"
 #include "nsSupportsPrimitives.h"
 #include "nsConsoleService.h"
-#include "nsExceptionService.h"
 
 #include "nsComponentManager.h"
 #include "nsCategoryManagerUtils.h"
 #include "nsIServiceManager.h"
 
 #include "nsThreadManager.h"
 #include "nsThreadPool.h"
 
@@ -176,17 +175,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupport
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64Impl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloatImpl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDoubleImpl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsConsoleService, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStorageStream)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsVersionComparatorImpl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableBase64Encoder)
 #ifdef MOZ_VISUAL_EVENT_TRACER
 NS_GENERIC_FACTORY_CONSTRUCTOR(VisualEventTracer)