mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 911258: Part 4 - Refactor exception implementations. r=bz
This commit is contained in:
parent
025c388bda
commit
6a6c67829f
@ -6,9 +6,14 @@
|
||||
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/DOMErrorBinding.h"
|
||||
#include "nsDOMException.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
// Implemented in DOMException.cpp
|
||||
nsresult
|
||||
NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
|
||||
const char** aMessage,
|
||||
uint16_t* aCode = nullptr);
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
708
dom/base/DOMException.cpp
Normal file
708
dom/base/DOMException.cpp
Normal file
@ -0,0 +1,708 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsprf.h"
|
||||
#include "js/OldDebugAPI.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionHoldDrop.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDOMException.h"
|
||||
#include "nsIException.h"
|
||||
#include "nsMemory.h"
|
||||
#include "prprf.h"
|
||||
#include "xpcprivate.h"
|
||||
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
enum DOM4ErrorTypeCodeMap {
|
||||
/* DOM4 errors from http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#domexception */
|
||||
IndexSizeError = nsIDOMDOMException::INDEX_SIZE_ERR,
|
||||
HierarchyRequestError = nsIDOMDOMException::HIERARCHY_REQUEST_ERR,
|
||||
WrongDocumentError = nsIDOMDOMException::WRONG_DOCUMENT_ERR,
|
||||
InvalidCharacterError = nsIDOMDOMException::INVALID_CHARACTER_ERR,
|
||||
NoModificationAllowedError = nsIDOMDOMException::NO_MODIFICATION_ALLOWED_ERR,
|
||||
NotFoundError = nsIDOMDOMException::NOT_FOUND_ERR,
|
||||
NotSupportedError = nsIDOMDOMException::NOT_SUPPORTED_ERR,
|
||||
// Can't remove until setNamedItem is removed
|
||||
InUseAttributeError = nsIDOMDOMException::INUSE_ATTRIBUTE_ERR,
|
||||
InvalidStateError = nsIDOMDOMException::INVALID_STATE_ERR,
|
||||
SyntaxError = nsIDOMDOMException::SYNTAX_ERR,
|
||||
InvalidModificationError = nsIDOMDOMException::INVALID_MODIFICATION_ERR,
|
||||
NamespaceError = nsIDOMDOMException::NAMESPACE_ERR,
|
||||
InvalidAccessError = nsIDOMDOMException::INVALID_ACCESS_ERR,
|
||||
TypeMismatchError = nsIDOMDOMException::TYPE_MISMATCH_ERR,
|
||||
SecurityError = nsIDOMDOMException::SECURITY_ERR,
|
||||
NetworkError = nsIDOMDOMException::NETWORK_ERR,
|
||||
AbortError = nsIDOMDOMException::ABORT_ERR,
|
||||
URLMismatchError = nsIDOMDOMException::URL_MISMATCH_ERR,
|
||||
QuotaExceededError = nsIDOMDOMException::QUOTA_EXCEEDED_ERR,
|
||||
TimeoutError = nsIDOMDOMException::TIMEOUT_ERR,
|
||||
InvalidNodeTypeError = nsIDOMDOMException::INVALID_NODE_TYPE_ERR,
|
||||
DataCloneError = nsIDOMDOMException::DATA_CLONE_ERR,
|
||||
EncodingError = 0,
|
||||
|
||||
/* XXX Should be JavaScript native errors */
|
||||
TypeError = 0,
|
||||
RangeError = 0,
|
||||
|
||||
/* IndexedDB errors http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#exceptions */
|
||||
UnknownError = 0,
|
||||
ConstraintError = 0,
|
||||
DataError = 0,
|
||||
TransactionInactiveError = 0,
|
||||
ReadOnlyError = 0,
|
||||
VersionError = 0,
|
||||
|
||||
/* File API errors http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException */
|
||||
NotReadableError = 0,
|
||||
|
||||
/* FileHandle API errors */
|
||||
LockedFileInactiveError = 0,
|
||||
};
|
||||
|
||||
#define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message},
|
||||
#define DOM_MSG_DEF(val, message) {(val), NS_ERROR_GET_CODE(val), #val, message},
|
||||
|
||||
static const struct ResultStruct
|
||||
{
|
||||
nsresult mNSResult;
|
||||
uint16_t mCode;
|
||||
const char* mName;
|
||||
const char* mMessage;
|
||||
} sDOMErrorMsgMap[] = {
|
||||
#include "domerr.msg"
|
||||
};
|
||||
|
||||
#undef DOM4_MSG_DEF
|
||||
#undef DOM_MSG_DEF
|
||||
|
||||
static void
|
||||
NSResultToNameAndMessage(nsresult aNSResult,
|
||||
const char** aName,
|
||||
const char** aMessage,
|
||||
uint16_t* aCode)
|
||||
{
|
||||
*aName = nullptr;
|
||||
*aMessage = nullptr;
|
||||
*aCode = 0;
|
||||
for (uint32_t idx = 0; idx < ArrayLength(sDOMErrorMsgMap); idx++) {
|
||||
if (aNSResult == sDOMErrorMsgMap[idx].mNSResult) {
|
||||
*aName = sDOMErrorMsgMap[idx].mName;
|
||||
*aMessage = sDOMErrorMsgMap[idx].mMessage;
|
||||
*aCode = sDOMErrorMsgMap[idx].mCode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NS_WARNING("Huh, someone is throwing non-DOM errors using the DOM module!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
|
||||
const char** aMessage, uint16_t* aCode)
|
||||
{
|
||||
const char* name = nullptr;
|
||||
const char* message = nullptr;
|
||||
uint16_t code = 0;
|
||||
NSResultToNameAndMessage(aNSResult, &name, &message, &code);
|
||||
|
||||
if (name && message) {
|
||||
*aName = name;
|
||||
*aMessage = message;
|
||||
if (aCode) {
|
||||
*aCode = code;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
bool Exception::sEverMadeOneFromFactory = false;
|
||||
|
||||
NS_IMPL_CLASSINFO(Exception, nullptr, nsIClassInfo::DOM_OBJECT,
|
||||
NS_XPCEXCEPTION_CID)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Exception)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIException)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXPCException)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
|
||||
NS_IMPL_QUERY_CLASSINFO(Exception)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Exception)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Exception)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Exception)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Exception)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Exception)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mThrownJSVal);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Exception)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CI_INTERFACE_GETTER1(Exception, nsIXPCException)
|
||||
|
||||
Exception::Exception(const char *aMessage,
|
||||
nsresult aResult,
|
||||
const char *aName,
|
||||
nsIStackFrame *aLocation,
|
||||
nsISupports *aData)
|
||||
: mMessage(nullptr),
|
||||
mResult(NS_OK),
|
||||
mName(nullptr),
|
||||
mLocation(nullptr),
|
||||
mData(nullptr),
|
||||
mFilename(nullptr),
|
||||
mLineNumber(0),
|
||||
mInner(nullptr),
|
||||
mInitialized(false),
|
||||
mHoldingJSVal(false)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
|
||||
// A little hack... The nsIGenericModule nsIClassInfo scheme relies on there
|
||||
// having been at least one instance made via the factory. Otherwise, the
|
||||
// shared factory/classinsance object never gets created and our QI getter
|
||||
// for our instance's pointer to our nsIClassInfo will always return null.
|
||||
// This is bad because it means that wrapped exceptions will never have a
|
||||
// shared prototype. So... We force one to be created via the factory
|
||||
// *once* and then go about our business.
|
||||
if (!sEverMadeOneFromFactory) {
|
||||
nsCOMPtr<nsIXPCException> e =
|
||||
do_CreateInstance(XPC_EXCEPTION_CONTRACTID);
|
||||
sEverMadeOneFromFactory = true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStackFrame> location;
|
||||
if (aLocation) {
|
||||
location = aLocation;
|
||||
} else {
|
||||
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
||||
xpc->GetCurrentJSStack(getter_AddRefs(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;
|
||||
}
|
||||
location = caller;
|
||||
}
|
||||
}
|
||||
|
||||
Initialize(aMessage, aResult, aName, location, aData, nullptr);
|
||||
}
|
||||
|
||||
Exception::Exception()
|
||||
: mMessage(nullptr),
|
||||
mResult(NS_OK),
|
||||
mName(nullptr),
|
||||
mFilename(nullptr),
|
||||
mLineNumber(-1),
|
||||
mInitialized(false),
|
||||
mHoldingJSVal(false)
|
||||
{
|
||||
}
|
||||
|
||||
Exception::~Exception()
|
||||
{
|
||||
if (mMessage) {
|
||||
nsMemory::Free(mMessage);
|
||||
mMessage = nullptr;
|
||||
}
|
||||
if (mName) {
|
||||
nsMemory::Free(mName);
|
||||
mName = nullptr;
|
||||
}
|
||||
if (mFilename) {
|
||||
nsMemory::Free(mFilename);
|
||||
mFilename = nullptr;
|
||||
}
|
||||
|
||||
if (mHoldingJSVal) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Exception::StealJSVal(JS::Value* aVp)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mHoldingJSVal) {
|
||||
*aVp = mThrownJSVal;
|
||||
mThrownJSVal = JSVAL_NULL;
|
||||
|
||||
mozilla::DropJSObjects(this);
|
||||
mHoldingJSVal = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Exception::StowJSVal(JS::Value& aVp)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mThrownJSVal = aVp;
|
||||
if (!mHoldingJSVal) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
mHoldingJSVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* readonly attribute string message; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetMessageMoz(char** aMessage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aMessage);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (mMessage) {
|
||||
*aMessage =
|
||||
(char*) nsMemory::Clone(mMessage, sizeof(char)*(strlen(mMessage)+1));
|
||||
} else {
|
||||
*aMessage = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsresult result; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetResult(nsresult* aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
*aResult = mResult;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string name; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetName(char** aName)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aName);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
const char* name = mName;
|
||||
if (!name) {
|
||||
nsXPCException::NameAndFormatForNSResult(mResult, &name, nullptr);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
*aName = (char*) nsMemory::Clone(name, sizeof(char)*(strlen(name)+1));
|
||||
} else {
|
||||
*aName = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string filename; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetFilename(char** aFilename)
|
||||
{
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
XPC_STRING_GETTER_BODY(aFilename, mFilename);
|
||||
}
|
||||
|
||||
/* readonly attribute uint32_t lineNumber; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetLineNumber(uint32_t *aLineNumber)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLineNumber);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
*aLineNumber = mLineNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute uint32_t columnNumber; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetColumnNumber(uint32_t* aColumnNumber)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aColumnNumber);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
*aColumnNumber = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIStackFrame location; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetLocation(nsIStackFrame** aLocation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLocation);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsIStackFrame> location = mLocation;
|
||||
location.forget(aLocation);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsISupports data; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetData(nsISupports** aData)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aData);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsISupports> data = mData;
|
||||
data.forget(aData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIException inner; */
|
||||
NS_IMETHODIMP
|
||||
Exception::GetInner(nsIException** aException)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aException);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsIException> inner = mInner;
|
||||
inner.forget(aException);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string toString (); */
|
||||
NS_IMETHODIMP
|
||||
Exception::ToString(char **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
static const char defaultMsg[] = "<no message>";
|
||||
static const char defaultLocation[] = "<unknown>";
|
||||
static const char format[] =
|
||||
"[Exception... \"%s\" nsresult: \"0x%x (%s)\" location: \"%s\" data: %s]";
|
||||
|
||||
char* indicatedLocation = nullptr;
|
||||
|
||||
if (mLocation) {
|
||||
// we need to free this if it does not fail
|
||||
nsresult rv = mLocation->ToString(&indicatedLocation);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
const char* msg = mMessage ? mMessage : nullptr;
|
||||
const char* location = indicatedLocation ?
|
||||
indicatedLocation : defaultLocation;
|
||||
const char* resultName = mName;
|
||||
if (!resultName &&
|
||||
!nsXPCException::NameAndFormatForNSResult(mResult, &resultName,
|
||||
(!msg) ? &msg : nullptr)) {
|
||||
if (!msg) {
|
||||
msg = defaultMsg;
|
||||
}
|
||||
resultName = "<unknown>";
|
||||
}
|
||||
const char* data = mData ? "yes" : "no";
|
||||
|
||||
char* temp = JS_smprintf(format, msg, mResult, resultName, location, data);
|
||||
if (indicatedLocation) {
|
||||
nsMemory::Free(indicatedLocation);
|
||||
}
|
||||
|
||||
char* final = nullptr;
|
||||
if (temp) {
|
||||
final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1));
|
||||
JS_smprintf_free(temp);
|
||||
}
|
||||
|
||||
*_retval = final;
|
||||
return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* void initialize (in string aMessage, in nsresult aResult, in string aName, in nsIStackFrame aLocation, in nsISupports aData, in nsIException aInner); */
|
||||
NS_IMETHODIMP
|
||||
Exception::Initialize(const char *aMessage, nsresult aResult, const char *aName, nsIStackFrame *aLocation, nsISupports *aData, nsIException *aInner)
|
||||
{
|
||||
NS_ENSURE_FALSE(mInitialized, NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
if (aMessage) {
|
||||
mMessage =
|
||||
(char*) nsMemory::Clone(aMessage, sizeof(char)*(strlen(aMessage)+1));
|
||||
}
|
||||
|
||||
if (aName) {
|
||||
mName = (char*) nsMemory::Clone(aName, sizeof(char)*(strlen(aName)+1));
|
||||
}
|
||||
|
||||
mResult = aResult;
|
||||
|
||||
if (aLocation) {
|
||||
mLocation = aLocation;
|
||||
// For now, fill in our location details from our stack frame.
|
||||
// Later we may allow other locations?
|
||||
nsresult rc;
|
||||
if (NS_FAILED(rc = aLocation->GetFilename(&mFilename))) {
|
||||
return rc;
|
||||
}
|
||||
if (NS_FAILED(rc = aLocation->GetLineNumber(&mLineNumber))) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
nsresult rv;
|
||||
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
||||
rv = xpc->GetCurrentJSStack(getter_AddRefs(mLocation));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
mData = aData;
|
||||
mInner = aInner;
|
||||
|
||||
mInitialized = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Exception::WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
|
||||
{
|
||||
return ExceptionBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
void
|
||||
Exception::GetMessageMoz(nsString& retval)
|
||||
{
|
||||
char* str = nullptr;
|
||||
#ifdef DEBUG
|
||||
DebugOnly<nsresult> rv =
|
||||
#endif
|
||||
GetMessageMoz(&str);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
CopyUTF8toUTF16(str, retval);
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Exception::Result() const
|
||||
{
|
||||
return (uint32_t)mResult;
|
||||
}
|
||||
|
||||
void
|
||||
Exception::GetName(nsString& retval)
|
||||
{
|
||||
char* str = nullptr;
|
||||
#ifdef DEBUG
|
||||
DebugOnly<nsresult> rv =
|
||||
#endif
|
||||
GetName(&str);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
CopyUTF8toUTF16(str, retval);
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
|
||||
void
|
||||
Exception::GetFilename(nsString& retval)
|
||||
{
|
||||
char* str = nullptr;
|
||||
#ifdef DEBUG
|
||||
DebugOnly<nsresult> rv =
|
||||
#endif
|
||||
GetFilename(&str);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
CopyUTF8toUTF16(str, retval);
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Exception::LineNumber() const
|
||||
{
|
||||
return mLineNumber;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Exception::ColumnNumber() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIStackFrame>
|
||||
Exception::GetLocation() const
|
||||
{
|
||||
nsCOMPtr<nsIStackFrame> location = mLocation;
|
||||
return location.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports>
|
||||
Exception::GetInner() const
|
||||
{
|
||||
nsCOMPtr<nsIException> inner = mInner;
|
||||
return inner.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports>
|
||||
Exception::GetData() const
|
||||
{
|
||||
nsCOMPtr<nsISupports> data = mData;
|
||||
return data.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Exception::Stringify(nsString& retval)
|
||||
{
|
||||
char* str = nullptr;
|
||||
#ifdef DEBUG
|
||||
DebugOnly<nsresult> rv =
|
||||
#endif
|
||||
ToString(&str);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
CopyUTF8toUTF16(str, retval);
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMException, Exception)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMException, Exception)
|
||||
NS_INTERFACE_MAP_BEGIN(DOMException)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMDOMException)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Exception)
|
||||
|
||||
DOMException::DOMException(nsresult aRv, const char* aMessage,
|
||||
const char* aName, uint16_t aCode)
|
||||
: Exception(nullptr, aRv, nullptr, nullptr, nullptr),
|
||||
mName(aName),
|
||||
mMessage(aMessage),
|
||||
mCode(aCode)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DOMException::GetCode(uint16_t* aCode)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCode);
|
||||
*aCode = mCode;
|
||||
|
||||
// Warn only when the code was changed (other than DOM Core)
|
||||
// or the code is useless (zero)
|
||||
if (NS_ERROR_GET_MODULE(mResult) != NS_ERROR_MODULE_DOM || !mCode) {
|
||||
nsCOMPtr<nsIDocument> doc = nsContentUtils::GetDocumentFromCaller();
|
||||
if (doc) {
|
||||
doc->WarnOnceAbout(nsIDocument::eDOMExceptionCode);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DOMException::ToString(char **aReturn)
|
||||
{
|
||||
*aReturn = nullptr;
|
||||
|
||||
static const char defaultMsg[] = "<no message>";
|
||||
static const char defaultLocation[] = "<unknown>";
|
||||
static const char defaultName[] = "<unknown>";
|
||||
static const char format[] =
|
||||
"[Exception... \"%s\" code: \"%d\" nsresult: \"0x%x (%s)\" location: \"%s\"]";
|
||||
|
||||
nsAutoCString location;
|
||||
|
||||
if (mInner) {
|
||||
nsXPIDLCString filename;
|
||||
|
||||
mInner->GetFilename(getter_Copies(filename));
|
||||
|
||||
if (!filename.IsEmpty()) {
|
||||
uint32_t line_nr = 0;
|
||||
|
||||
mInner->GetLineNumber(&line_nr);
|
||||
|
||||
char *temp = PR_smprintf("%s Line: %d", filename.get(), line_nr);
|
||||
if (temp) {
|
||||
location.Assign(temp);
|
||||
PR_smprintf_free(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (location.IsEmpty()) {
|
||||
location = defaultLocation;
|
||||
}
|
||||
|
||||
const char* msg = mMessage ? mMessage : defaultMsg;
|
||||
const char* resultName = mName ? mName : defaultName;
|
||||
|
||||
*aReturn = PR_smprintf(format, msg, mCode, mResult, resultName,
|
||||
location.get());
|
||||
|
||||
return *aReturn ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
void
|
||||
DOMException::GetName(nsString& retval)
|
||||
{
|
||||
CopyUTF8toUTF16(mName, retval);
|
||||
}
|
||||
|
||||
void
|
||||
DOMException::GetMessageMoz(nsString& retval)
|
||||
{
|
||||
CopyUTF8toUTF16(mMessage, retval);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
DOMException::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return DOMExceptionBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
/* static */already_AddRefed<DOMException>
|
||||
DOMException::Create(nsresult aRv)
|
||||
{
|
||||
const char* name;
|
||||
const char* message;
|
||||
uint16_t code;
|
||||
NSResultToNameAndMessage(aRv, &name, &message, &code);
|
||||
nsRefPtr<DOMException> inst =
|
||||
new DOMException(aRv, message, name, code);
|
||||
return inst.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
161
dom/base/DOMException.h
Normal file
161
dom/base/DOMException.h
Normal file
@ -0,0 +1,161 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_DOMException_h__
|
||||
#define mozilla_dom_DOMException_h__
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "jspubtd.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsID.h"
|
||||
#include "nsIDOMDOMException.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "xpcexception.h"
|
||||
|
||||
class nsIStackFrame;
|
||||
class nsString;
|
||||
|
||||
nsresult
|
||||
NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
|
||||
const char** aMessage,
|
||||
uint16_t* aCode = nullptr);
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#define MOZILLA_DOM_EXCEPTION_IID \
|
||||
{ 0x55eda557, 0xeba0, 0x4fe3, \
|
||||
{ 0xae, 0x2e, 0xf3, 0x94, 0x49, 0x23, 0x62, 0xd6 } }
|
||||
|
||||
class Exception : public nsIXPCException,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_EXCEPTION_IID)
|
||||
|
||||
NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCEXCEPTION_CID)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Exception)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_NSIEXCEPTION
|
||||
NS_DECL_NSIXPCEXCEPTION
|
||||
|
||||
// Cruft used by XPConnect for exceptions originating in JS implemented
|
||||
// components.
|
||||
bool StealJSVal(JS::Value* aVp);
|
||||
void StowJSVal(JS::Value& aVp);
|
||||
|
||||
// WebIDL API
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
nsISupports* GetParentObject() const { return nullptr; }
|
||||
|
||||
void GetMessageMoz(nsString& retval);
|
||||
|
||||
uint32_t Result() const;
|
||||
|
||||
void GetName(nsString& retval);
|
||||
|
||||
void GetFilename(nsString& retval);
|
||||
|
||||
uint32_t LineNumber() const;
|
||||
|
||||
uint32_t ColumnNumber() const;
|
||||
|
||||
already_AddRefed<nsIStackFrame> GetLocation() const;
|
||||
|
||||
already_AddRefed<nsISupports> GetInner() const;
|
||||
|
||||
already_AddRefed<nsISupports> GetData() const;
|
||||
|
||||
void Stringify(nsString& retval);
|
||||
|
||||
// XPCOM factory ctor.
|
||||
Exception();
|
||||
|
||||
Exception(const char *aMessage,
|
||||
nsresult aResult,
|
||||
const char *aName,
|
||||
nsIStackFrame *aLocation,
|
||||
nsISupports *aData);
|
||||
|
||||
protected:
|
||||
virtual ~Exception();
|
||||
|
||||
char* mMessage;
|
||||
nsresult mResult;
|
||||
char* mName;
|
||||
nsCOMPtr<nsIStackFrame> mLocation;
|
||||
nsCOMPtr<nsISupports> mData;
|
||||
char* mFilename;
|
||||
int mLineNumber;
|
||||
nsCOMPtr<nsIException> mInner;
|
||||
bool mInitialized;
|
||||
|
||||
bool mHoldingJSVal;
|
||||
JS::Heap<JS::Value> mThrownJSVal;
|
||||
|
||||
private:
|
||||
static bool sEverMadeOneFromFactory;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Exception, MOZILLA_DOM_EXCEPTION_IID)
|
||||
|
||||
class DOMException : public Exception,
|
||||
public nsIDOMDOMException
|
||||
{
|
||||
public:
|
||||
DOMException(nsresult aRv, const char* aMessage,
|
||||
const char* aName, uint16_t aCode);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMDOMEXCEPTION
|
||||
|
||||
// nsIException overrides
|
||||
NS_IMETHOD ToString(char **aReturn) MOZ_OVERRIDE;
|
||||
|
||||
// nsWrapperCache overrides
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
MOZ_OVERRIDE;
|
||||
|
||||
uint16_t Code() const {
|
||||
return mCode;
|
||||
}
|
||||
|
||||
// Intentionally shadow the nsXPCException version.
|
||||
void GetMessageMoz(nsString& retval);
|
||||
void GetName(nsString& retval);
|
||||
|
||||
static already_AddRefed<DOMException>
|
||||
Create(nsresult aRv);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~DOMException() {}
|
||||
|
||||
// Intentionally shadow the nsXPCException version.
|
||||
const char* mName;
|
||||
const char* mMessage;
|
||||
|
||||
uint16_t mCode;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
@ -22,7 +22,6 @@ EXPORTS += [
|
||||
'nsDOMCID.h',
|
||||
'nsDOMClassInfoClasses.h',
|
||||
'nsDOMClassInfoID.h',
|
||||
'nsDOMException.h',
|
||||
'nsDOMJSUtils.h',
|
||||
'nsDOMNavigationTiming.h',
|
||||
'nsDOMString.h',
|
||||
@ -54,6 +53,7 @@ EXPORTS.mozilla.dom += [
|
||||
'BarProps.h',
|
||||
'DOMCursor.h',
|
||||
'DOMError.h',
|
||||
'DOMException.h',
|
||||
'DOMRequest.h',
|
||||
'MessageChannel.h',
|
||||
'MessagePort.h',
|
||||
@ -67,13 +67,13 @@ CPP_SOURCES += [
|
||||
'Crypto.cpp',
|
||||
'DOMCursor.cpp',
|
||||
'DOMError.cpp',
|
||||
'DOMException.cpp',
|
||||
'DOMRequest.cpp',
|
||||
'Navigator.cpp',
|
||||
'MessageChannel.cpp',
|
||||
'MessagePort.cpp',
|
||||
'nsContentPermissionHelper.cpp',
|
||||
'nsDOMClassInfo.cpp',
|
||||
'nsDOMException.cpp',
|
||||
'nsDOMNavigationTiming.cpp',
|
||||
'nsDOMScriptObjectFactory.cpp',
|
||||
'nsDOMWindowList.cpp',
|
||||
|
@ -77,7 +77,6 @@
|
||||
|
||||
// DOM core includes
|
||||
#include "nsError.h"
|
||||
#include "nsIDOMDOMException.h"
|
||||
#include "nsIDOMDOMStringList.h"
|
||||
#include "nsIDOMUserDataHandler.h"
|
||||
#include "nsIDOMLoadStatus.h"
|
||||
@ -338,10 +337,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
nsIXPCScriptable::WANT_CONSTRUCT |
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
|
||||
|
||||
// Core classes
|
||||
NS_DEFINE_CLASSINFO_DATA(DOMException, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
// Misc Core related classes
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(DeviceAcceleration, nsDOMGenericSH,
|
||||
@ -1110,11 +1105,6 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DOMException, nsIDOMDOMException)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMException)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIException)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DeviceAcceleration, nsIDOMDeviceAcceleration)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDeviceAcceleration)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -9,9 +9,6 @@ DOMCI_CLASS(Location)
|
||||
DOMCI_CLASS(DOMPrototype)
|
||||
DOMCI_CLASS(DOMConstructor)
|
||||
|
||||
// Core classes
|
||||
DOMCI_CLASS(DOMException)
|
||||
|
||||
DOMCI_CLASS(DeviceAcceleration)
|
||||
DOMCI_CLASS(DeviceRotationRate)
|
||||
|
||||
|
@ -1,238 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDOMException.h"
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIDOMDOMException.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsString.h"
|
||||
#include "prprf.h"
|
||||
#include "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,
|
||||
NotFoundError = nsIDOMDOMException::NOT_FOUND_ERR,
|
||||
NotSupportedError = nsIDOMDOMException::NOT_SUPPORTED_ERR,
|
||||
// Can't remove until setNamedItem is removed
|
||||
InUseAttributeError = nsIDOMDOMException::INUSE_ATTRIBUTE_ERR,
|
||||
InvalidStateError = nsIDOMDOMException::INVALID_STATE_ERR,
|
||||
SyntaxError = nsIDOMDOMException::SYNTAX_ERR,
|
||||
InvalidModificationError = nsIDOMDOMException::INVALID_MODIFICATION_ERR,
|
||||
NamespaceError = nsIDOMDOMException::NAMESPACE_ERR,
|
||||
InvalidAccessError = nsIDOMDOMException::INVALID_ACCESS_ERR,
|
||||
TypeMismatchError = nsIDOMDOMException::TYPE_MISMATCH_ERR,
|
||||
SecurityError = nsIDOMDOMException::SECURITY_ERR,
|
||||
NetworkError = nsIDOMDOMException::NETWORK_ERR,
|
||||
AbortError = nsIDOMDOMException::ABORT_ERR,
|
||||
URLMismatchError = nsIDOMDOMException::URL_MISMATCH_ERR,
|
||||
QuotaExceededError = nsIDOMDOMException::QUOTA_EXCEEDED_ERR,
|
||||
TimeoutError = nsIDOMDOMException::TIMEOUT_ERR,
|
||||
InvalidNodeTypeError = nsIDOMDOMException::INVALID_NODE_TYPE_ERR,
|
||||
DataCloneError = nsIDOMDOMException::DATA_CLONE_ERR,
|
||||
EncodingError = 0,
|
||||
|
||||
/* XXX Should be JavaScript native errors */
|
||||
TypeError = 0,
|
||||
RangeError = 0,
|
||||
|
||||
/* IndexedDB errors http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#exceptions */
|
||||
UnknownError = 0,
|
||||
ConstraintError = 0,
|
||||
DataError = 0,
|
||||
TransactionInactiveError = 0,
|
||||
ReadOnlyError = 0,
|
||||
VersionError = 0,
|
||||
|
||||
/* File API errors http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException */
|
||||
NotReadableError = 0,
|
||||
|
||||
/* FileHandle API errors */
|
||||
LockedFileInactiveError = 0,
|
||||
};
|
||||
|
||||
#define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message},
|
||||
#define DOM_MSG_DEF(val, message) {(val), NS_ERROR_GET_CODE(val), #val, message},
|
||||
|
||||
static const struct ResultStruct
|
||||
{
|
||||
nsresult mNSResult;
|
||||
uint16_t mCode;
|
||||
const char* mName;
|
||||
const char* mMessage;
|
||||
} sDOMErrorMsgMap[] = {
|
||||
#include "domerr.msg"
|
||||
};
|
||||
|
||||
#undef DOM4_MSG_DEF
|
||||
#undef DOM_MSG_DEF
|
||||
|
||||
static void
|
||||
NSResultToNameAndMessage(nsresult aNSResult,
|
||||
const char** aName,
|
||||
const char** aMessage,
|
||||
uint16_t* aCode)
|
||||
{
|
||||
*aName = nullptr;
|
||||
*aMessage = nullptr;
|
||||
*aCode = 0;
|
||||
for (uint32_t idx = 0; idx < ArrayLength(sDOMErrorMsgMap); idx++) {
|
||||
if (aNSResult == sDOMErrorMsgMap[idx].mNSResult) {
|
||||
*aName = sDOMErrorMsgMap[idx].mName;
|
||||
*aMessage = sDOMErrorMsgMap[idx].mMessage;
|
||||
*aCode = sDOMErrorMsgMap[idx].mCode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NS_WARNING("Huh, someone is throwing non-DOM errors using the DOM module!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, const char** aName,
|
||||
const char** aMessage, uint16_t* aCode)
|
||||
{
|
||||
const char* name = nullptr;
|
||||
const char* message = nullptr;
|
||||
uint16_t code = 0;
|
||||
NSResultToNameAndMessage(aNSResult, &name, &message, &code);
|
||||
|
||||
if (name && message) {
|
||||
*aName = name;
|
||||
*aMessage = message;
|
||||
if (aCode) {
|
||||
*aCode = code;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
DOMCI_DATA(DOMException, nsDOMException)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMException, nsXPCException)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMException, nsXPCException)
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMException)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMDOMException)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMException)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsXPCException)
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
// Warn only when the code was changed (other than DOM Core)
|
||||
// or the code is useless (zero)
|
||||
if (NS_ERROR_GET_MODULE(mResult) != NS_ERROR_MODULE_DOM || !mCode) {
|
||||
nsCOMPtr<nsIDocument> doc = nsContentUtils::GetDocumentFromCaller();
|
||||
if (doc) {
|
||||
doc->WarnOnceAbout(nsIDocument::eDOMExceptionCode);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMException::ToString(char **aReturn)
|
||||
{
|
||||
*aReturn = nullptr;
|
||||
|
||||
static const char defaultMsg[] = "<no message>";
|
||||
static const char defaultLocation[] = "<unknown>";
|
||||
static const char defaultName[] = "<unknown>";
|
||||
static const char format[] =
|
||||
"[Exception... \"%s\" code: \"%d\" nsresult: \"0x%x (%s)\" location: \"%s\"]";
|
||||
|
||||
nsAutoCString location;
|
||||
|
||||
if (mInner) {
|
||||
nsXPIDLCString filename;
|
||||
|
||||
mInner->GetFilename(getter_Copies(filename));
|
||||
|
||||
if (!filename.IsEmpty()) {
|
||||
uint32_t line_nr = 0;
|
||||
|
||||
mInner->GetLineNumber(&line_nr);
|
||||
|
||||
char *temp = PR_smprintf("%s Line: %d", filename.get(), line_nr);
|
||||
if (temp) {
|
||||
location.Assign(temp);
|
||||
PR_smprintf_free(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (location.IsEmpty()) {
|
||||
location = defaultLocation;
|
||||
}
|
||||
|
||||
const char* msg = mMessage ? mMessage : defaultMsg;
|
||||
const char* resultName = mName ? mName : defaultName;
|
||||
|
||||
*aReturn = PR_smprintf(format, msg, mCode, mResult, resultName,
|
||||
location.get());
|
||||
|
||||
return *aReturn ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMException::GetName(nsString& retval)
|
||||
{
|
||||
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);
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// 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"
|
||||
#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);
|
||||
|
||||
already_AddRefed<nsDOMException>
|
||||
NS_NewDOMException(nsresult aNSResult);
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
@ -24,7 +24,6 @@
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsDOMException.h"
|
||||
#include "nsCRT.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPrototypeCache.h"
|
||||
|
@ -320,7 +320,6 @@ DOMInterfaces = {
|
||||
},
|
||||
|
||||
'DOMException': {
|
||||
'nativeType': 'nsDOMException',
|
||||
'binaryNames': {
|
||||
'message': 'messageMoz',
|
||||
},
|
||||
@ -399,8 +398,7 @@ DOMInterfaces = {
|
||||
}],
|
||||
|
||||
'Exception': {
|
||||
'nativeType': 'nsXPCException',
|
||||
'headerFile': 'xpcprivate.h',
|
||||
'headerFile': 'mozilla/dom/DOMException.h',
|
||||
'binaryNames': {
|
||||
'message': 'messageMoz',
|
||||
}
|
||||
|
410
dom/bindings/Exceptions.cpp
Normal file
410
dom/bindings/Exceptions.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/OldDebugAPI.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsprf.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "XPCWrapper.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// We can't use nsContentUtils::IsCallerChrome because it might not exist in
|
||||
// xpcshell.
|
||||
bool
|
||||
IsCallerChrome()
|
||||
{
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan;
|
||||
secMan = XPCWrapper::GetSecurityManager();
|
||||
|
||||
if (!secMan) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isChrome;
|
||||
return NS_SUCCEEDED(secMan->SubjectPrincipalIsSystem(&isChrome)) && isChrome;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
bool
|
||||
ThrowExceptionObject(JSContext* aCx, nsIException* aException)
|
||||
{
|
||||
// See if we really have an Exception.
|
||||
nsCOMPtr<Exception> exception = do_QueryInterface(aException);
|
||||
if (exception) {
|
||||
return ThrowExceptionObject(aCx, exception);
|
||||
}
|
||||
|
||||
// We only have an nsIException (probably an XPCWrappedJS). Fall back on old
|
||||
// wrapping.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
JS::RootedObject glob(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (!glob) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsresult rv = nsContentUtils::XPConnect()->WrapNative(aCx, glob, aException,
|
||||
NS_GET_IID(nsIException),
|
||||
getter_AddRefs(holder));
|
||||
if (NS_FAILED(rv) ||! holder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::RootedObject obj(aCx, holder->GetJSObject());
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_SetPendingException(aCx, OBJECT_TO_JSVAL(obj));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowExceptionObject(JSContext* aCx, Exception* aException)
|
||||
{
|
||||
JS::RootedValue thrown(aCx);
|
||||
|
||||
// If we stored the original thrown JS value in the exception
|
||||
// (see XPCConvert::ConstructException) and we are in a web context
|
||||
// (i.e., not chrome), rethrow the original value. This only applies to JS
|
||||
// implemented components so we only need to check for this on the main
|
||||
// thread.
|
||||
if (NS_IsMainThread() && !IsCallerChrome() &&
|
||||
aException->StealJSVal(thrown.address())) {
|
||||
if (!JS_WrapValue(aCx, thrown.address())) {
|
||||
return false;
|
||||
}
|
||||
JS_SetPendingException(aCx, thrown);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::RootedObject glob(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (!glob) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::RootedValue val(aCx);
|
||||
if (!mozilla::dom::WrapNewBindingObject(aCx, glob, aException, &val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_SetPendingException(aCx, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Throw(JSContext* cx, nsresult rv, const char* sz)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (JS_IsExceptionPending(cx)) {
|
||||
// Don't clobber the existing exception.
|
||||
return;
|
||||
}
|
||||
|
||||
/* no need to set an expection if the security manager already has */
|
||||
if (rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO && JS_IsExceptionPending(cx)) {
|
||||
// This should only ever happen on the main thread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return;
|
||||
}
|
||||
|
||||
CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
|
||||
nsCOMPtr<nsIException> existingException = runtime->GetPendingException();
|
||||
if (existingException) {
|
||||
nsresult nr;
|
||||
if (NS_SUCCEEDED(existingException->GetResult(&nr)) &&
|
||||
rv == nr) {
|
||||
// Just reuse the existing exception.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<Exception> 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()) {
|
||||
finalException = DOMException::Create(rv);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If not, use the default.
|
||||
if (finalException == nullptr) {
|
||||
finalException = new Exception(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);
|
||||
}
|
||||
}
|
||||
|
||||
namespace exceptions {
|
||||
|
||||
class JSStackFrame : public nsIStackFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTACKFRAME
|
||||
|
||||
JSStackFrame();
|
||||
virtual ~JSStackFrame();
|
||||
|
||||
static already_AddRefed<nsIStackFrame>
|
||||
CreateStack(JSContext* cx);
|
||||
static already_AddRefed<nsIStackFrame>
|
||||
CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller);
|
||||
|
||||
private:
|
||||
bool IsJSFrame() const {
|
||||
return mLanguage == nsIProgrammingLanguage::JAVASCRIPT;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStackFrame> mCaller;
|
||||
|
||||
char* mFilename;
|
||||
char* mFunname;
|
||||
int32_t mLineno;
|
||||
uint32_t mLanguage;
|
||||
};
|
||||
|
||||
JSStackFrame::JSStackFrame()
|
||||
: mFilename(nullptr),
|
||||
mFunname(nullptr),
|
||||
mLineno(0),
|
||||
mLanguage(nsIProgrammingLanguage::UNKNOWN)
|
||||
{}
|
||||
|
||||
JSStackFrame::~JSStackFrame()
|
||||
{
|
||||
if (mFilename) {
|
||||
nsMemory::Free(mFilename);
|
||||
}
|
||||
if (mFunname) {
|
||||
nsMemory::Free(mFunname);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(JSStackFrame, nsIStackFrame)
|
||||
|
||||
/* readonly attribute uint32_t language; */
|
||||
NS_IMETHODIMP JSStackFrame::GetLanguage(uint32_t* aLanguage)
|
||||
{
|
||||
*aLanguage = mLanguage;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string languageName; */
|
||||
NS_IMETHODIMP JSStackFrame::GetLanguageName(char** aLanguageName)
|
||||
{
|
||||
static const char js[] = "JavaScript";
|
||||
static const char cpp[] = "C++";
|
||||
|
||||
if (IsJSFrame()) {
|
||||
*aLanguageName = (char*) nsMemory::Clone(js, sizeof(js));
|
||||
} else {
|
||||
*aLanguageName = (char*) nsMemory::Clone(cpp, sizeof(cpp));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string filename; */
|
||||
NS_IMETHODIMP JSStackFrame::GetFilename(char** aFilename)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFilename);
|
||||
|
||||
if (mFilename) {
|
||||
*aFilename = (char*) nsMemory::Clone(mFilename,
|
||||
sizeof(char)*(strlen(mFilename)+1));
|
||||
} else {
|
||||
*aFilename = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string name; */
|
||||
NS_IMETHODIMP JSStackFrame::GetName(char** aFunction)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFunction);
|
||||
|
||||
if (mFunname) {
|
||||
*aFunction = (char*) nsMemory::Clone(mFunname,
|
||||
sizeof(char)*(strlen(mFunname)+1));
|
||||
} else {
|
||||
*aFunction = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute int32_t lineNumber; */
|
||||
NS_IMETHODIMP JSStackFrame::GetLineNumber(int32_t* aLineNumber)
|
||||
{
|
||||
*aLineNumber = mLineno;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string sourceLine; */
|
||||
NS_IMETHODIMP JSStackFrame::GetSourceLine(char** aSourceLine)
|
||||
{
|
||||
*aSourceLine = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIStackFrame caller; */
|
||||
NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
|
||||
{
|
||||
NS_IF_ADDREF(*aCaller = mCaller);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string toString (); */
|
||||
NS_IMETHODIMP JSStackFrame::ToString(char** _retval)
|
||||
{
|
||||
const char* frametype = IsJSFrame() ? "JS" : "native";
|
||||
const char* filename = mFilename ? mFilename : "<unknown filename>";
|
||||
const char* funname = mFunname ? mFunname : "<TOP_LEVEL>";
|
||||
static const char format[] = "%s frame :: %s :: %s :: line %d";
|
||||
int len = sizeof(char)*
|
||||
(strlen(frametype) + strlen(filename) + strlen(funname)) +
|
||||
sizeof(format) + 6 /* space for lineno */;
|
||||
|
||||
char* buf = (char*) nsMemory::Alloc(len);
|
||||
JS_snprintf(buf, len, format, frametype, filename, funname, mLineno);
|
||||
*_retval = buf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIStackFrame>
|
||||
JSStackFrame::CreateStack(JSContext* cx)
|
||||
{
|
||||
static const unsigned MAX_FRAMES = 100;
|
||||
|
||||
nsRefPtr<JSStackFrame> first = new JSStackFrame();
|
||||
nsRefPtr<JSStackFrame> self = first;
|
||||
|
||||
JS::StackDescription* desc = JS::DescribeStack(cx, MAX_FRAMES);
|
||||
if (!desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < desc->nframes && self; i++) {
|
||||
self->mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
|
||||
JSAutoCompartment ac(cx, desc->frames[i].script);
|
||||
const char* filename = JS_GetScriptFilename(cx, desc->frames[i].script);
|
||||
if (filename) {
|
||||
self->mFilename =
|
||||
(char*)nsMemory::Clone(filename, sizeof(char)*(strlen(filename)+1));
|
||||
}
|
||||
|
||||
self->mLineno = desc->frames[i].lineno;
|
||||
|
||||
JSFunction* fun = desc->frames[i].fun;
|
||||
if (fun) {
|
||||
JS::RootedString funid(cx, JS_GetFunctionDisplayId(fun));
|
||||
if (funid) {
|
||||
size_t length = JS_GetStringEncodingLength(cx, funid);
|
||||
if (length != size_t(-1)) {
|
||||
self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
|
||||
if (self->mFunname) {
|
||||
JS_EncodeStringToBuffer(cx, funid, self->mFunname, length);
|
||||
self->mFunname[length] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<JSStackFrame> frame = new JSStackFrame();
|
||||
self->mCaller = frame;
|
||||
self = frame.forget();
|
||||
}
|
||||
|
||||
JS::FreeStackDescription(cx, desc);
|
||||
|
||||
return first.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIStackFrame>
|
||||
JSStackFrame::CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller)
|
||||
{
|
||||
nsRefPtr<JSStackFrame> self = new JSStackFrame();
|
||||
|
||||
self->mLanguage = aLanguage;
|
||||
self->mLineno = aLineNumber;
|
||||
|
||||
if (aFilename) {
|
||||
self->mFilename =
|
||||
(char*)nsMemory::Clone(aFilename, sizeof(char)*(strlen(aFilename)+1));
|
||||
}
|
||||
|
||||
if (aFunctionName) {
|
||||
self->mFunname =
|
||||
(char*)nsMemory::Clone(aFunctionName,
|
||||
sizeof(char)*(strlen(aFunctionName)+1));
|
||||
}
|
||||
|
||||
self->mCaller = aCaller;
|
||||
|
||||
return self.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIStackFrame>
|
||||
CreateStack(JSContext* cx)
|
||||
{
|
||||
return JSStackFrame::CreateStack(cx);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIStackFrame>
|
||||
CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller)
|
||||
{
|
||||
return JSStackFrame::CreateStackFrameLocation(aLanguage, aFilename,
|
||||
aFunctionName, aLineNumber,
|
||||
aCaller);
|
||||
}
|
||||
|
||||
} // namespace exceptions
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
50
dom/bindings/Exceptions.h
Normal file
50
dom/bindings/Exceptions.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_Exceptions_h__
|
||||
#define mozilla_dom_Exceptions_h__
|
||||
|
||||
// DOM exception throwing machinery (for both main thread and workers).
|
||||
|
||||
#include <stdint.h>
|
||||
#include "jspubtd.h"
|
||||
#include "nsIException.h"
|
||||
|
||||
class nsIStackFrame;
|
||||
template <class T>
|
||||
class already_AddRefed;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Exception;
|
||||
|
||||
void
|
||||
Throw(JSContext* cx, nsresult rv, const char* sz);
|
||||
|
||||
bool
|
||||
ThrowExceptionObject(JSContext* aCx, Exception* aException);
|
||||
|
||||
bool
|
||||
ThrowExceptionObject(JSContext* aCx, nsIException* aException);
|
||||
|
||||
// Internal stuff not intended to be widely used.
|
||||
namespace exceptions {
|
||||
|
||||
already_AddRefed<nsIStackFrame>
|
||||
CreateStack(JSContext* cx);
|
||||
|
||||
already_AddRefed<nsIStackFrame>
|
||||
CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller);
|
||||
|
||||
} // namespace exceptions
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -60,6 +60,7 @@ CPPSRCS = \
|
||||
CallbackObject.cpp \
|
||||
DOMJSProxyHandler.cpp \
|
||||
Date.cpp \
|
||||
Exceptions.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -21,6 +21,7 @@ EXPORTS.mozilla.dom += [
|
||||
'DOMJSProxyHandler.h',
|
||||
'Date.h',
|
||||
'Errors.msg',
|
||||
'Exceptions.h',
|
||||
'JSSlots.h',
|
||||
'NonRefcountedDOMObject.h',
|
||||
'Nullable.h',
|
||||
|
@ -1116,7 +1116,7 @@ bool
|
||||
IsCurrentThreadRunningChromeWorker()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||
CycleCollectedJSRuntime* ccrt = nsCycleCollector_currentJSRuntime();
|
||||
CycleCollectedJSRuntime* ccrt = CycleCollectedJSRuntime::Get();
|
||||
if (!ccrt) {
|
||||
return false;
|
||||
}
|
||||
|
@ -7,14 +7,7 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIException.idl"
|
||||
|
||||
%{ C++
|
||||
#include "js/TypeDecls.h"
|
||||
%}
|
||||
|
||||
[ptr] native xpcexJSContextPtr(JSContext);
|
||||
native xpcexJSVal(JS::Value);
|
||||
|
||||
[scriptable, uuid(cac29630-7bf2-4e22-811b-46855a7d5af0)]
|
||||
[scriptable, uuid(ce83229c-0a82-4ba4-937b-7fd4cd45f34b)]
|
||||
interface nsIXPCException : nsIException
|
||||
{
|
||||
// inherits methods from nsIException
|
||||
@ -25,10 +18,6 @@ interface nsIXPCException : nsIException
|
||||
in nsIStackFrame aLocation,
|
||||
in nsISupports aData,
|
||||
in nsIException aInner);
|
||||
|
||||
[noscript] xpcexJSVal stealJSVal();
|
||||
[noscript] void stowJSVal(in xpcexJSContextPtr cx,
|
||||
in xpcexJSVal val);
|
||||
};
|
||||
|
||||
/* this goes into the C++ header verbatim. */
|
||||
|
@ -39,12 +39,14 @@
|
||||
#include "mozilla/XPTInterfaceInfoManager.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace JS;
|
||||
using namespace js;
|
||||
using namespace xpc;
|
||||
using mozilla::dom::Exception;
|
||||
|
||||
/***************************************************************************/
|
||||
// stuff used by all
|
||||
@ -1946,7 +1948,7 @@ nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
|
||||
// Do the security check if necessary
|
||||
|
||||
nsIXPCSecurityManager* sm = xpc->GetDefaultSecurityManager();
|
||||
if (sm && NS_FAILED(sm->CanCreateInstance(cx, nsXPCException::GetCID()))) {
|
||||
if (sm && NS_FAILED(sm->CanCreateInstance(cx, Exception::GetCID()))) {
|
||||
// the security manager vetoed. It should have set an exception.
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
@ -1957,11 +1959,9 @@ nsXPCComponents_Exception::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
|
||||
if (!parser.parse(args))
|
||||
return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
|
||||
|
||||
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<nsIException> e = new Exception(parser.eMsg, parser.eResult,
|
||||
nullptr, parser.eStack,
|
||||
parser.eData);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
RootedObject newObj(cx);
|
||||
@ -1988,7 +1988,7 @@ nsXPCComponents_Exception::HasInstance(nsIXPConnectWrappedNative *wrapper,
|
||||
|
||||
RootedValue v(cx, val);
|
||||
if (bp) {
|
||||
nsXPCException* e;
|
||||
Exception* e;
|
||||
*bp = NS_SUCCEEDED(UNWRAP_OBJECT(Exception, cx, v.toObjectOrNull(), e)) ||
|
||||
JSValIsInterfaceOfType(cx, v, NS_GET_IID(nsIException));
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "JavaScriptParent.h"
|
||||
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/PrimitiveConversions.h"
|
||||
|
||||
using namespace xpc;
|
||||
@ -1080,14 +1081,14 @@ XPCConvert::ConstructException(nsresult rv, const char* message,
|
||||
if (ifaceName && methodName)
|
||||
msg = sz = JS_smprintf(format, msg, ifaceName, methodName);
|
||||
|
||||
nsCOMPtr<nsIException> e = new nsXPCException(msg, rv, nullptr, nullptr, data);
|
||||
nsRefPtr<Exception> e = new Exception(msg, rv, nullptr, nullptr, data);
|
||||
|
||||
if (cx && jsExceptionPtr && *exceptn) {
|
||||
nsCOMPtr<nsIXPCException> xpcEx = do_QueryInterface(*exceptn);
|
||||
if (xpcEx)
|
||||
xpcEx->StowJSVal(cx, *jsExceptionPtr);
|
||||
if (cx && jsExceptionPtr) {
|
||||
e->StowJSVal(*jsExceptionPtr);
|
||||
}
|
||||
|
||||
e.forget(exceptn);
|
||||
|
||||
if (sz)
|
||||
JS_smprintf_free(sz);
|
||||
return NS_OK;
|
||||
|
@ -7,12 +7,7 @@
|
||||
/* An implementaion of nsIException. */
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include "jsprf.h"
|
||||
#include "nsError.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
|
||||
@ -83,462 +78,3 @@ nsXPCException::GetNSResultCount()
|
||||
{
|
||||
return RESULT_COUNT;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
NS_IMPL_CLASSINFO(nsXPCException, NULL, nsIClassInfo::DOM_OBJECT,
|
||||
NS_XPCEXCEPTION_CID)
|
||||
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
|
||||
|
||||
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),
|
||||
mName(nullptr),
|
||||
mLocation(nullptr),
|
||||
mData(nullptr),
|
||||
mFilename(nullptr),
|
||||
mLineNumber(0),
|
||||
mInner(nullptr),
|
||||
mInitialized(false)
|
||||
{ }
|
||||
|
||||
nsXPCException::~nsXPCException()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/* [noscript] xpcexJSVal stealJSVal (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::StealJSVal(jsval *vp)
|
||||
{
|
||||
if (mThrownJSVal.IsHeld()) {
|
||||
*vp = mThrownJSVal.Release();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* [noscript] void stowJSVal (in xpcexJSContextPtr cx, in xpcexJSVal val); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::StowJSVal(JSContext* cx, jsval v)
|
||||
{
|
||||
if (mThrownJSVal.Hold(cx)) {
|
||||
mThrownJSVal = v;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
nsXPCException::Reset()
|
||||
{
|
||||
if (mMessage) {
|
||||
nsMemory::Free(mMessage);
|
||||
mMessage = nullptr;
|
||||
}
|
||||
if (mName) {
|
||||
nsMemory::Free(mName);
|
||||
mName = nullptr;
|
||||
}
|
||||
if (mFilename) {
|
||||
nsMemory::Free(mFilename);
|
||||
mFilename = nullptr;
|
||||
}
|
||||
mLineNumber = (uint32_t)-1;
|
||||
NS_IF_RELEASE(mLocation);
|
||||
NS_IF_RELEASE(mData);
|
||||
NS_IF_RELEASE(mInner);
|
||||
}
|
||||
|
||||
/* readonly attribute string message; */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::GetMessageMoz(char * *aMessage)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
XPC_STRING_GETTER_BODY(aMessage, mMessage);
|
||||
}
|
||||
|
||||
/* readonly attribute nsresult result; */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::GetResult(nsresult *aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
*aResult = mResult;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string name; */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::GetName(char * *aName)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
const char* name = mName;
|
||||
if (!name)
|
||||
NameAndFormatForNSResult(mResult, &name, nullptr);
|
||||
|
||||
XPC_STRING_GETTER_BODY(aName, name);
|
||||
}
|
||||
|
||||
/* readonly attribute string filename; */
|
||||
NS_IMETHODIMP nsXPCException::GetFilename(char * *aFilename)
|
||||
{
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
XPC_STRING_GETTER_BODY(aFilename, mFilename);
|
||||
}
|
||||
|
||||
/* readonly attribute uint32_t lineNumber; */
|
||||
NS_IMETHODIMP nsXPCException::GetLineNumber(uint32_t *aLineNumber)
|
||||
{
|
||||
if (!aLineNumber)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
*aLineNumber = mLineNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute uint32_t columnNumber; */
|
||||
NS_IMETHODIMP nsXPCException::GetColumnNumber(uint32_t *aColumnNumber)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aColumnNumber);
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
*aColumnNumber = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIStackFrame location; */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::GetLocation(nsIStackFrame * *aLocation)
|
||||
{
|
||||
if (!aLocation)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
*aLocation = mLocation;
|
||||
NS_IF_ADDREF(mLocation);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsISupports data; */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::GetData(nsISupports * *aData)
|
||||
{
|
||||
if (!aData)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
*aData = mData;
|
||||
NS_IF_ADDREF(mData);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIException inner; */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::GetInner(nsIException* *aException)
|
||||
{
|
||||
if (!aException)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
*aException = mInner;
|
||||
NS_IF_ADDREF(mInner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void initialize (in string aMessage, in nsresult aResult, in string aName, in nsIStackFrame aLocation, in nsISupports aData, in nsIException aInner); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::Initialize(const char *aMessage, nsresult aResult, const char *aName, nsIStackFrame *aLocation, nsISupports *aData, nsIException *aInner)
|
||||
{
|
||||
if (mInitialized)
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
|
||||
Reset();
|
||||
|
||||
if (aMessage) {
|
||||
if (!(mMessage = (char*) nsMemory::Clone(aMessage,
|
||||
sizeof(char)*(strlen(aMessage)+1))))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (aName) {
|
||||
if (!(mName = (char*) nsMemory::Clone(aName,
|
||||
sizeof(char)*(strlen(aName)+1))))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mResult = aResult;
|
||||
|
||||
if (aLocation) {
|
||||
mLocation = aLocation;
|
||||
NS_ADDREF(mLocation);
|
||||
// For now, fill in our location details from our stack frame.
|
||||
// Later we may allow other locations?
|
||||
nsresult rc;
|
||||
if (NS_FAILED(rc = aLocation->GetFilename(&mFilename)))
|
||||
return rc;
|
||||
if (NS_FAILED(rc = aLocation->GetLineNumber(&mLineNumber)))
|
||||
return rc;
|
||||
} else {
|
||||
nsresult rv;
|
||||
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
||||
rv = xpc->GetCurrentJSStack(&mLocation);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aData) {
|
||||
mData = aData;
|
||||
NS_ADDREF(mData);
|
||||
}
|
||||
if (aInner) {
|
||||
mInner = aInner;
|
||||
NS_ADDREF(mInner);
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string toString (); */
|
||||
NS_IMETHODIMP
|
||||
nsXPCException::ToString(char **_retval)
|
||||
{
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mInitialized)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
static const char defaultMsg[] = "<no message>";
|
||||
static const char defaultLocation[] = "<unknown>";
|
||||
static const char format[] =
|
||||
"[Exception... \"%s\" nsresult: \"0x%x (%s)\" location: \"%s\" data: %s]";
|
||||
|
||||
char* indicatedLocation = nullptr;
|
||||
|
||||
if (mLocation) {
|
||||
// we need to free this if it does not fail
|
||||
nsresult rv = mLocation->ToString(&indicatedLocation);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
const char* msg = mMessage ? mMessage : nullptr;
|
||||
const char* location = indicatedLocation ?
|
||||
indicatedLocation : defaultLocation;
|
||||
const char* resultName = mName;
|
||||
if (!resultName && !NameAndFormatForNSResult(mResult, &resultName,
|
||||
(!msg) ? &msg : nullptr)) {
|
||||
if (!msg)
|
||||
msg = defaultMsg;
|
||||
resultName = "<unknown>";
|
||||
}
|
||||
const char* data = mData ? "yes" : "no";
|
||||
|
||||
char* temp = JS_smprintf(format, msg, mResult, resultName, location, data);
|
||||
if (indicatedLocation)
|
||||
nsMemory::Free(indicatedLocation);
|
||||
|
||||
char* final = nullptr;
|
||||
if (temp) {
|
||||
final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1));
|
||||
JS_smprintf_free(temp);
|
||||
}
|
||||
|
||||
*_retval = final;
|
||||
return final ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
nsXPCException::WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
|
||||
{
|
||||
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;
|
||||
|
@ -17,7 +17,6 @@ class XPCContext;
|
||||
class XPCCallContext;
|
||||
|
||||
class XPCJSThrower;
|
||||
class XPCJSStack;
|
||||
|
||||
class nsXPCWrappedJS;
|
||||
class nsXPCWrappedJSClass;
|
||||
|
@ -1393,6 +1393,10 @@ void XPCJSRuntime::SystemIsBeingShutDown()
|
||||
|
||||
XPCJSRuntime::~XPCJSRuntime()
|
||||
{
|
||||
// Clear any pending exception. It might be an XPCWrappedJS, and if we try
|
||||
// to destroy it later we will crash.
|
||||
SetPendingException(nullptr);
|
||||
|
||||
JS::SetGCSliceCallback(Runtime(), mPrevGCSliceCallback);
|
||||
|
||||
xpc_DelocalizeRuntime(Runtime());
|
||||
|
@ -21,7 +21,6 @@
|
||||
#define MOZJSSUBSCRIPTLOADER_CONTRACTID "@mozilla.org/moz/jssubscript-loader;1"
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSID)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCException)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIXPConnect,
|
||||
nsXPConnect::GetSingleton)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptError)
|
||||
@ -39,7 +38,6 @@ NS_DEFINE_NAMED_CID(MOZ_JSSUBSCRIPTLOADER_CID);
|
||||
#define XPCONNECT_CIDENTRIES \
|
||||
{ &kNS_JS_ID_CID, false, NULL, nsJSIDConstructor }, \
|
||||
{ &kNS_XPCONNECT_CID, false, NULL, nsIXPConnectConstructor }, \
|
||||
{ &kNS_XPCEXCEPTION_CID, false, NULL, nsXPCExceptionConstructor }, \
|
||||
{ &kNS_SCRIPTERROR_CID, false, NULL, nsScriptErrorConstructor }, \
|
||||
{ &kMOZJSCOMPONENTLOADER_CID, false, NULL, mozJSComponentLoaderConstructor },\
|
||||
{ &kMOZ_JSSUBSCRIPTLOADER_CID, false, NULL, mozJSSubScriptLoaderConstructor },
|
||||
@ -49,7 +47,6 @@ NS_DEFINE_NAMED_CID(MOZ_JSSUBSCRIPTLOADER_CID);
|
||||
{ XPC_XPCONNECT_CONTRACTID, &kNS_XPCONNECT_CID }, \
|
||||
{ XPC_CONTEXT_STACK_CONTRACTID, &kNS_XPCONNECT_CID }, \
|
||||
{ XPC_RUNTIME_CONTRACTID, &kNS_XPCONNECT_CID }, \
|
||||
{ XPC_EXCEPTION_CONTRACTID, &kNS_XPCEXCEPTION_CID }, \
|
||||
{ NS_SCRIPTERROR_CONTRACTID, &kNS_SCRIPTERROR_CID }, \
|
||||
{ MOZJSCOMPONENTLOADER_CONTRACTID, &kMOZJSCOMPONENTLOADER_CID }, \
|
||||
{ MOZJSSUBSCRIPTLOADER_CONTRACTID, &kMOZ_JSSUBSCRIPTLOADER_CID },
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "XPCInlines.h"
|
||||
#include "XPCQuickStubs.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace JS;
|
||||
@ -250,7 +251,7 @@ ThrowCallFailed(JSContext *cx, nsresult rv,
|
||||
format, rv, ifaceName, memberName);
|
||||
}
|
||||
|
||||
XPCThrower::BuildAndThrowException(cx, rv, sz);
|
||||
dom::Throw(cx, rv, sz);
|
||||
|
||||
if (sz)
|
||||
JS_smprintf_free(sz);
|
||||
@ -336,7 +337,7 @@ ThrowBadArg(JSContext *cx, nsresult rv, const char *ifaceName,
|
||||
sz = JS_smprintf("%s arg %u [%s.%s]",
|
||||
format, (unsigned int) paramnum, ifaceName, memberName);
|
||||
|
||||
XPCThrower::BuildAndThrowException(cx, rv, sz);
|
||||
dom::Throw(cx, rv, sz);
|
||||
|
||||
if (sz)
|
||||
JS_smprintf_free(sz);
|
||||
|
@ -1,268 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Implements nsIStackFrame. */
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include "jsprf.h"
|
||||
#include "js/OldDebugAPI.h"
|
||||
|
||||
class XPCJSStackFrame : public nsIStackFrame
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSISTACKFRAME
|
||||
|
||||
static nsresult CreateStack(JSContext* cx, XPCJSStackFrame** stack);
|
||||
|
||||
static nsresult CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller,
|
||||
XPCJSStackFrame** stack);
|
||||
|
||||
XPCJSStackFrame();
|
||||
virtual ~XPCJSStackFrame();
|
||||
|
||||
bool IsJSFrame() const
|
||||
{return mLanguage == nsIProgrammingLanguage::JAVASCRIPT;}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIStackFrame> mCaller;
|
||||
|
||||
char* mFilename;
|
||||
char* mFunname;
|
||||
int32_t mLineno;
|
||||
uint32_t mLanguage;
|
||||
};
|
||||
|
||||
/**********************************************/
|
||||
|
||||
// static
|
||||
|
||||
nsresult
|
||||
XPCJSStack::CreateStack(JSContext* cx, nsIStackFrame** stack)
|
||||
{
|
||||
if (!cx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return XPCJSStackFrame::CreateStack(cx, (XPCJSStackFrame**) stack);
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
XPCJSStack::CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller,
|
||||
nsIStackFrame** stack)
|
||||
{
|
||||
return XPCJSStackFrame::CreateStackFrameLocation(aLanguage,
|
||||
aFilename,
|
||||
aFunctionName,
|
||||
aLineNumber,
|
||||
aCaller,
|
||||
(XPCJSStackFrame**) stack);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************/
|
||||
|
||||
XPCJSStackFrame::XPCJSStackFrame()
|
||||
: mFilename(nullptr),
|
||||
mFunname(nullptr),
|
||||
mLineno(0),
|
||||
mLanguage(nsIProgrammingLanguage::UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
XPCJSStackFrame::~XPCJSStackFrame()
|
||||
{
|
||||
if (mFilename)
|
||||
nsMemory::Free(mFilename);
|
||||
if (mFunname)
|
||||
nsMemory::Free(mFunname);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(XPCJSStackFrame, nsIStackFrame)
|
||||
|
||||
nsresult
|
||||
XPCJSStackFrame::CreateStack(JSContext* cx, XPCJSStackFrame** stack)
|
||||
{
|
||||
static const unsigned MAX_FRAMES = 100;
|
||||
|
||||
nsRefPtr<XPCJSStackFrame> first = new XPCJSStackFrame();
|
||||
nsRefPtr<XPCJSStackFrame> self = first;
|
||||
|
||||
JS::StackDescription* desc = JS::DescribeStack(cx, MAX_FRAMES);
|
||||
if (!desc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
for (size_t i = 0; i < desc->nframes && self; i++) {
|
||||
self->mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
|
||||
JSAutoCompartment ac(cx, desc->frames[i].script);
|
||||
const char* filename = JS_GetScriptFilename(cx, desc->frames[i].script);
|
||||
if (filename) {
|
||||
self->mFilename = (char*)
|
||||
nsMemory::Clone(filename,
|
||||
sizeof(char)*(strlen(filename)+1));
|
||||
}
|
||||
|
||||
self->mLineno = desc->frames[i].lineno;
|
||||
|
||||
JSFunction* fun = desc->frames[i].fun;
|
||||
if (fun) {
|
||||
JS::RootedString funid(cx, JS_GetFunctionDisplayId(fun));
|
||||
if (funid) {
|
||||
size_t length = JS_GetStringEncodingLength(cx, funid);
|
||||
if (length != size_t(-1)) {
|
||||
self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
|
||||
if (self->mFunname) {
|
||||
JS_EncodeStringToBuffer(cx, funid, self->mFunname, length);
|
||||
self->mFunname[length] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XPCJSStackFrame* frame = new XPCJSStackFrame();
|
||||
self->mCaller = frame;
|
||||
self = frame;
|
||||
}
|
||||
|
||||
JS::FreeStackDescription(cx, desc);
|
||||
|
||||
*stack = first.forget().get();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
XPCJSStackFrame::CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller,
|
||||
XPCJSStackFrame** stack)
|
||||
{
|
||||
bool failed = false;
|
||||
XPCJSStackFrame* self = new XPCJSStackFrame();
|
||||
if (self)
|
||||
NS_ADDREF(self);
|
||||
else
|
||||
failed = true;
|
||||
|
||||
if (!failed) {
|
||||
self->mLanguage = aLanguage;
|
||||
self->mLineno = aLineNumber;
|
||||
}
|
||||
|
||||
if (!failed && aFilename) {
|
||||
self->mFilename = (char*)
|
||||
nsMemory::Clone(aFilename,
|
||||
sizeof(char)*(strlen(aFilename)+1));
|
||||
if (!self->mFilename)
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (!failed && aFunctionName) {
|
||||
self->mFunname = (char*)
|
||||
nsMemory::Clone(aFunctionName,
|
||||
sizeof(char)*(strlen(aFunctionName)+1));
|
||||
if (!self->mFunname)
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (!failed && aCaller) {
|
||||
self->mCaller = aCaller;
|
||||
}
|
||||
|
||||
if (failed && self) {
|
||||
NS_RELEASE(self); // sets self to nullptr
|
||||
}
|
||||
|
||||
*stack = self;
|
||||
return self ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* readonly attribute uint32_t language; */
|
||||
NS_IMETHODIMP XPCJSStackFrame::GetLanguage(uint32_t *aLanguage)
|
||||
{
|
||||
*aLanguage = mLanguage;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string languageName; */
|
||||
NS_IMETHODIMP XPCJSStackFrame::GetLanguageName(char * *aLanguageName)
|
||||
{
|
||||
static const char js[] = "JavaScript";
|
||||
static const char cpp[] = "C++";
|
||||
char* temp;
|
||||
|
||||
if (IsJSFrame())
|
||||
*aLanguageName = temp = (char*) nsMemory::Clone(js, sizeof(js));
|
||||
else
|
||||
*aLanguageName = temp = (char*) nsMemory::Clone(cpp, sizeof(cpp));
|
||||
|
||||
return temp ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* readonly attribute string filename; */
|
||||
NS_IMETHODIMP XPCJSStackFrame::GetFilename(char * *aFilename)
|
||||
{
|
||||
XPC_STRING_GETTER_BODY(aFilename, mFilename);
|
||||
}
|
||||
|
||||
/* readonly attribute string name; */
|
||||
NS_IMETHODIMP XPCJSStackFrame::GetName(char * *aFunction)
|
||||
{
|
||||
XPC_STRING_GETTER_BODY(aFunction, mFunname);
|
||||
}
|
||||
|
||||
/* readonly attribute int32_t lineNumber; */
|
||||
NS_IMETHODIMP XPCJSStackFrame::GetLineNumber(int32_t *aLineNumber)
|
||||
{
|
||||
*aLineNumber = mLineno;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute string sourceLine; */
|
||||
NS_IMETHODIMP XPCJSStackFrame::GetSourceLine(char * *aSourceLine)
|
||||
{
|
||||
*aSourceLine = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIStackFrame caller; */
|
||||
NS_IMETHODIMP XPCJSStackFrame::GetCaller(nsIStackFrame * *aCaller)
|
||||
{
|
||||
NS_IF_ADDREF(*aCaller = mCaller);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* string toString (); */
|
||||
NS_IMETHODIMP XPCJSStackFrame::ToString(char **_retval)
|
||||
{
|
||||
const char* frametype = IsJSFrame() ? "JS" : "native";
|
||||
const char* filename = mFilename ? mFilename : "<unknown filename>";
|
||||
const char* funname = mFunname ? mFunname : "<TOP_LEVEL>";
|
||||
static const char format[] = "%s frame :: %s :: %s :: line %d";
|
||||
int len = sizeof(char)*
|
||||
(strlen(frametype) + strlen(filename) + strlen(funname)) +
|
||||
sizeof(format) + 6 /* space for lineno */;
|
||||
|
||||
char* buf = (char*) nsMemory::Alloc(len);
|
||||
if (!buf)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
JS_snprintf(buf, len, format, frametype, filename, funname, mLineno);
|
||||
*_retval = buf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -10,8 +10,11 @@
|
||||
#include "xpcpublic.h"
|
||||
#include "XPCWrapper.h"
|
||||
#include "jsprf.h"
|
||||
#include "nsDOMException.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
bool XPCThrower::sVerbose = true;
|
||||
|
||||
@ -24,7 +27,7 @@ XPCThrower::Throw(nsresult rv, JSContext* cx)
|
||||
return;
|
||||
if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
|
||||
format = "";
|
||||
BuildAndThrowException(cx, rv, format);
|
||||
dom::Throw(cx, rv, format);
|
||||
}
|
||||
|
||||
namespace xpc {
|
||||
@ -56,7 +59,7 @@ XPCThrower::CheckForPendingException(nsresult result, JSContext *cx)
|
||||
if (NS_FAILED(e->GetResult(&e_result)) || e_result != result)
|
||||
return false;
|
||||
|
||||
if (!ThrowExceptionObject(cx, static_cast<nsXPCException*>(e.get())))
|
||||
if (!ThrowExceptionObject(cx, e))
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return true;
|
||||
}
|
||||
@ -79,7 +82,7 @@ XPCThrower::Throw(nsresult rv, XPCCallContext& ccx)
|
||||
if (sz && sVerbose)
|
||||
Verbosify(ccx, &sz, false);
|
||||
|
||||
BuildAndThrowException(ccx, rv, sz);
|
||||
dom::Throw(ccx, rv, sz);
|
||||
|
||||
if (sz && sz != format)
|
||||
JS_smprintf_free(sz);
|
||||
@ -117,7 +120,7 @@ XPCThrower::ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx)
|
||||
if (sz && sVerbose)
|
||||
Verbosify(ccx, &sz, true);
|
||||
|
||||
BuildAndThrowException(ccx, result, sz);
|
||||
dom::Throw(ccx, result, sz);
|
||||
|
||||
if (sz)
|
||||
JS_smprintf_free(sz);
|
||||
@ -138,7 +141,7 @@ XPCThrower::ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx)
|
||||
if (sz && sVerbose)
|
||||
Verbosify(ccx, &sz, true);
|
||||
|
||||
BuildAndThrowException(ccx, rv, sz);
|
||||
dom::Throw(ccx, rv, sz);
|
||||
|
||||
if (sz)
|
||||
JS_smprintf_free(sz);
|
||||
@ -169,104 +172,3 @@ XPCThrower::Verbosify(XPCCallContext& ccx,
|
||||
*psz = sz;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
XPCThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
/* no need to set an expection if the security manager already has */
|
||||
if (rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO && JS_IsExceptionPending(cx))
|
||||
return;
|
||||
|
||||
XPCJSRuntime* runtime = XPCJSRuntime::Get();
|
||||
nsCOMPtr<nsIException> existingException = runtime->GetPendingException();
|
||||
if (existingException) {
|
||||
nsresult nr;
|
||||
if (NS_SUCCEEDED(existingException->GetResult(&nr)) &&
|
||||
rv == nr) {
|
||||
// Just reuse the existing exception.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
finalException = NS_NewDOMException(rv);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If not, use the default.
|
||||
if (finalException == nullptr) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCallerChrome(JSContext* cx)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan;
|
||||
secMan = XPCWrapper::GetSecurityManager();
|
||||
|
||||
if (!secMan)
|
||||
return false;
|
||||
|
||||
bool isChrome;
|
||||
rv = secMan->SubjectPrincipalIsSystem(&isChrome);
|
||||
return NS_SUCCEEDED(rv) && isChrome;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
XPCThrower::ThrowExceptionObject(JSContext* cx, nsXPCException* e)
|
||||
{
|
||||
bool success = false;
|
||||
if (e) {
|
||||
JS::RootedValue thrown(cx);
|
||||
|
||||
// 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) &&
|
||||
NS_SUCCEEDED(e->StealJSVal(thrown.address()))) {
|
||||
if (!JS_WrapValue(cx, thrown.address()))
|
||||
return false;
|
||||
JS_SetPendingException(cx, thrown);
|
||||
success = true;
|
||||
} else {
|
||||
JS::RootedObject glob(cx, JS::CurrentGlobalOrNull(cx));
|
||||
if (!glob)
|
||||
return false;
|
||||
|
||||
JS::RootedValue val(cx);
|
||||
if (mozilla::dom::WrapNewBindingObject(cx, glob, e, &val)) {
|
||||
JS_SetPendingException(cx, val);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsJSUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
@ -264,7 +265,7 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
|
||||
// XPConnect may have constructed an object to represent a
|
||||
// C++ QI failure. See if that is the case.
|
||||
using namespace mozilla::dom;
|
||||
nsXPCException *e = nullptr;
|
||||
Exception *e = nullptr;
|
||||
UNWRAP_OBJECT(Exception, cx, &jsexception.toObject(), e);
|
||||
|
||||
if (e &&
|
||||
|
@ -34,7 +34,6 @@ CPP_SOURCES += [
|
||||
'XPCModule.cpp',
|
||||
'XPCQuickStubs.cpp',
|
||||
'XPCRuntimeService.cpp',
|
||||
'XPCStack.cpp',
|
||||
'XPCString.cpp',
|
||||
'XPCThrower.cpp',
|
||||
'XPCVariant.cpp',
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "XPCQuickStubs.h"
|
||||
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
#include "mozilla/dom/IDBIndexBinding.h"
|
||||
#include "mozilla/dom/IDBObjectStoreBinding.h"
|
||||
#include "mozilla/dom/IDBOpenDBRequestBinding.h"
|
||||
@ -863,12 +864,14 @@ nsXPConnect::CreateStackFrameLocation(uint32_t aLanguage,
|
||||
{
|
||||
MOZ_ASSERT(_retval, "bad param");
|
||||
|
||||
return XPCJSStack::CreateStackFrameLocation(aLanguage,
|
||||
aFilename,
|
||||
aFunctionName,
|
||||
aLineNumber,
|
||||
aCaller,
|
||||
_retval);
|
||||
nsCOMPtr<nsIStackFrame> stackFrame =
|
||||
exceptions::CreateStackFrameLocation(aLanguage,
|
||||
aFilename,
|
||||
aFunctionName,
|
||||
aLineNumber,
|
||||
aCaller);
|
||||
stackFrame.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIStackFrame CurrentJSStack; */
|
||||
@ -880,8 +883,7 @@ nsXPConnect::GetCurrentJSStack(nsIStackFrame * *aCurrentJSStack)
|
||||
|
||||
// is there a current context available?
|
||||
if (JSContext *cx = GetCurrentJSContext()) {
|
||||
nsCOMPtr<nsIStackFrame> stack;
|
||||
XPCJSStack::CreateStack(cx, getter_AddRefs(stack));
|
||||
nsCOMPtr<nsIStackFrame> stack = exceptions::CreateStack(cx);
|
||||
if (stack) {
|
||||
// peel off native frames...
|
||||
uint32_t language;
|
||||
|
@ -739,17 +739,6 @@ public:
|
||||
|
||||
~XPCJSRuntime();
|
||||
|
||||
already_AddRefed<nsIException> GetPendingException()
|
||||
{
|
||||
nsCOMPtr<nsIException> out = mPendingException;
|
||||
return out.forget();
|
||||
}
|
||||
|
||||
void SetPendingException(nsIException* aException)
|
||||
{
|
||||
mPendingException = aException;
|
||||
}
|
||||
|
||||
XPCReadableJSStringWrapper *NewStringWrapper(const PRUnichar *str, uint32_t len);
|
||||
void DeleteString(nsAString *string);
|
||||
|
||||
@ -831,8 +820,6 @@ private:
|
||||
|
||||
mozilla::TimeStamp mSlowScriptCheckpoint;
|
||||
|
||||
nsCOMPtr<nsIException> mPendingException;
|
||||
|
||||
#define XPCCCX_STRING_CACHE_SIZE 2
|
||||
|
||||
// String wrapper entry, holds a string, and a boolean that tells
|
||||
@ -2943,54 +2930,21 @@ public:
|
||||
static bool SetVerbosity(bool state)
|
||||
{bool old = sVerbose; sVerbose = state; return old;}
|
||||
|
||||
static void BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz);
|
||||
static bool CheckForPendingException(nsresult result, JSContext *cx);
|
||||
|
||||
private:
|
||||
static void Verbosify(XPCCallContext& ccx,
|
||||
char** psz, bool own);
|
||||
|
||||
static bool ThrowExceptionObject(JSContext* cx, nsXPCException* e);
|
||||
|
||||
private:
|
||||
static bool sVerbose;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
class XPCJSStack
|
||||
class nsXPCException
|
||||
{
|
||||
public:
|
||||
static nsresult
|
||||
CreateStack(JSContext* cx, nsIStackFrame** stack);
|
||||
|
||||
static nsresult
|
||||
CreateStackFrameLocation(uint32_t aLanguage,
|
||||
const char* aFilename,
|
||||
const char* aFunctionName,
|
||||
int32_t aLineNumber,
|
||||
nsIStackFrame* aCaller,
|
||||
nsIStackFrame** stack);
|
||||
private:
|
||||
XPCJSStack(); // not implemented
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
class nsXPCException :
|
||||
public nsIXPCException,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCEXCEPTION_CID)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXPCException)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_NSIEXCEPTION
|
||||
NS_DECL_NSIXPCEXCEPTION
|
||||
|
||||
static bool NameAndFormatForNSResult(nsresult rv,
|
||||
const char** name,
|
||||
const char** format);
|
||||
@ -3001,58 +2955,6 @@ public:
|
||||
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();
|
||||
|
||||
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();
|
||||
|
||||
char* mMessage;
|
||||
nsresult mResult;
|
||||
char* mName;
|
||||
nsIStackFrame* mLocation;
|
||||
nsISupports* mData;
|
||||
char* mFilename;
|
||||
int mLineNumber;
|
||||
nsIException* mInner;
|
||||
bool mInitialized;
|
||||
|
||||
nsAutoJSValHolder mThrownJSVal;
|
||||
|
||||
private:
|
||||
static bool sEverMadeOneFromFactory;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -68,7 +68,6 @@
|
||||
|
||||
// DOM includes
|
||||
#include "nsDOMBlobBuilder.h"
|
||||
#include "nsDOMException.h"
|
||||
#include "nsDOMFileReader.h"
|
||||
|
||||
#include "nsFormData.h"
|
||||
@ -85,6 +84,7 @@
|
||||
#include "mozIApplicationClearPrivateDataParams.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/Activity.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "mozilla/dom/EventSource.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
@ -275,6 +275,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaSourceProtocolHandler)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontTableProtocolHandler)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHostObjectURI)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(DOMParser)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(Exception)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(DOMSessionStorageManager)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(DOMLocalStorageManager)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsChannelPolicy)
|
||||
@ -1027,6 +1028,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
||||
{ &kNS_EVENTSOURCE_CID, false, NULL, EventSourceConstructor },
|
||||
{ &kNS_DOMACTIVITY_CID, false, NULL, ActivityConstructor },
|
||||
{ &kNS_DOMPARSER_CID, false, NULL, DOMParserConstructor },
|
||||
{ &kNS_XPCEXCEPTION_CID, false, NULL, ExceptionConstructor },
|
||||
{ &kNS_DOMSESSIONSTORAGEMANAGER_CID, false, NULL, DOMSessionStorageManagerConstructor },
|
||||
{ &kNS_DOMLOCALSTORAGEMANAGER_CID, false, NULL, DOMLocalStorageManagerConstructor },
|
||||
{ &kNS_DOMJSON_CID, false, NULL, NS_NewJSON },
|
||||
@ -1181,6 +1183,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
||||
{ NS_EVENTSOURCE_CONTRACTID, &kNS_EVENTSOURCE_CID },
|
||||
{ NS_DOMACTIVITY_CONTRACTID, &kNS_DOMACTIVITY_CID },
|
||||
{ NS_DOMPARSER_CONTRACTID, &kNS_DOMPARSER_CID },
|
||||
{ XPC_EXCEPTION_CONTRACTID, &kNS_XPCEXCEPTION_CID },
|
||||
{ "@mozilla.org/dom/localStorage-manager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },
|
||||
// Keeping the old ContractID for backward compatibility
|
||||
{ "@mozilla.org/dom/storagemanager;1", &kNS_DOMLOCALSTORAGEMANAGER_CID },
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsIException.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
@ -463,6 +464,9 @@ CycleCollectedJSRuntime::~CycleCollectedJSRuntime()
|
||||
MOZ_ASSERT(!mDeferredFinalizerTable.Count());
|
||||
MOZ_ASSERT(!mDeferredSupports.Length());
|
||||
|
||||
// Clear mPendingException first, since it might be cycle collected.
|
||||
mPendingException = nullptr;
|
||||
|
||||
nsCycleCollector_forgetJSRuntime();
|
||||
|
||||
JS_DestroyRuntime(mJSRuntime);
|
||||
@ -828,6 +832,19 @@ CycleCollectedJSRuntime::AssertNoObjectsToTrace(void* aPossibleJSHolder)
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<nsIException>
|
||||
CycleCollectedJSRuntime::GetPendingException() const
|
||||
{
|
||||
nsCOMPtr<nsIException> out = mPendingException;
|
||||
return out.forget();
|
||||
}
|
||||
|
||||
void
|
||||
CycleCollectedJSRuntime::SetPendingException(nsIException* aException)
|
||||
{
|
||||
mPendingException = aException;
|
||||
}
|
||||
|
||||
nsCycleCollectionParticipant*
|
||||
CycleCollectedJSRuntime::GCThingParticipant()
|
||||
{
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
class nsCycleCollectionNoteRootCallback;
|
||||
class nsScriptObjectTracer;
|
||||
class nsIException;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -172,6 +173,9 @@ public:
|
||||
void AssertNoObjectsToTrace(void* aPossibleJSHolder);
|
||||
#endif
|
||||
|
||||
already_AddRefed<nsIException> GetPendingException() const;
|
||||
void SetPendingException(nsIException* aException);
|
||||
|
||||
nsCycleCollectionParticipant* GCThingParticipant();
|
||||
nsCycleCollectionParticipant* ZoneParticipant();
|
||||
|
||||
@ -198,6 +202,12 @@ public:
|
||||
MOZ_ASSERT(mJSRuntime);
|
||||
return mJSRuntime;
|
||||
}
|
||||
|
||||
// Get the current thread's CycleCollectedJSRuntime. Returns null if there
|
||||
// isn't one.
|
||||
static CycleCollectedJSRuntime*
|
||||
Get();
|
||||
|
||||
private:
|
||||
JSGCThingParticipant mGCThingCycleCollectorGlobal;
|
||||
|
||||
@ -214,6 +224,8 @@ private:
|
||||
|
||||
nsRefPtr<IncrementalFinalizeRunnable> mFinalizeRunnable;
|
||||
|
||||
nsCOMPtr<nsIException> mPendingException;
|
||||
|
||||
#ifdef DEBUG
|
||||
void* mObjectToUnlink;
|
||||
#endif
|
||||
|
@ -2903,8 +2903,8 @@ nsCycleCollector_forgetJSRuntime()
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::CycleCollectedJSRuntime*
|
||||
nsCycleCollector_currentJSRuntime()
|
||||
/* static */ CycleCollectedJSRuntime*
|
||||
CycleCollectedJSRuntime::Get()
|
||||
{
|
||||
CollectorData* data = sCollectorData.get();
|
||||
if (data) {
|
||||
|
@ -64,7 +64,6 @@ void nsCycleCollector_shutdown();
|
||||
// Helpers for interacting with JS
|
||||
void nsCycleCollector_registerJSRuntime(mozilla::CycleCollectedJSRuntime *aRt);
|
||||
void nsCycleCollector_forgetJSRuntime();
|
||||
mozilla::CycleCollectedJSRuntime* nsCycleCollector_currentJSRuntime();
|
||||
|
||||
#define NS_CYCLE_COLLECTOR_LOGGER_CID \
|
||||
{ 0x58be81b4, 0x39d2, 0x437c, \
|
||||
|
Loading…
Reference in New Issue
Block a user