michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/dom/DOMException.h" michael@0: michael@0: #include "jsprf.h" michael@0: #include "js/OldDebugAPI.h" michael@0: #include "mozilla/ArrayUtils.h" michael@0: #include "mozilla/HoldDropJSObjects.h" michael@0: #include "mozilla/dom/Exceptions.h" michael@0: #include "nsContentUtils.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIClassInfoImpl.h" michael@0: #include "nsIDocument.h" michael@0: #include "nsIDOMDOMException.h" michael@0: #include "nsIException.h" michael@0: #include "nsIProgrammingLanguage.h" michael@0: #include "nsMemory.h" michael@0: #include "prprf.h" michael@0: #include "xpcprivate.h" michael@0: michael@0: #include "mozilla/dom/DOMExceptionBinding.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: enum DOM4ErrorTypeCodeMap { michael@0: /* DOM4 errors from http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#domexception */ michael@0: IndexSizeError = nsIDOMDOMException::INDEX_SIZE_ERR, michael@0: HierarchyRequestError = nsIDOMDOMException::HIERARCHY_REQUEST_ERR, michael@0: WrongDocumentError = nsIDOMDOMException::WRONG_DOCUMENT_ERR, michael@0: InvalidCharacterError = nsIDOMDOMException::INVALID_CHARACTER_ERR, michael@0: NoModificationAllowedError = nsIDOMDOMException::NO_MODIFICATION_ALLOWED_ERR, michael@0: NotFoundError = nsIDOMDOMException::NOT_FOUND_ERR, michael@0: NotSupportedError = nsIDOMDOMException::NOT_SUPPORTED_ERR, michael@0: // Can't remove until setNamedItem is removed michael@0: InUseAttributeError = nsIDOMDOMException::INUSE_ATTRIBUTE_ERR, michael@0: InvalidStateError = nsIDOMDOMException::INVALID_STATE_ERR, michael@0: SyntaxError = nsIDOMDOMException::SYNTAX_ERR, michael@0: InvalidModificationError = nsIDOMDOMException::INVALID_MODIFICATION_ERR, michael@0: NamespaceError = nsIDOMDOMException::NAMESPACE_ERR, michael@0: InvalidAccessError = nsIDOMDOMException::INVALID_ACCESS_ERR, michael@0: TypeMismatchError = nsIDOMDOMException::TYPE_MISMATCH_ERR, michael@0: SecurityError = nsIDOMDOMException::SECURITY_ERR, michael@0: NetworkError = nsIDOMDOMException::NETWORK_ERR, michael@0: AbortError = nsIDOMDOMException::ABORT_ERR, michael@0: URLMismatchError = nsIDOMDOMException::URL_MISMATCH_ERR, michael@0: QuotaExceededError = nsIDOMDOMException::QUOTA_EXCEEDED_ERR, michael@0: TimeoutError = nsIDOMDOMException::TIMEOUT_ERR, michael@0: InvalidNodeTypeError = nsIDOMDOMException::INVALID_NODE_TYPE_ERR, michael@0: DataCloneError = nsIDOMDOMException::DATA_CLONE_ERR, michael@0: InvalidPointerId = nsIDOMDOMException::INVALID_POINTER_ERR, michael@0: EncodingError = 0, michael@0: michael@0: /* XXX Should be JavaScript native errors */ michael@0: TypeError = 0, michael@0: RangeError = 0, michael@0: michael@0: /* IndexedDB errors http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#exceptions */ michael@0: UnknownError = 0, michael@0: ConstraintError = 0, michael@0: DataError = 0, michael@0: TransactionInactiveError = 0, michael@0: ReadOnlyError = 0, michael@0: VersionError = 0, michael@0: michael@0: /* File API errors http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException */ michael@0: NotReadableError = 0, michael@0: michael@0: /* FileHandle API errors */ michael@0: LockedFileInactiveError = 0, michael@0: }; michael@0: michael@0: #define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message}, michael@0: #define DOM_MSG_DEF(val, message) {(val), NS_ERROR_GET_CODE(val), #val, message}, michael@0: michael@0: static const struct ResultStruct michael@0: { michael@0: nsresult mNSResult; michael@0: uint16_t mCode; michael@0: const char* mName; michael@0: const char* mMessage; michael@0: } sDOMErrorMsgMap[] = { michael@0: #include "domerr.msg" michael@0: }; michael@0: michael@0: #undef DOM4_MSG_DEF michael@0: #undef DOM_MSG_DEF michael@0: michael@0: static void michael@0: NSResultToNameAndMessage(nsresult aNSResult, michael@0: nsCString& aName, michael@0: nsCString& aMessage, michael@0: uint16_t* aCode) michael@0: { michael@0: aName.Truncate(); michael@0: aMessage.Truncate(); michael@0: *aCode = 0; michael@0: for (uint32_t idx = 0; idx < ArrayLength(sDOMErrorMsgMap); idx++) { michael@0: if (aNSResult == sDOMErrorMsgMap[idx].mNSResult) { michael@0: aName.Rebind(sDOMErrorMsgMap[idx].mName, michael@0: strlen(sDOMErrorMsgMap[idx].mName)); michael@0: aMessage.Rebind(sDOMErrorMsgMap[idx].mMessage, michael@0: strlen(sDOMErrorMsgMap[idx].mMessage)); michael@0: *aCode = sDOMErrorMsgMap[idx].mCode; michael@0: return; michael@0: } michael@0: } michael@0: michael@0: NS_WARNING("Huh, someone is throwing non-DOM errors using the DOM module!"); michael@0: michael@0: return; michael@0: } michael@0: michael@0: nsresult michael@0: NS_GetNameAndMessageForDOMNSResult(nsresult aNSResult, nsACString& aName, michael@0: nsACString& aMessage, uint16_t* aCode) michael@0: { michael@0: nsCString name; michael@0: nsCString message; michael@0: uint16_t code = 0; michael@0: NSResultToNameAndMessage(aNSResult, name, message, &code); michael@0: michael@0: if (!name.IsEmpty() && !message.IsEmpty()) { michael@0: aName = name; michael@0: aMessage = message; michael@0: if (aCode) { michael@0: *aCode = code; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: bool Exception::sEverMadeOneFromFactory = false; michael@0: michael@0: NS_IMPL_CLASSINFO(Exception, nullptr, nsIClassInfo::DOM_OBJECT, michael@0: NS_XPCEXCEPTION_CID) michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Exception) michael@0: NS_INTERFACE_MAP_ENTRY(nsIException) michael@0: NS_INTERFACE_MAP_ENTRY(nsIXPCException) michael@0: NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException) michael@0: NS_IMPL_QUERY_CLASSINFO(Exception) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(Exception) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(Exception) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_CLASS(Exception) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Exception) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInner) michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS michael@0: NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Exception) michael@0: NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER michael@0: NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mThrownJSVal); michael@0: NS_IMPL_CYCLE_COLLECTION_TRACE_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Exception) michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation) michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK(mInner) michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER michael@0: tmp->mThrownJSVal.setNull(); michael@0: NS_IMPL_CYCLE_COLLECTION_UNLINK_END michael@0: michael@0: NS_IMPL_CI_INTERFACE_GETTER(Exception, nsIXPCException) michael@0: michael@0: Exception::Exception(const nsACString& aMessage, michael@0: nsresult aResult, michael@0: const nsACString& aName, michael@0: nsIStackFrame *aLocation, michael@0: nsISupports *aData) michael@0: : mResult(NS_OK), michael@0: mLineNumber(0), michael@0: mInitialized(false), michael@0: mHoldingJSVal(false) michael@0: { michael@0: SetIsDOMBinding(); michael@0: michael@0: // A little hack... The nsIGenericModule nsIClassInfo scheme relies on there michael@0: // having been at least one instance made via the factory. Otherwise, the michael@0: // shared factory/classinsance object never gets created and our QI getter michael@0: // for our instance's pointer to our nsIClassInfo will always return null. michael@0: // This is bad because it means that wrapped exceptions will never have a michael@0: // shared prototype. So... We force one to be created via the factory michael@0: // *once* and then go about our business. michael@0: if (!sEverMadeOneFromFactory) { michael@0: nsCOMPtr e = michael@0: do_CreateInstance(XPC_EXCEPTION_CONTRACTID); michael@0: sEverMadeOneFromFactory = true; michael@0: } michael@0: michael@0: nsCOMPtr location; michael@0: if (aLocation) { michael@0: location = aLocation; michael@0: } else { michael@0: location = GetCurrentJSStack(); michael@0: // it is legal for there to be no active JS stack, if C++ code michael@0: // is operating on a JS-implemented interface pointer without michael@0: // having been called in turn by JS. This happens in the JS michael@0: // component loader, and will become more common as additional michael@0: // components are implemented in JS. michael@0: } michael@0: // We want to trim off any leading native 'dataless' frames michael@0: if (location) { michael@0: while (1) { michael@0: uint32_t language; michael@0: int32_t lineNumber; michael@0: if (NS_FAILED(location->GetLanguage(&language)) || michael@0: language == nsIProgrammingLanguage::JAVASCRIPT || michael@0: NS_FAILED(location->GetLineNumber(&lineNumber)) || michael@0: lineNumber) { michael@0: break; michael@0: } michael@0: nsCOMPtr caller; michael@0: if (NS_FAILED(location->GetCaller(getter_AddRefs(caller))) || !caller) { michael@0: break; michael@0: } michael@0: location = caller; michael@0: } michael@0: } michael@0: michael@0: Initialize(aMessage, aResult, aName, location, aData, nullptr); michael@0: } michael@0: michael@0: Exception::Exception() michael@0: : mResult(NS_OK), michael@0: mLineNumber(-1), michael@0: mInitialized(false), michael@0: mHoldingJSVal(false) michael@0: { michael@0: } michael@0: michael@0: Exception::~Exception() michael@0: { michael@0: if (mHoldingJSVal) { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: mozilla::DropJSObjects(this); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: Exception::StealJSVal(JS::Value* aVp) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: if (mHoldingJSVal) { michael@0: *aVp = mThrownJSVal; michael@0: mThrownJSVal.setNull(); michael@0: michael@0: mozilla::DropJSObjects(this); michael@0: mHoldingJSVal = false; michael@0: return true; michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: void michael@0: Exception::StowJSVal(JS::Value& aVp) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: mThrownJSVal = aVp; michael@0: if (!mHoldingJSVal) { michael@0: mozilla::HoldJSObjects(this); michael@0: mHoldingJSVal = true; michael@0: } michael@0: } michael@0: michael@0: /* readonly attribute AUTF8String message; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetMessageMoz(nsACString& aMessage) michael@0: { michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: aMessage.Assign(mMessage); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsresult result; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetResult(nsresult* aResult) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aResult); michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: *aResult = mResult; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute AUTF8String name; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetName(nsACString& aName) michael@0: { michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: if (!mName.IsEmpty()) { michael@0: aName.Assign(mName); michael@0: } else { michael@0: aName.Truncate(); michael@0: michael@0: const char* name = nullptr; michael@0: nsXPCException::NameAndFormatForNSResult(mResult, &name, nullptr); michael@0: michael@0: if (name) { michael@0: aName.Assign(name); michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute AString filename; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetFilename(nsAString& aFilename) michael@0: { michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: if (mLocation) { michael@0: return mLocation->GetFilename(aFilename); michael@0: } michael@0: michael@0: aFilename.Assign(mFilename); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t lineNumber; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetLineNumber(uint32_t *aLineNumber) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aLineNumber); michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: if (mLocation) { michael@0: int32_t lineno; michael@0: nsresult rv = mLocation->GetLineNumber(&lineno); michael@0: *aLineNumber = lineno; michael@0: return rv; michael@0: } michael@0: michael@0: *aLineNumber = mLineNumber; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute uint32_t columnNumber; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetColumnNumber(uint32_t* aColumnNumber) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aColumnNumber); michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: *aColumnNumber = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsIStackFrame location; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetLocation(nsIStackFrame** aLocation) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aLocation); michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: nsCOMPtr location = mLocation; michael@0: location.forget(aLocation); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsISupports data; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetData(nsISupports** aData) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aData); michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: nsCOMPtr data = mData; michael@0: data.forget(aData); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute nsIException inner; */ michael@0: NS_IMETHODIMP michael@0: Exception::GetInner(nsIException** aException) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aException); michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: nsCOMPtr inner = mInner; michael@0: inner.forget(aException); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* AUTF8String toString (); */ michael@0: NS_IMETHODIMP michael@0: Exception::ToString(nsACString& _retval) michael@0: { michael@0: NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: static const char defaultMsg[] = ""; michael@0: static const char defaultLocation[] = ""; michael@0: static const char format[] = michael@0: "[Exception... \"%s\" nsresult: \"0x%x (%s)\" location: \"%s\" data: %s]"; michael@0: michael@0: nsCString location; michael@0: michael@0: if (mLocation) { michael@0: // we need to free this if it does not fail michael@0: nsresult rv = mLocation->ToString(location); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: if (location.IsEmpty()) { michael@0: location.Assign(defaultLocation); michael@0: } michael@0: michael@0: const char* msg = mMessage.IsEmpty() ? nullptr : mMessage.get(); michael@0: michael@0: const char* resultName = mName.IsEmpty() ? nullptr: mName.get(); michael@0: if (!resultName && michael@0: !nsXPCException::NameAndFormatForNSResult(mResult, &resultName, michael@0: (!msg) ? &msg : nullptr)) { michael@0: if (!msg) { michael@0: msg = defaultMsg; michael@0: } michael@0: resultName = ""; michael@0: } michael@0: const char* data = mData ? "yes" : "no"; michael@0: michael@0: _retval.Truncate(); michael@0: _retval.AppendPrintf(format, msg, mResult, resultName, michael@0: location.get(), data); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void initialize (in AUTF8String aMessage, in nsresult aResult, michael@0: * in AUTF8String aName, in nsIStackFrame aLocation, michael@0: * in nsISupports aData, in nsIException aInner); */ michael@0: NS_IMETHODIMP michael@0: Exception::Initialize(const nsACString& aMessage, nsresult aResult, michael@0: const nsACString& aName, nsIStackFrame *aLocation, michael@0: nsISupports *aData, nsIException *aInner) michael@0: { michael@0: NS_ENSURE_FALSE(mInitialized, NS_ERROR_ALREADY_INITIALIZED); michael@0: michael@0: mMessage = aMessage; michael@0: mName = aName; michael@0: mResult = aResult; michael@0: michael@0: if (aLocation) { michael@0: mLocation = aLocation; michael@0: } else { michael@0: nsresult rv; michael@0: nsXPConnect* xpc = nsXPConnect::XPConnect(); michael@0: rv = xpc->GetCurrentJSStack(getter_AddRefs(mLocation)); michael@0: if (NS_FAILED(rv)) { michael@0: return rv; michael@0: } michael@0: } michael@0: michael@0: mData = aData; michael@0: mInner = aInner; michael@0: michael@0: mInitialized = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: JSObject* michael@0: Exception::WrapObject(JSContext* cx) michael@0: { michael@0: return ExceptionBinding::Wrap(cx, this); michael@0: } michael@0: michael@0: void michael@0: Exception::GetMessageMoz(nsString& retval) michael@0: { michael@0: nsCString str; michael@0: #ifdef DEBUG michael@0: DebugOnly rv = michael@0: #endif michael@0: GetMessageMoz(str); michael@0: MOZ_ASSERT(NS_SUCCEEDED(rv)); michael@0: CopyUTF8toUTF16(str, retval); michael@0: } michael@0: michael@0: uint32_t michael@0: Exception::Result() const michael@0: { michael@0: return (uint32_t)mResult; michael@0: } michael@0: michael@0: void michael@0: Exception::GetName(nsString& retval) michael@0: { michael@0: nsCString str; michael@0: #ifdef DEBUG michael@0: DebugOnly rv = michael@0: #endif michael@0: GetName(str); michael@0: MOZ_ASSERT(NS_SUCCEEDED(rv)); michael@0: CopyUTF8toUTF16(str, retval); michael@0: } michael@0: michael@0: uint32_t michael@0: Exception::LineNumber() const michael@0: { michael@0: if (mLocation) { michael@0: int32_t lineno; michael@0: if (NS_SUCCEEDED(mLocation->GetLineNumber(&lineno))) { michael@0: return lineno; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: return mLineNumber; michael@0: } michael@0: michael@0: uint32_t michael@0: Exception::ColumnNumber() const michael@0: { michael@0: return 0; michael@0: } michael@0: michael@0: already_AddRefed michael@0: Exception::GetLocation() const michael@0: { michael@0: nsCOMPtr location = mLocation; michael@0: return location.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: Exception::GetInner() const michael@0: { michael@0: nsCOMPtr inner = mInner; michael@0: return inner.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: Exception::GetData() const michael@0: { michael@0: nsCOMPtr data = mData; michael@0: return data.forget(); michael@0: } michael@0: michael@0: void michael@0: Exception::Stringify(nsString& retval) michael@0: { michael@0: nsCString str; michael@0: #ifdef DEBUG michael@0: DebugOnly rv = michael@0: #endif michael@0: ToString(str); michael@0: MOZ_ASSERT(NS_SUCCEEDED(rv)); michael@0: CopyUTF8toUTF16(str, retval); michael@0: } michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(DOMException, Exception) michael@0: NS_IMPL_RELEASE_INHERITED(DOMException, Exception) michael@0: NS_INTERFACE_MAP_BEGIN(DOMException) michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMDOMException) michael@0: NS_INTERFACE_MAP_END_INHERITING(Exception) michael@0: michael@0: DOMException::DOMException(nsresult aRv, const nsACString& aMessage, michael@0: const nsACString& aName, uint16_t aCode) michael@0: : Exception(EmptyCString(), aRv, EmptyCString(), nullptr, nullptr), michael@0: mName(aName), michael@0: mMessage(aMessage), michael@0: mCode(aCode) michael@0: { michael@0: SetIsDOMBinding(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DOMException::GetCode(uint16_t* aCode) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aCode); michael@0: *aCode = mCode; michael@0: michael@0: // Warn only when the code was changed (other than DOM Core) michael@0: // or the code is useless (zero) michael@0: if (NS_ERROR_GET_MODULE(mResult) != NS_ERROR_MODULE_DOM || !mCode) { michael@0: nsCOMPtr doc = nsContentUtils::GetDocumentFromCaller(); michael@0: if (doc) { michael@0: doc->WarnOnceAbout(nsIDocument::eDOMExceptionCode); michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DOMException::ToString(nsACString& aReturn) michael@0: { michael@0: aReturn.Truncate(); michael@0: michael@0: static const char defaultMsg[] = ""; michael@0: static const char defaultLocation[] = ""; michael@0: static const char defaultName[] = ""; michael@0: static const char format[] = michael@0: "[Exception... \"%s\" code: \"%d\" nsresult: \"0x%x (%s)\" location: \"%s\"]"; michael@0: michael@0: nsAutoCString location; michael@0: michael@0: if (mInner) { michael@0: nsString filename; michael@0: mInner->GetFilename(filename); michael@0: michael@0: if (!filename.IsEmpty()) { michael@0: uint32_t line_nr = 0; michael@0: michael@0: mInner->GetLineNumber(&line_nr); michael@0: michael@0: char *temp = PR_smprintf("%s Line: %d", michael@0: NS_ConvertUTF16toUTF8(filename).get(), michael@0: line_nr); michael@0: if (temp) { michael@0: location.Assign(temp); michael@0: PR_smprintf_free(temp); michael@0: } michael@0: } michael@0: } michael@0: michael@0: if (location.IsEmpty()) { michael@0: location = defaultLocation; michael@0: } michael@0: michael@0: const char* msg = !mMessage.IsEmpty() ? mMessage.get() : defaultMsg; michael@0: const char* resultName = !mName.IsEmpty() ? mName.get() : defaultName; michael@0: michael@0: aReturn.AppendPrintf(format, msg, mCode, mResult, resultName, michael@0: location.get()); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: DOMException::GetName(nsString& retval) michael@0: { michael@0: CopyUTF8toUTF16(mName, retval); michael@0: } michael@0: michael@0: void michael@0: DOMException::GetMessageMoz(nsString& retval) michael@0: { michael@0: CopyUTF8toUTF16(mMessage, retval); michael@0: } michael@0: michael@0: JSObject* michael@0: DOMException::WrapObject(JSContext* aCx) michael@0: { michael@0: return DOMExceptionBinding::Wrap(aCx, this); michael@0: } michael@0: michael@0: /* static */already_AddRefed michael@0: DOMException::Create(nsresult aRv) michael@0: { michael@0: nsCString name; michael@0: nsCString message; michael@0: uint16_t code; michael@0: NSResultToNameAndMessage(aRv, name, message, &code); michael@0: nsRefPtr inst = michael@0: new DOMException(aRv, message, name, code); michael@0: return inst.forget(); michael@0: } michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla