Bug 911258: Part 3 - Convert exceptions to WebIDL. r=bz

This commit is contained in:
Kyle Huey 2013-09-08 20:28:49 -07:00
parent af632a6a4e
commit bf2b356316
14 changed files with 467 additions and 310 deletions

View File

@ -15,9 +15,10 @@
#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 */
@ -125,53 +126,35 @@ NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
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
@ -192,122 +175,6 @@ nsDOMException::GetCode(uint16_t* aCode)
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)
{
@ -352,15 +219,20 @@ nsDOMException::ToString(char **aReturn)
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)
{
mResult = aNSResult;
mName = aName;
mMessage = aMessage;
mCode = aCode;
mInner = aDefaultException;
return NS_OK;
CopyUTF8toUTF16(mName, retval);
}
void
nsDOMException::GetMessageMoz(nsString& retval)
{
CopyUTF8toUTF16(mMessage, retval);
}
JSObject*
nsDOMException::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return DOMExceptionBinding::Wrap(aCx, aScope, this);
}

View File

@ -3,15 +3,65 @@
* 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

View File

@ -319,6 +319,13 @@ DOMInterfaces = {
'resultNotAddRefed': [ 'querySelector' ]
},
'DOMException': {
'nativeType': 'nsDOMException',
'binaryNames': {
'message': 'messageMoz',
},
},
'DOMSettableTokenList': {
'nativeType': 'nsDOMSettableTokenList',
},
@ -391,6 +398,14 @@ DOMInterfaces = {
'concrete': False
}],
'Exception': {
'nativeType': 'nsXPCException',
'headerFile': 'xpcprivate.h',
'binaryNames': {
'message': 'messageMoz',
}
},
'FileHandle': {
'nativeType': 'mozilla::dom::file::FileHandle'
},
@ -1812,6 +1827,8 @@ addExternalIface('Principal', nativeType='nsIPrincipal',
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')

View File

@ -6,7 +6,6 @@
#include "IDBEvents.h"
#include "nsDOMException.h"
#include "nsJSON.h"
#include "nsThreadUtils.h"

View File

@ -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;

View File

@ -69,6 +69,7 @@ webidl_files = \
DocumentType.webidl \
DOMCursor.webidl \
DOMError.webidl \
DOMException.webidl \
DOMImplementation.webidl \
DOMMMIError.webidl \
DOMParser.webidl \

View File

@ -9,11 +9,15 @@
#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)

View File

@ -39,6 +39,7 @@
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsDOMClassInfoID.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/DOMExceptionBinding.h"
using namespace mozilla;
using namespace JS;
@ -1956,9 +1957,9 @@ nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
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);
@ -1983,9 +1984,14 @@ nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper,
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;
}

View File

@ -1080,9 +1080,9 @@ XPCConvert::ConstructException(nsresult rv, const char* message,
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);
@ -1090,7 +1090,7 @@ XPCConvert::ConstructException(nsresult rv, const char* message,
if (sz)
JS_smprintf_free(sz);
return res;
return NS_OK;
}
/********************************/

View File

@ -9,7 +9,10 @@
#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
@ -85,18 +88,96 @@ nsXPCException::GetNSResultCount()
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_ADDREF(nsXPCException)
NS_IMPL_RELEASE(nsXPCException)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXPCException)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXPCException)
NS_IMPL_CYCLE_COLLECTION_CLASS(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),
@ -107,13 +188,10 @@ nsXPCException::nsXPCException()
mLineNumber(0),
mInner(nullptr),
mInitialized(false)
{
MOZ_COUNT_CTOR(nsXPCException);
}
{ }
nsXPCException::~nsXPCException()
{
MOZ_COUNT_DTOR(nsXPCException);
Reset();
}
@ -366,79 +444,101 @@ nsXPCException::ToString(char **_retval)
return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
bool nsXPCException::sEverMadeOneFromFactory = false;
// static
nsresult
nsXPCException::NewException(const char *aMessage,
nsresult aResult,
nsIStackFrame *aLocation,
nsISupports *aData,
nsIException** exceptn)
JSObject*
nsXPCException::WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
{
// A little hack... The nsIGenericModule nsIClassInfo scheme relies on there
// having been at least one instance made via the factory. Otherwise, the
// shared factory/classinsance object never gets created and our QI getter
// for our instance's pointer to our nsIClassInfo will always return null.
// This is bad because it means that wrapped exceptions will never have a
// shared prototype. So... We force one to be created via the factory
// *once* and then go about our business.
if (!sEverMadeOneFromFactory) {
nsCOMPtr<nsIXPCException> e =
do_CreateInstance(XPC_EXCEPTION_CONTRACTID);
sEverMadeOneFromFactory = true;
}
nsresult rv;
nsXPCException* e = new nsXPCException();
if (e) {
NS_ADDREF(e);
nsIStackFrame* location;
if (aLocation) {
location = aLocation;
NS_ADDREF(location);
} else {
nsXPConnect* xpc = nsXPConnect::XPConnect();
rv = xpc->GetCurrentJSStack(&location);
if (NS_FAILED(rv)) {
NS_RELEASE(e);
return NS_ERROR_FAILURE;
}
// it is legal for there to be no active JS stack, if C++ code
// is operating on a JS-implemented interface pointer without
// having been called in turn by JS. This happens in the JS
// component loader, and will become more common as additional
// components are implemented in JS.
}
// We want to trim off any leading native 'dataless' frames
if (location)
while (1) {
uint32_t language;
int32_t lineNumber;
if (NS_FAILED(location->GetLanguage(&language)) ||
language == nsIProgrammingLanguage::JAVASCRIPT ||
NS_FAILED(location->GetLineNumber(&lineNumber)) ||
lineNumber) {
break;
}
nsCOMPtr<nsIStackFrame> caller;
if (NS_FAILED(location->GetCaller(getter_AddRefs(caller))) || !caller)
break;
NS_RELEASE(location);
caller->QueryInterface(NS_GET_IID(nsIStackFrame), (void **)&location);
}
// at this point we have non-null location with one extra addref,
// or no location at all
rv = e->Initialize(aMessage, aResult, nullptr, location, aData, nullptr);
NS_IF_RELEASE(location);
if (NS_FAILED(rv))
NS_RELEASE(e);
}
if (!e)
return NS_ERROR_FAILURE;
*exceptn = static_cast<nsIXPCException*>(e);
return NS_OK;
return ExceptionBinding::Wrap(cx, scope, this);
}
void
nsXPCException::GetMessageMoz(nsString& retval)
{
char* str = nullptr;
#ifdef DEBUG
DebugOnly<nsresult> rv =
#endif
GetMessageMoz(&str);
MOZ_ASSERT(NS_SUCCEEDED(rv));
CopyUTF8toUTF16(str, retval);
nsMemory::Free(str);
}
uint32_t
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);
}
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;
}
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();
}
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;

View File

@ -11,7 +11,6 @@ nsresult
xpcModuleCtor()
{
nsXPConnect::InitStatics();
nsXPCException::InitStatics();
XPCWrappedNativeScope::InitStatics();
return NS_OK;

View File

@ -11,6 +11,7 @@
#include "XPCWrapper.h"
#include "jsprf.h"
#include "nsDOMException.h"
#include "mozilla/dom/BindingUtils.h"
bool XPCThrower::sVerbose = true;
@ -55,7 +56,7 @@ XPCThrower::CheckForPendingException(nsresult result, JSContext *cx)
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;
}
@ -190,10 +191,7 @@ XPCThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz)
}
}
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)) {
@ -203,8 +201,7 @@ XPCThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz)
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;
@ -214,7 +211,7 @@ XPCThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz)
// If not, use the default.
if (finalException == nullptr) {
finalException = defaultException;
finalException = new nsXPCException(sz, rv, nullptr, nullptr, nullptr);
}
MOZ_ASSERT(finalException);
@ -244,39 +241,30 @@ IsCallerChrome(JSContext* cx)
// 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;
}
}
}

View File

@ -16,6 +16,8 @@
#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"
@ -261,21 +263,14 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
if (jsexception.isObject()) {
// XPConnect may have constructed an object to represent a
// C++ QI failure. See if that is the case.
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
using namespace mozilla::dom;
nsXPCException *e = nullptr;
UNWRAP_OBJECT(Exception, cx, &jsexception.toObject(), e);
nsXPConnect::XPConnect()->
GetWrappedNativeOfJSObject(cx,
&jsexception.toObject(),
getter_AddRefs(wrapper));
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.

View File

@ -2931,6 +2931,8 @@ private:
/***************************************************************************/
// code for throwing exceptions into JS
class nsXPCException;
class XPCThrower
{
public:
@ -2948,7 +2950,7 @@ 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;
@ -2977,21 +2979,18 @@ private:
/***************************************************************************/
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);
@ -3003,14 +3002,43 @@ public:
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;
@ -3023,6 +3051,7 @@ private:
nsAutoJSValHolder mThrownJSVal;
private:
static bool sEverMadeOneFromFactory;
};