Bug 911258: Part 5 - Use the unified exception handling mechanism on workers. r=bz
authorKyle Huey <khuey@kylehuey.com>
Sun, 08 Sep 2013 20:29:21 -0700
changeset 146113 4127ebc547fdf569b326ab0fdb0e7fca94086fc2
parent 146112 3f4223fab461f9a4e5b4fe646db5a0625cedd31e
child 146114 9846f07d5867f66d282c790d9f5adc8bce622424
push id25240
push useremorley@mozilla.com
push dateMon, 09 Sep 2013 12:09:06 +0000
treeherdermozilla-central@9846f07d5867 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs911258
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
Bug 911258: Part 5 - Use the unified exception handling mechanism on workers. r=bz
content/base/src/Element.cpp
content/base/src/Makefile.in
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsINode.cpp
content/base/src/nsObjectLoadingContent.cpp
dom/base/DOMException.cpp
dom/base/DOMException.h
dom/base/Navigator.cpp
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/bindings/Exceptions.cpp
dom/bindings/Exceptions.h
dom/workers/Exceptions.cpp
dom/workers/Exceptions.h
dom/workers/File.cpp
dom/workers/RuntimeService.cpp
dom/workers/ScriptLoader.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/WorkerScope.cpp
dom/workers/XMLHttpRequest.cpp
dom/workers/moz.build
js/xpconnect/src/nsXPConnect.cpp
xpcom/base/CycleCollectedJSRuntime.h
--- 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/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/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/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/dom/base/DOMException.cpp
+++ b/dom/base/DOMException.cpp
@@ -4,16 +4,17 @@
  * 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"
@@ -194,18 +195,17 @@ Exception::Exception(const char *aMessag
         do_CreateInstance(XPC_EXCEPTION_CONTRACTID);
     sEverMadeOneFromFactory = true;
   }
 
   nsCOMPtr<nsIStackFrame> location;
   if (aLocation) {
     location = aLocation;
   } else {
-    nsXPConnect* xpc = nsXPConnect::XPConnect();
-    xpc->GetCurrentJSStack(getter_AddRefs(location));
+    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) {
@@ -264,17 +264,17 @@ Exception::~Exception()
 
 bool
 Exception::StealJSVal(JS::Value* aVp)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mHoldingJSVal) {
     *aVp = mThrownJSVal;
-    mThrownJSVal = JSVAL_NULL;
+    mThrownJSVal.setNull();
 
     mozilla::DropJSObjects(this);
     mHoldingJSVal = false;
     return true;
   }
 
   return false;
 }
--- a/dom/base/DOMException.h
+++ b/dom/base/DOMException.h
@@ -1,16 +1,17 @@
 /* -*- 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"
@@ -27,25 +28,25 @@ class nsString;
 nsresult
 NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
                                    const char** aMessage,
                                    uint16_t* aCode = nullptr);
 
 namespace mozilla {
 namespace dom {
 
-#define MOZILLA_DOM_EXCEPTION_IID \
+#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_DOM_EXCEPTION_IID)
+  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
@@ -105,17 +106,17 @@ protected:
 
   bool mHoldingJSVal;
   JS::Heap<JS::Value> mThrownJSVal;
 
 private:
   static bool sEverMadeOneFromFactory;
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(Exception, MOZILLA_DOM_EXCEPTION_IID)
+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);
 
--- 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/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;
 }
@@ -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
@@ -315,16 +315,17 @@ DOMInterfaces = {
     'skipGen': True
 }],
 
 'DocumentFragment': {
     'resultNotAddRefed': [ 'querySelector' ]
 },
 
 'DOMException': {
+    'wantsQI': False,
     'binaryNames': {
         'message': 'messageMoz',
     },
 },
 
 'DOMSettableTokenList': {
     'nativeType': 'nsDOMSettableTokenList',
 },
@@ -394,19 +395,20 @@ DOMInterfaces = {
 },
 {
     'workers': True,
     'concrete': False
 }],
 
 'Exception': {
     'headerFile': 'mozilla/dom/DOMException.h',
+    'wantsQI': False,
     'binaryNames': {
         'message': 'messageMoz',
-    }
+    },
 },
 
 'FileHandle': {
     'nativeType': 'mozilla::dom::file::FileHandle'
 },
 
 'FileList': {
     'nativeType': 'nsDOMFileList',
--- 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')]
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -7,18 +7,20 @@
 
 #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()
 {
@@ -46,17 +48,17 @@ ThrowExceptionObject(JSContext* aCx, nsI
   if (exception) {
     return ThrowExceptionObject(aCx, exception);
   }
 
   // We only have an nsIException (probably an XPCWrappedJS).  Fall back on old
   // wrapping.
   MOZ_ASSERT(NS_IsMainThread());
 
-  JS::RootedObject glob(aCx, JS::CurrentGlobalOrNull(aCx));
+  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));
@@ -72,104 +74,131 @@ ThrowExceptionObject(JSContext* aCx, nsI
   JS_SetPendingException(aCx, OBJECT_TO_JSVAL(obj));
 
   return true;
 }
 
 bool
 ThrowExceptionObject(JSContext* aCx, Exception* aException)
 {
-  JS::RootedValue thrown(aCx);
+  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::RootedObject glob(aCx, JS::CurrentGlobalOrNull(aCx));
+  JS::Rooted<JSObject*> glob(aCx, JS::CurrentGlobalOrNull(aCx));
   if (!glob) {
     return false;
   }
 
-  JS::RootedValue val(aCx);
-  if (!mozilla::dom::WrapNewBindingObject(aCx, glob, aException, &val)) {
+  if (!WrapNewBindingObject(aCx, glob, aException, &thrown)) {
     return false;
   }
 
-  JS_SetPendingException(aCx, val);
+  JS_SetPendingException(aCx, thrown);
   return true;
 }
 
-void
-Throw(JSContext* cx, nsresult rv, const char* sz)
+bool
+Throw(JSContext* aCx, nsresult aRv, const char* aMessage)
 {
-  bool success = false;
-
-  if (JS_IsExceptionPending(cx)) {
+  if (JS_IsExceptionPending(aCx)) {
     // Don't clobber the existing exception.
-    return;
-  }
-
-  /* no need to set an expection if the security manager already has */
-  if (rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO && JS_IsExceptionPending(cx)) {
-    // This should only ever happen on the main thread.
-    MOZ_ASSERT(NS_IsMainThread());
-    return;
+    return false;
   }
 
   CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
   nsCOMPtr<nsIException> existingException = runtime->GetPendingException();
   if (existingException) {
     nsresult nr;
     if (NS_SUCCEEDED(existingException->GetResult(&nr)) && 
-        rv == nr) {
+        aRv == nr) {
       // Just reuse the existing exception.
-      return;
+      return false;
     }
   }
 
   nsRefPtr<Exception> finalException;
 
   // Do we use DOM exceptions for this error code?
-  switch (NS_ERROR_GET_MODULE(rv)) {
+  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:
-    if (NS_IsMainThread()) {
-      finalException = DOMException::Create(rv);
-    }
+    finalException = DOMException::Create(aRv);
     break;
 
   default:
       break;
   }
 
   // If not, use the default.
-  if (finalException == nullptr) {
-    finalException = new Exception(sz, rv, nullptr, nullptr, nullptr);
+  if (!finalException) {
+    finalException = new Exception(aMessage, aRv, nullptr, nullptr, nullptr);
   }
 
   MOZ_ASSERT(finalException);
-  success = ThrowExceptionObject(cx, finalException);
-  // If we weren't able to throw an exception we're
-  // most likely out of memory
-  if (!success) {
-    JS_ReportOutOfMemory(cx);
+  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
@@ -296,17 +325,17 @@ NS_IMETHODIMP JSStackFrame::GetCaller(ns
 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) + 6 /* space for lineno */;
+            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>
@@ -346,17 +375,17 @@ JSStackFrame::CreateStack(JSContext* cx)
             self->mFunname[length] = '\0';
           }
         }
       }
     }
 
     nsRefPtr<JSStackFrame> frame = new JSStackFrame();
     self->mCaller = frame;
-    self = frame.forget();
+    self.swap(frame);
   }
 
   JS::FreeStackDescription(cx, desc);
 
   return first.forget();
 }
 
 /* static */ already_AddRefed<nsIStackFrame>
--- a/dom/bindings/Exceptions.h
+++ b/dom/bindings/Exceptions.h
@@ -16,25 +16,28 @@ class nsIStackFrame;
 template <class T>
 class already_AddRefed;
 
 namespace mozilla {
 namespace dom {
 
 class Exception;
 
-void
-Throw(JSContext* cx, nsresult rv, const char* sz);
+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,
deleted file mode 100644
--- a/dom/workers/Exceptions.cpp
+++ /dev/null
@@ -1,283 +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 "nsTraceRefcnt.h"
-
-#include "WorkerInlines.h"
-
-nsresult
-NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
-                                   const char** aMessage,
-                                   uint16_t* aCode = nullptr);
-
-#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!");
+  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,16 +7,17 @@
 #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"
@@ -30,17 +31,16 @@
 #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"
@@ -1048,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/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -874,35 +874,20 @@ nsXPConnect::CreateStackFrameLocation(ui
     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 = exceptions::CreateStack(cx);
-        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/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -200,18 +200,17 @@ public:
   JSRuntime* Runtime() const
   {
     MOZ_ASSERT(mJSRuntime);
     return mJSRuntime;
   }
 
   // Get the current thread's CycleCollectedJSRuntime.  Returns null if there
   // isn't one.
-  static CycleCollectedJSRuntime*
-  Get();
+  static CycleCollectedJSRuntime* Get();
 
 private:
   JSGCThingParticipant mGCThingCycleCollectorGlobal;
 
   JSZoneParticipant mJSZoneCycleCollectorGlobal;
 
   JSRuntime* mJSRuntime;