Bug 911258: Part 3 - Convert exceptions to WebIDL. r=bz
authorKyle Huey <khuey@kylehuey.com>
Sun, 08 Sep 2013 20:28:49 -0700
changeset 159938 16cf9da0d24282153c9ea53e49439dcb3aac194f
parent 159937 c04e927b631b053fc9e8d26840bac101869c550e
child 159939 3f4223fab461f9a4e5b4fe646db5a0625cedd31e
push id407
push userlsblakk@mozilla.com
push dateTue, 03 Dec 2013 03:32:50 +0000
treeherdermozilla-release@babf8c9ebc52 [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 3 - Convert exceptions to WebIDL. r=bz
dom/base/nsDOMException.cpp
dom/base/nsDOMException.h
dom/bindings/Bindings.conf
dom/indexedDB/IDBEvents.cpp
dom/webidl/DOMException.webidl
dom/webidl/WebIDL.mk
dom/workers/Exceptions.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCException.cpp
js/xpconnect/src/XPCModule.cpp
js/xpconnect/src/XPCThrower.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/xpcprivate.h
--- a/dom/base/nsDOMException.cpp
+++ b/dom/base/nsDOMException.cpp
@@ -10,19 +10,20 @@
 #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"
+#include "mozilla/dom/DOMExceptionBinding.h"
 
 using namespace mozilla;
+namespace DOMExceptionBinding = mozilla::dom::DOMExceptionBinding;
 
 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,
@@ -120,63 +121,45 @@ NS_GetNameAndMessageForDOMNSResult(nsres
       *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_IMPL_ADDREF_INHERITED(nsDOMException, nsXPCException)
+NS_IMPL_RELEASE_INHERITED(nsDOMException, nsXPCException)
 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
+NS_INTERFACE_MAP_END_INHERITING(nsXPCException)
 
-nsresult
-NS_NewDOMException(nsresult aNSResult, nsIException* aDefaultException,
-                   nsIException** aException)
+nsDOMException::nsDOMException(nsresult aRv, const char* aMessage,
+                               const char* aName, uint16_t aCode)
+  : nsXPCException(nullptr, aRv, nullptr, nullptr, nullptr),
+    mName(aName),
+    mMessage(aMessage),
+    mCode(aCode)
+{
+  SetIsDOMBinding();
+}
+
+already_AddRefed<nsDOMException>
+NS_NewDOMException(nsresult aNSResult)
 {
   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;
+  nsRefPtr<nsDOMException> inst =
+    new nsDOMException(aNSResult, message, name, code);
+  return inst.forget();
 }
 
 NS_IMETHODIMP
 nsDOMException::GetCode(uint16_t* aCode)
 {
   NS_ENSURE_ARG_POINTER(aCode);
   *aCode = mCode;
 
@@ -188,132 +171,16 @@ nsDOMException::GetCode(uint16_t* aCode)
       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[] =
@@ -347,20 +214,25 @@ nsDOMException::ToString(char **aReturn)
   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)
+void
+nsDOMException::GetName(nsString& retval)
+{
+  CopyUTF8toUTF16(mName, retval);
+}
+
+void
+nsDOMException::GetMessageMoz(nsString& retval)
 {
-  mResult = aNSResult;
-  mName = aName;
-  mMessage = aMessage;
-  mCode = aCode;
-  mInner = aDefaultException;
-  return NS_OK;
+  CopyUTF8toUTF16(mMessage, retval);
 }
+
+JSObject*
+nsDOMException::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return DOMExceptionBinding::Wrap(aCx, aScope, this);
+}
--- a/dom/base/nsDOMException.h
+++ b/dom/base/nsDOMException.h
@@ -1,17 +1,67 @@
 /* -*- 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/. */
 
+// We intentionally shadow non-virtual methods, but gcc gets confused.
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Woverloaded-virtual"
+#endif
+
 #include "mozilla/NullPtr.h"
 #include "nsError.h"
-class nsIException;
+#include "nsIDOMDOMException.h"
+#include "nsIException.h"
+#include "nsCOMPtr.h"
+#include "xpcprivate.h"
+
+template<typename> class already_AddRefed;
+
+class nsDOMException : public nsXPCException,
+                       public nsIDOMDOMException
+{
+public:
+  nsDOMException(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);
+
+protected:
+
+  virtual ~nsDOMException() {}
+
+  // Intentionally shadow the nsXPCException version.
+  const char* mName;
+  const char* mMessage;
+
+  uint16_t mCode;
+};
 
 nsresult
 NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
                                    const char** aMessage,
                                    uint16_t* aCode = nullptr);
 
-nsresult
-NS_NewDOMException(nsresult aNSResult, nsIException* aDefaultException,
-                   nsIException** aException);
+already_AddRefed<nsDOMException>
+NS_NewDOMException(nsresult aNSResult);
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -314,16 +314,23 @@ DOMInterfaces = {
     'workers': True,
     'skipGen': True
 }],
 
 'DocumentFragment': {
     'resultNotAddRefed': [ 'querySelector' ]
 },
 
+'DOMException': {
+    'nativeType': 'nsDOMException',
+    'binaryNames': {
+        'message': 'messageMoz',
+    },
+},
+
 'DOMSettableTokenList': {
     'nativeType': 'nsDOMSettableTokenList',
 },
 
 'DOMStringMap': {
     'nativeType': 'nsDOMStringMap'
 },
 
@@ -386,16 +393,24 @@ DOMInterfaces = {
     'concrete': False,
     'jsImplParent': 'nsDOMEventTargetHelper'
 },
 {
     'workers': True,
     'concrete': False
 }],
 
+'Exception': {
+    'nativeType': 'nsXPCException',
+    'headerFile': 'xpcprivate.h',
+    '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/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;
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 \
--- a/dom/workers/Exceptions.cpp
+++ b/dom/workers/Exceptions.cpp
@@ -4,21 +4,25 @@
  * 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"
 
+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
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -34,16 +34,17 @@
 #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/DOMExceptionBinding.h"
 
 using namespace mozilla;
 using namespace JS;
 using namespace js;
 using namespace xpc;
 
 /***************************************************************************/
 // stuff used by all
@@ -1951,19 +1952,19 @@ nsXPCComponents_Exception::CallOrConstru
         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));
+    nsCOMPtr<nsIException> e = new nsXPCException(parser.eMsg, parser.eResult,
+                                                  nullptr, parser.eStack,
+                                                  parser.eData);
     if (!e)
         return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     RootedObject newObj(cx);
 
     if (NS_FAILED(xpc->WrapNative(cx, obj, e, NS_GET_IID(nsIXPCException),
                                   getter_AddRefs(holder))) || !holder ||
@@ -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) {
+        nsXPCException* 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
@@ -1075,27 +1075,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);
+    nsCOMPtr<nsIException> e = new nsXPCException(msg, rv, nullptr, nullptr, data);
 
-    if (NS_SUCCEEDED(res) && cx && jsExceptionPtr && *exceptn) {
+    if (cx && jsExceptionPtr && *exceptn) {
         nsCOMPtr<nsIXPCException> xpcEx = do_QueryInterface(*exceptn);
         if (xpcEx)
             xpcEx->StowJSVal(cx, *jsExceptionPtr);
     }
 
     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
@@ -4,17 +4,20 @@
  * 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"
+#include "mozilla/dom/DOMExceptionBinding.h"
+
+namespace ExceptionBinding = mozilla::dom::ExceptionBinding;
+using mozilla::DebugOnly;
 
 /***************************************************************************/
 /* 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.
@@ -80,45 +83,120 @@ nsXPCException::GetNSResultCount()
 {
     return RESULT_COUNT;
 }
 
 /***************************************************************************/
 
 NS_IMPL_CLASSINFO(nsXPCException, NULL, nsIClassInfo::DOM_OBJECT,
                   NS_XPCEXCEPTION_CID)
-NS_INTERFACE_MAP_BEGIN(nsXPCException)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(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_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXPCException)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXPCException)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXPCException)
 
-NS_IMPL_ADDREF(nsXPCException)
-NS_IMPL_RELEASE(nsXPCException)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXPCException)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsXPCException)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXPCException)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CI_INTERFACE_GETTER1(nsXPCException, nsIXPCException)
 
+nsXPCException::nsXPCException(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)
+{
+    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;
+    }
+
+    nsIStackFrame* location;
+    if (aLocation) {
+        location = aLocation;
+        NS_ADDREF(location);
+    } else {
+        nsXPConnect* xpc = nsXPConnect::XPConnect();
+        xpc->GetCurrentJSStack(&location);
+        // 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);
+        }
+    }
+
+    Initialize(aMessage, aResult, aName, location, aData, nullptr);
+    NS_IF_RELEASE(location);
+}
+
 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()) {
@@ -361,84 +439,106 @@ nsXPCException::ToString(char **_retval)
         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;
+JSObject*
+nsXPCException::WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
+{
+    return ExceptionBinding::Wrap(cx, scope, this);
+}
 
-// static
-nsresult
-nsXPCException::NewException(const char *aMessage,
-                             nsresult aResult,
-                             nsIStackFrame *aLocation,
-                             nsISupports *aData,
-                             nsIException** exceptn)
+void
+nsXPCException::GetMessageMoz(nsString& retval)
 {
-    // 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;
-    }
+    char* str = nullptr;
+#ifdef DEBUG
+    DebugOnly<nsresult> rv = 
+#endif
+    GetMessageMoz(&str);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    CopyUTF8toUTF16(str, retval);
+    nsMemory::Free(str);
+}
 
-    nsresult rv;
-    nsXPCException* e = new nsXPCException();
-    if (e) {
-        NS_ADDREF(e);
+uint32_t
+nsXPCException::Result() const
+{
+    return (uint32_t)mResult;
+}
+
+void
+nsXPCException::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);
+}
 
-        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);
-    }
+void
+nsXPCException::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
+nsXPCException::LineNumber() const
+{
+    return mLineNumber;
+}
+
+uint32_t
+nsXPCException::ColumnNumber() const
+{
+    return 0;
+}
 
-    if (!e)
-        return NS_ERROR_FAILURE;
+already_AddRefed<nsIStackFrame>
+nsXPCException::GetLocation() const
+{
+    nsCOMPtr<nsIStackFrame> location = mLocation;
+    return location.forget();
+}
+
+already_AddRefed<nsISupports>
+nsXPCException::GetInner() const
+{
+    nsCOMPtr<nsISupports> inner = mInner;
+    return inner.forget();
+}
 
-    *exceptn = static_cast<nsIXPCException*>(e);
-    return NS_OK;
+already_AddRefed<nsISupports>
+nsXPCException::GetData() const
+{
+    nsCOMPtr<nsISupports> data = mData;
+    return data.forget();
 }
+
+void
+nsXPCException::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);
+}
+
+bool nsXPCException::sEverMadeOneFromFactory = false;
--- 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/XPCThrower.cpp
+++ b/js/xpconnect/src/XPCThrower.cpp
@@ -6,16 +6,17 @@
 
 /* Code for throwing errors into JavaScript. */
 
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "XPCWrapper.h"
 #include "jsprf.h"
 #include "nsDOMException.h"
+#include "mozilla/dom/BindingUtils.h"
 
 bool XPCThrower::sVerbose = true;
 
 // static
 void
 XPCThrower::Throw(nsresult rv, JSContext* cx)
 {
     const char* format;
@@ -50,17 +51,17 @@ XPCThrower::CheckForPendingException(nsr
     if (!e)
         return false;
     XPCJSRuntime::Get()->SetPendingException(nullptr);
 
     nsresult e_result;
     if (NS_FAILED(e->GetResult(&e_result)) || e_result != result)
         return false;
 
-    if (!ThrowExceptionObject(cx, e))
+    if (!ThrowExceptionObject(cx, static_cast<nsXPCException*>(e.get())))
         JS_ReportOutOfMemory(cx);
     return true;
 }
 
 // static
 void
 XPCThrower::Throw(nsresult rv, XPCCallContext& ccx)
 {
@@ -185,41 +186,37 @@ XPCThrower::BuildAndThrowException(JSCon
         nsresult nr;
         if (NS_SUCCEEDED(existingException->GetResult(&nr)) && 
             rv == nr) {
             // Just reuse the existing exception.
             return;
         }
     }
 
-    nsCOMPtr<nsIException> finalException;
-    nsCOMPtr<nsIException> defaultException;
-    nsXPCException::NewException(sz, rv, nullptr, nullptr,
-                                 getter_AddRefs(defaultException));
+    nsRefPtr<nsXPCException> finalException;
 
     // Do we use DOM exceptions for this error code?
     switch (NS_ERROR_GET_MODULE(rv)) {
     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()) {
-            NS_NewDOMException(rv, defaultException,
-                               getter_AddRefs(finalException));
+            finalException = NS_NewDOMException(rv);
         }
         break;
 
     default:
         break;
     }
 
     // If not, use the default.
     if (finalException == nullptr) {
-        finalException = defaultException;
+        finalException = new nsXPCException(sz, rv, 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);
@@ -239,46 +236,37 @@ IsCallerChrome(JSContext* cx)
 
     bool isChrome;
     rv = secMan->SubjectPrincipalIsSystem(&isChrome);
     return NS_SUCCEEDED(rv) && isChrome;
 }
 
 // static
 bool
-XPCThrower::ThrowExceptionObject(JSContext* cx, nsIException* e)
+XPCThrower::ThrowExceptionObject(JSContext* cx, nsXPCException* 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()))) {
+            NS_SUCCEEDED(e->StealJSVal(thrown.address()))) {
             if (!JS_WrapValue(cx, thrown.address()))
                 return false;
             JS_SetPendingException(cx, thrown);
             success = true;
-        } else if ((xpc = nsXPConnect::XPConnect())) {
+        } else {
             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;
-                }
+            JS::RootedValue val(cx);
+            if (mozilla::dom::WrapNewBindingObject(cx, glob, e, &val)) {
+                JS_SetPendingException(cx, val);
+                success = true;
             }
         }
     }
     return success;
 }
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -11,16 +11,18 @@
 #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/DOMExceptionBinding.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 
 using namespace xpc;
 using namespace JS;
 
 NS_IMPL_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
@@ -256,31 +258,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;
+                    nsXPCException *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/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2926,16 +2926,18 @@ 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)
@@ -2943,17 +2945,17 @@ public:
 
     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);
+    static bool ThrowExceptionObject(JSContext* cx, nsXPCException* e);
 
 private:
     static bool sVerbose;
 };
 
 
 /***************************************************************************/
 
@@ -2972,62 +2974,89 @@ public:
                              nsIStackFrame** stack);
 private:
     XPCJSStack();   // not implemented
 };
 
 /***************************************************************************/
 
 class nsXPCException :
-            public nsIXPCException
+            public nsIXPCException,
+            public nsWrapperCache
 {
 public:
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCEXCEPTION_CID)
 
-    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXPCException)
+
+    NS_DECL_CYCLE_COLLECTING_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(const char *aMessage,
+                   nsresult aResult,
+                   const char *aName,
+                   nsIStackFrame *aLocation,
+                   nsISupports *aData);
+    // XPCOM factory ctor.
     nsXPCException();
     virtual ~nsXPCException();
 
-    static void InitStatics() { sEverMadeOneFromFactory = false; }
+    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);
 
 protected:
     void Reset();
-private:
+
     char*           mMessage;
     nsresult        mResult;
     char*           mName;
     nsIStackFrame*  mLocation;
     nsISupports*    mData;
     char*           mFilename;
     int             mLineNumber;
     nsIException*   mInner;
     bool            mInitialized;
 
     nsAutoJSValHolder mThrownJSVal;
 
+private:
     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.
 */