mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-27 07:34:20 +00:00
Bug 911258: Part 3 - Convert exceptions to WebIDL. r=bz
This commit is contained in:
parent
af632a6a4e
commit
bf2b356316
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "IDBEvents.h"
|
||||
|
||||
#include "nsDOMException.h"
|
||||
#include "nsJSON.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
|
97
dom/webidl/DOMException.webidl
Normal file
97
dom/webidl/DOMException.webidl
Normal 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;
|
@ -69,6 +69,7 @@ webidl_files = \
|
||||
DocumentType.webidl \
|
||||
DOMCursor.webidl \
|
||||
DOMError.webidl \
|
||||
DOMException.webidl \
|
||||
DOMImplementation.webidl \
|
||||
DOMMMIError.webidl \
|
||||
DOMParser.webidl \
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
@ -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;
|
||||
|
@ -11,7 +11,6 @@ nsresult
|
||||
xpcModuleCtor()
|
||||
{
|
||||
nsXPConnect::InitStatics();
|
||||
nsXPCException::InitStatics();
|
||||
XPCWrappedNativeScope::InitStatics();
|
||||
|
||||
return NS_OK;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user