--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -66,16 +66,17 @@
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/Likely.h"
#include "mozilla/ManualNAC.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Preferences.h"
+#include "mozilla/ResultExtensions.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/TextEvents.h"
#include "nsArrayUtils.h"
#include "nsAString.h"
#include "nsAttrName.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsBindingManager.h"
@@ -10907,30 +10908,65 @@ nsContentUtils::IsOverridingWindowName(c
{
return !aName.IsEmpty() &&
!aName.LowerCaseEqualsLiteral("_blank") &&
!aName.LowerCaseEqualsLiteral("_top") &&
!aName.LowerCaseEqualsLiteral("_parent") &&
!aName.LowerCaseEqualsLiteral("_self");
}
+// Unfortunately, we can't unwrap an IDL object using only a concrete type.
+// We need to calculate type data based on the IDL typename. Which means
+// wrapping our templated function in a macro.
+#define EXTRACT_EXN_VALUES(T, ...) \
+ ExtractExceptionValues<mozilla::dom::prototypes::id::T, \
+ T##Binding::NativeType, T>(__VA_ARGS__).isOk()
+
+template <prototypes::ID PrototypeID, class NativeType, typename T>
+static Result<Ok, nsresult>
+ExtractExceptionValues(JSContext* aCx,
+ JS::HandleObject aObj,
+ nsACString& aSourceSpecOut,
+ uint32_t* aLineOut,
+ uint32_t* aColumnOut,
+ nsString& aMessageOut)
+{
+ RefPtr<T> exn;
+ MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn)));
+
+ nsAutoString filename;
+ exn->GetFilename(aCx, filename);
+ if (!filename.IsEmpty()) {
+ CopyUTF16toUTF8(filename, aSourceSpecOut);
+ *aLineOut = exn->LineNumber(aCx);
+ *aColumnOut = exn->ColumnNumber();
+ }
+
+ exn->GetName(aMessageOut);
+ aMessageOut.AppendLiteral(": ");
+
+ nsAutoString message;
+ exn->GetMessageMoz(message);
+ aMessageOut.Append(message);
+ return Ok();
+}
+
/* static */ void
nsContentUtils::ExtractErrorValues(JSContext* aCx,
JS::Handle<JS::Value> aValue,
nsACString& aSourceSpecOut,
uint32_t* aLineOut,
uint32_t* aColumnOut,
nsString& aMessageOut)
{
MOZ_ASSERT(aLineOut);
MOZ_ASSERT(aColumnOut);
if (aValue.isObject()) {
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
- RefPtr<dom::DOMException> domException;
// Try to process as an Error object. Use the file/line/column values
// from the Error as they will be more specific to the root cause of
// the problem.
JSErrorReport* err = obj ? JS_ErrorFromException(aCx, obj) : nullptr;
if (err) {
// Use xpc to extract the error message only. We don't actually send
// this report anywhere.
@@ -10944,48 +10980,43 @@ nsContentUtils::ExtractErrorValues(JSCon
CopyUTF16toUTF8(report->mFileName, aSourceSpecOut);
*aLineOut = report->mLineNumber;
*aColumnOut = report->mColumn;
}
aMessageOut.Assign(report->mErrorMsg);
}
// Next, try to unwrap the rejection value as a DOMException.
- else if(NS_SUCCEEDED(UNWRAP_OBJECT(DOMException, obj, domException))) {
-
- nsAutoString filename;
- domException->GetFilename(aCx, filename);
- if (!filename.IsEmpty()) {
- CopyUTF16toUTF8(filename, aSourceSpecOut);
- *aLineOut = domException->LineNumber(aCx);
- *aColumnOut = domException->ColumnNumber();
- }
-
- domException->GetName(aMessageOut);
- aMessageOut.AppendLiteral(": ");
-
- nsAutoString message;
- domException->GetMessageMoz(message);
- aMessageOut.Append(message);
+ else if (EXTRACT_EXN_VALUES(DOMException, aCx, obj, aSourceSpecOut,
+ aLineOut, aColumnOut, aMessageOut)) {
+ return;
+ }
+
+ // Next, try to unwrap the rejection value as an XPC Exception.
+ else if (EXTRACT_EXN_VALUES(Exception, aCx, obj, aSourceSpecOut,
+ aLineOut, aColumnOut, aMessageOut)) {
+ return;
}
}
// If we could not unwrap a specific error type, then perform default safe
// string conversions on primitives. Objects will result in "[Object]"
// unfortunately.
if (aMessageOut.IsEmpty()) {
nsAutoJSString jsString;
if (jsString.init(aCx, aValue)) {
aMessageOut = jsString;
} else {
JS_ClearPendingException(aCx);
}
}
}
+#undef EXTRACT_EXN_VALUES
+
/* static */ bool
nsContentUtils::DevToolsEnabled(JSContext* aCx)
{
if (NS_IsMainThread()) {
return sDevToolsEnabled;
}
workers::WorkerPrivate* workerPrivate = workers::GetWorkerPrivateFromContext(aCx);