mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 18:07:31 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
5fda7c378f
282 changed files with 8990 additions and 3961 deletions
|
|
@ -1183,14 +1183,6 @@ GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
UnforgeableValueOf(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
args.rval().set(args.thisv());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2044,9 +2044,6 @@ GetInterface(JSContext* aCx, T* aThis, nsIJSID* aIID,
|
|||
GetInterfaceImpl(aCx, aThis, aThis, aIID, aRetval, aError);
|
||||
}
|
||||
|
||||
bool
|
||||
UnforgeableValueOf(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
|
|
|
|||
|
|
@ -2390,11 +2390,10 @@ class MethodDefiner(PropertyDefiner):
|
|||
# Synthesize our valueOf method
|
||||
self.regular.append({
|
||||
"name": 'valueOf',
|
||||
"nativeName": "UnforgeableValueOf",
|
||||
"selfHostedName": "Object_valueOf",
|
||||
"methodInfo": False,
|
||||
"length": 0,
|
||||
"flags": "JSPROP_ENUMERATE", # readonly/permanent added
|
||||
# automatically.
|
||||
"flags": "0", # readonly/permanent added automatically.
|
||||
"condition": MemberCondition()
|
||||
})
|
||||
|
||||
|
|
@ -3456,19 +3455,15 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode,
|
|||
"nsContentUtils::ThreadsafeIsCallerChrome()"))
|
||||
|
||||
if descriptor.interface.getExtendedAttribute("Unforgeable"):
|
||||
# We do our undefined toJSON and toPrimitive here, not as a regular
|
||||
# property because we don't have a concept of value props anywhere in
|
||||
# IDL.
|
||||
# We do our undefined toPrimitive here, not as a regular property
|
||||
# because we don't have a concept of value props anywhere in IDL.
|
||||
unforgeables.append(CGGeneric(fill(
|
||||
"""
|
||||
JS::RootedId toPrimitive(aCx,
|
||||
SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::toPrimitive)));
|
||||
if (!JS_DefinePropertyById(aCx, ${holderName}, toPrimitive,
|
||||
JS::UndefinedHandleValue,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT) ||
|
||||
!JS_DefineProperty(aCx, ${holderName}, "toJSON",
|
||||
JS::UndefinedHandleValue,
|
||||
JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
|
||||
JSPROP_READONLY | JSPROP_PERMANENT)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@
|
|||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIScriptError.idl'
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_bindings'
|
||||
|
||||
EXPORTS.ipc += [
|
||||
'ErrorIPCUtils.h',
|
||||
]
|
||||
|
|
@ -91,6 +97,8 @@ UNIFIED_SOURCES += [
|
|||
'DOMJSProxyHandler.cpp',
|
||||
'Exceptions.cpp',
|
||||
'IterableIterator.cpp',
|
||||
'nsScriptError.cpp',
|
||||
'nsScriptErrorWithStack.cpp',
|
||||
'SimpleGlobalObject.cpp',
|
||||
'ToJSValue.cpp',
|
||||
'WebIDLGlobalNameHash.cpp',
|
||||
|
|
|
|||
135
dom/bindings/nsIScriptError.idl
Normal file
135
dom/bindings/nsIScriptError.idl
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
/*
|
||||
* nsIConsoleMessage subclass for representing JavaScript errors and warnings.
|
||||
*/
|
||||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIArray.idl"
|
||||
#include "nsIConsoleMessage.idl"
|
||||
|
||||
%{C++
|
||||
#include "nsStringGlue.h" // for nsDependentCString
|
||||
%}
|
||||
|
||||
[scriptable, uuid(e8933fc9-c302-4e12-a55b-4f88611d9c6c)]
|
||||
interface nsIScriptErrorNote : nsISupports
|
||||
{
|
||||
readonly attribute AString errorMessage;
|
||||
readonly attribute AString sourceName;
|
||||
readonly attribute uint32_t lineNumber;
|
||||
readonly attribute uint32_t columnNumber;
|
||||
|
||||
AUTF8String toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(63eb4d3e-7d99-4150-b4f3-11314f9d82a9)]
|
||||
interface nsIScriptError : nsIConsoleMessage
|
||||
{
|
||||
/** pseudo-flag for default case */
|
||||
const unsigned long errorFlag = 0x0;
|
||||
|
||||
/** message is warning */
|
||||
const unsigned long warningFlag = 0x1;
|
||||
|
||||
/** exception was thrown for this case - exception-aware hosts can ignore */
|
||||
const unsigned long exceptionFlag = 0x2;
|
||||
|
||||
// XXX check how strict is implemented these days.
|
||||
/** error or warning is due to strict option */
|
||||
const unsigned long strictFlag = 0x4;
|
||||
|
||||
/** just a log message */
|
||||
const unsigned long infoFlag = 0x8;
|
||||
|
||||
/**
|
||||
* The error message without any context/line number information.
|
||||
*
|
||||
* @note nsIConsoleMessage.message will return the error formatted
|
||||
* with file/line information.
|
||||
*/
|
||||
readonly attribute AString errorMessage;
|
||||
|
||||
readonly attribute AString sourceName;
|
||||
readonly attribute AString sourceLine;
|
||||
readonly attribute uint32_t lineNumber;
|
||||
readonly attribute uint32_t columnNumber;
|
||||
readonly attribute uint32_t flags;
|
||||
|
||||
/**
|
||||
* Categories I know about -
|
||||
* XUL javascript
|
||||
* content javascript (both of these from nsDocShell, currently)
|
||||
* system javascript (errors in JS components and other system JS)
|
||||
*/
|
||||
readonly attribute string category;
|
||||
|
||||
/* Get the window id this was initialized with. Zero will be
|
||||
returned if init() was used instead of initWithWindowID(). */
|
||||
readonly attribute unsigned long long outerWindowID;
|
||||
|
||||
/* Get the inner window id this was initialized with. Zero will be
|
||||
returned if init() was used instead of initWithWindowID(). */
|
||||
readonly attribute unsigned long long innerWindowID;
|
||||
|
||||
readonly attribute boolean isFromPrivateWindow;
|
||||
|
||||
attribute jsval stack;
|
||||
|
||||
/**
|
||||
* The name of a template string, as found in js.msg, associated with the
|
||||
* error message.
|
||||
*/
|
||||
attribute AString errorMessageName;
|
||||
|
||||
readonly attribute nsIArray notes;
|
||||
|
||||
void init(in AString message,
|
||||
in AString sourceName,
|
||||
in AString sourceLine,
|
||||
in uint32_t lineNumber,
|
||||
in uint32_t columnNumber,
|
||||
in uint32_t flags,
|
||||
in string category);
|
||||
|
||||
/* This should be called instead of nsIScriptError.init to
|
||||
initialize with a window id. The window id should be for the
|
||||
inner window associated with this error. */
|
||||
void initWithWindowID(in AString message,
|
||||
in AString sourceName,
|
||||
in AString sourceLine,
|
||||
in uint32_t lineNumber,
|
||||
in uint32_t columnNumber,
|
||||
in uint32_t flags,
|
||||
in ACString category,
|
||||
in unsigned long long innerWindowID);
|
||||
%{C++
|
||||
// This overload allows passing a literal string for category.
|
||||
template<uint32_t N>
|
||||
nsresult InitWithWindowID(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
const nsAString& sourceLine,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber,
|
||||
uint32_t flags,
|
||||
const char (&c)[N],
|
||||
uint64_t aInnerWindowID)
|
||||
{
|
||||
nsDependentCString category(c, N - 1);
|
||||
return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
|
||||
columnNumber, flags, category, aInnerWindowID);
|
||||
}
|
||||
%}
|
||||
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define NS_SCRIPTERROR_CID \
|
||||
{ 0x1950539a, 0x90f0, 0x4d22, { 0xb5, 0xaf, 0x71, 0x32, 0x9c, 0x68, 0xfa, 0x35 }}
|
||||
|
||||
#define NS_SCRIPTERROR_CONTRACTID "@mozilla.org/scripterror;1"
|
||||
%}
|
||||
438
dom/bindings/nsScriptError.cpp
Normal file
438
dom/bindings/nsScriptError.cpp
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* nsIScriptError implementation.
|
||||
*/
|
||||
|
||||
#include "nsScriptError.h"
|
||||
#include "jsprf.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsISensitiveInfoHiddenURI.h"
|
||||
|
||||
static_assert(nsIScriptError::errorFlag == JSREPORT_ERROR &&
|
||||
nsIScriptError::warningFlag == JSREPORT_WARNING &&
|
||||
nsIScriptError::exceptionFlag == JSREPORT_EXCEPTION &&
|
||||
nsIScriptError::strictFlag == JSREPORT_STRICT &&
|
||||
nsIScriptError::infoFlag == JSREPORT_USER_1,
|
||||
"flags should be consistent");
|
||||
|
||||
nsScriptErrorBase::nsScriptErrorBase()
|
||||
: mMessage(),
|
||||
mMessageName(),
|
||||
mSourceName(),
|
||||
mLineNumber(0),
|
||||
mSourceLine(),
|
||||
mColumnNumber(0),
|
||||
mFlags(0),
|
||||
mCategory(),
|
||||
mOuterWindowID(0),
|
||||
mInnerWindowID(0),
|
||||
mTimeStamp(0),
|
||||
mInitializedOnMainThread(false),
|
||||
mIsFromPrivateWindow(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsScriptErrorBase::~nsScriptErrorBase() {}
|
||||
|
||||
void
|
||||
nsScriptErrorBase::AddNote(nsIScriptErrorNote* note)
|
||||
{
|
||||
mNotes.AppendObject(note);
|
||||
}
|
||||
|
||||
void
|
||||
nsScriptErrorBase::InitializeOnMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mInitializedOnMainThread);
|
||||
|
||||
if (mInnerWindowID) {
|
||||
nsGlobalWindow* window =
|
||||
nsGlobalWindow::GetInnerWindowWithId(mInnerWindowID);
|
||||
if (window) {
|
||||
nsPIDOMWindowOuter* outer = window->GetOuterWindow();
|
||||
if (outer)
|
||||
mOuterWindowID = outer->WindowID();
|
||||
|
||||
nsIDocShell* docShell = window->GetDocShell();
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
|
||||
|
||||
if (loadContext) {
|
||||
// Never mark exceptions from chrome windows as having come from
|
||||
// private windows, since we always want them to be reported.
|
||||
nsIPrincipal* winPrincipal = window->GetPrincipal();
|
||||
mIsFromPrivateWindow = loadContext->UsePrivateBrowsing() &&
|
||||
!nsContentUtils::IsSystemPrincipal(winPrincipal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mInitializedOnMainThread = true;
|
||||
}
|
||||
|
||||
// nsIConsoleMessage methods
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetMessageMoz(char16_t** result) {
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString message;
|
||||
rv = ToString(message);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*result = UTF8ToNewUnicode(message);
|
||||
if (!*result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetLogLevel(uint32_t* aLogLevel)
|
||||
{
|
||||
if (mFlags & (uint32_t)nsIScriptError::infoFlag) {
|
||||
*aLogLevel = nsIConsoleMessage::info;
|
||||
} else if (mFlags & (uint32_t)nsIScriptError::warningFlag) {
|
||||
*aLogLevel = nsIConsoleMessage::warn;
|
||||
} else {
|
||||
*aLogLevel = nsIConsoleMessage::error;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIScriptError methods
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetErrorMessage(nsAString& aResult) {
|
||||
aResult.Assign(mMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetSourceName(nsAString& aResult) {
|
||||
aResult.Assign(mSourceName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetSourceLine(nsAString& aResult) {
|
||||
aResult.Assign(mSourceLine);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetLineNumber(uint32_t* result) {
|
||||
*result = mLineNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetColumnNumber(uint32_t* result) {
|
||||
*result = mColumnNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetFlags(uint32_t* result) {
|
||||
*result = mFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetCategory(char** result) {
|
||||
*result = ToNewCString(mCategory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetStack(JS::MutableHandleValue aStack) {
|
||||
aStack.setUndefined();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::SetStack(JS::HandleValue aStack) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetErrorMessageName(nsAString& aErrorMessageName) {
|
||||
aErrorMessageName = mMessageName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::SetErrorMessageName(const nsAString& aErrorMessageName) {
|
||||
mMessageName = aErrorMessageName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::Init(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
const nsAString& sourceLine,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber,
|
||||
uint32_t flags,
|
||||
const char* category)
|
||||
{
|
||||
return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
|
||||
columnNumber, flags,
|
||||
category ? nsDependentCString(category)
|
||||
: EmptyCString(),
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
AssignSourceNameHelper(nsString& aSourceNameDest, const nsAString& aSourceNameSrc)
|
||||
{
|
||||
if (aSourceNameSrc.IsEmpty())
|
||||
return;
|
||||
|
||||
aSourceNameDest.Assign(aSourceNameSrc);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoCString pass;
|
||||
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aSourceNameSrc)) &&
|
||||
NS_SUCCEEDED(uri->GetPassword(pass)) &&
|
||||
!pass.IsEmpty())
|
||||
{
|
||||
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(uri);
|
||||
|
||||
nsAutoCString loc;
|
||||
if (safeUri && NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc)))
|
||||
aSourceNameDest.Assign(NS_ConvertUTF8toUTF16(loc));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
const nsAString& sourceLine,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber,
|
||||
uint32_t flags,
|
||||
const nsACString& category,
|
||||
uint64_t aInnerWindowID)
|
||||
{
|
||||
mMessage.Assign(message);
|
||||
AssignSourceNameHelper(mSourceName, sourceName);
|
||||
mLineNumber = lineNumber;
|
||||
mSourceLine.Assign(sourceLine);
|
||||
mColumnNumber = columnNumber;
|
||||
mFlags = flags;
|
||||
mCategory = category;
|
||||
mTimeStamp = JS_Now() / 1000;
|
||||
mInnerWindowID = aInnerWindowID;
|
||||
|
||||
if (aInnerWindowID && NS_IsMainThread()) {
|
||||
InitializeOnMainThread();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ToStringHelper(const char* aSeverity, const nsString& aMessage,
|
||||
const nsString& aSourceName, const nsString* aSourceLine,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsACString& /*UTF8*/ aResult)
|
||||
{
|
||||
static const char format0[] =
|
||||
"[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
|
||||
static const char format1[] =
|
||||
"[%s: \"%s\" {file: \"%s\" line: %d}]";
|
||||
static const char format2[] =
|
||||
"[%s: \"%s\"]";
|
||||
|
||||
char* temp;
|
||||
char* tempMessage = nullptr;
|
||||
char* tempSourceName = nullptr;
|
||||
char* tempSourceLine = nullptr;
|
||||
|
||||
if (!aMessage.IsEmpty())
|
||||
tempMessage = ToNewUTF8String(aMessage);
|
||||
if (!aSourceName.IsEmpty())
|
||||
// Use at most 512 characters from mSourceName.
|
||||
tempSourceName = ToNewUTF8String(StringHead(aSourceName, 512));
|
||||
if (aSourceLine && !aSourceLine->IsEmpty())
|
||||
// Use at most 512 characters from mSourceLine.
|
||||
tempSourceLine = ToNewUTF8String(StringHead(*aSourceLine, 512));
|
||||
|
||||
if (nullptr != tempSourceName && nullptr != tempSourceLine) {
|
||||
temp = JS_smprintf(format0,
|
||||
aSeverity,
|
||||
tempMessage,
|
||||
tempSourceName,
|
||||
aLineNumber,
|
||||
aColumnNumber,
|
||||
tempSourceLine);
|
||||
} else if (!aSourceName.IsEmpty()) {
|
||||
temp = JS_smprintf(format1,
|
||||
aSeverity,
|
||||
tempMessage,
|
||||
tempSourceName,
|
||||
aLineNumber);
|
||||
} else {
|
||||
temp = JS_smprintf(format2,
|
||||
aSeverity,
|
||||
tempMessage);
|
||||
}
|
||||
|
||||
if (nullptr != tempMessage)
|
||||
free(tempMessage);
|
||||
if (nullptr != tempSourceName)
|
||||
free(tempSourceName);
|
||||
if (nullptr != tempSourceLine)
|
||||
free(tempSourceLine);
|
||||
|
||||
if (!temp)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
aResult.Assign(temp);
|
||||
JS_smprintf_free(temp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
|
||||
{
|
||||
static const char error[] = "JavaScript Error";
|
||||
static const char warning[] = "JavaScript Warning";
|
||||
|
||||
const char* severity = !(mFlags & JSREPORT_WARNING) ? error : warning;
|
||||
|
||||
return ToStringHelper(severity, mMessage, mSourceName, &mSourceLine,
|
||||
mLineNumber, mColumnNumber, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID)
|
||||
{
|
||||
NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
|
||||
"This can't be safely determined off the main thread, "
|
||||
"returning an inaccurate value!");
|
||||
|
||||
if (!mInitializedOnMainThread && NS_IsMainThread()) {
|
||||
InitializeOnMainThread();
|
||||
}
|
||||
|
||||
*aOuterWindowID = mOuterWindowID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetInnerWindowID(uint64_t* aInnerWindowID)
|
||||
{
|
||||
*aInnerWindowID = mInnerWindowID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetTimeStamp(int64_t* aTimeStamp)
|
||||
{
|
||||
*aTimeStamp = mTimeStamp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow)
|
||||
{
|
||||
NS_WARNING_ASSERTION(NS_IsMainThread() || mInitializedOnMainThread,
|
||||
"This can't be safely determined off the main thread, "
|
||||
"returning an inaccurate value!");
|
||||
|
||||
if (!mInitializedOnMainThread && NS_IsMainThread()) {
|
||||
InitializeOnMainThread();
|
||||
}
|
||||
|
||||
*aIsFromPrivateWindow = mIsFromPrivateWindow;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetNotes(nsIArray** aNotes)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> array =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t len = mNotes.Length();
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
array->AppendElement(mNotes[i], false);
|
||||
array.forget(aNotes);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
|
||||
|
||||
nsScriptErrorNote::nsScriptErrorNote()
|
||||
: mMessage(),
|
||||
mSourceName(),
|
||||
mLineNumber(0),
|
||||
mColumnNumber(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsScriptErrorNote::~nsScriptErrorNote() {}
|
||||
|
||||
void
|
||||
nsScriptErrorNote::Init(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber)
|
||||
{
|
||||
mMessage.Assign(message);
|
||||
AssignSourceNameHelper(mSourceName, sourceName);
|
||||
mLineNumber = lineNumber;
|
||||
mColumnNumber = columnNumber;
|
||||
}
|
||||
|
||||
// nsIScriptErrorNote methods
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetErrorMessage(nsAString& aResult) {
|
||||
aResult.Assign(mMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetSourceName(nsAString& aResult) {
|
||||
aResult.Assign(mSourceName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetLineNumber(uint32_t* result) {
|
||||
*result = mLineNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetColumnNumber(uint32_t* result) {
|
||||
*result = mColumnNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::ToString(nsACString& /*UTF8*/ aResult)
|
||||
{
|
||||
return ToStringHelper("JavaScript Note", mMessage, mSourceName, nullptr,
|
||||
mLineNumber, mColumnNumber, aResult);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsScriptErrorNote, nsIScriptErrorNote)
|
||||
109
dom/bindings/nsScriptError.h
Normal file
109
dom/bindings/nsScriptError.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_nsScriptError_h
|
||||
#define mozilla_dom_nsScriptError_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsScriptErrorNote final : public nsIScriptErrorNote {
|
||||
public:
|
||||
nsScriptErrorNote();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSISCRIPTERRORNOTE
|
||||
|
||||
void Init(const nsAString& message, const nsAString& sourceName,
|
||||
uint32_t lineNumber, uint32_t columnNumber);
|
||||
|
||||
private:
|
||||
virtual ~nsScriptErrorNote();
|
||||
|
||||
nsString mMessage;
|
||||
nsString mSourceName;
|
||||
nsString mSourceLine;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumnNumber;
|
||||
};
|
||||
|
||||
// Definition of nsScriptError..
|
||||
class nsScriptErrorBase : public nsIScriptError {
|
||||
public:
|
||||
nsScriptErrorBase();
|
||||
|
||||
NS_DECL_NSICONSOLEMESSAGE
|
||||
NS_DECL_NSISCRIPTERROR
|
||||
|
||||
void AddNote(nsIScriptErrorNote* note);
|
||||
|
||||
protected:
|
||||
virtual ~nsScriptErrorBase();
|
||||
|
||||
void
|
||||
InitializeOnMainThread();
|
||||
|
||||
nsCOMArray<nsIScriptErrorNote> mNotes;
|
||||
nsString mMessage;
|
||||
nsString mMessageName;
|
||||
nsString mSourceName;
|
||||
uint32_t mLineNumber;
|
||||
nsString mSourceLine;
|
||||
uint32_t mColumnNumber;
|
||||
uint32_t mFlags;
|
||||
nsCString mCategory;
|
||||
// mOuterWindowID is set on the main thread from InitializeOnMainThread().
|
||||
uint64_t mOuterWindowID;
|
||||
uint64_t mInnerWindowID;
|
||||
int64_t mTimeStamp;
|
||||
// mInitializedOnMainThread and mIsFromPrivateWindow are set on the main
|
||||
// thread from InitializeOnMainThread().
|
||||
mozilla::Atomic<bool> mInitializedOnMainThread;
|
||||
bool mIsFromPrivateWindow;
|
||||
};
|
||||
|
||||
class nsScriptError final : public nsScriptErrorBase {
|
||||
public:
|
||||
nsScriptError() {}
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
private:
|
||||
virtual ~nsScriptError() {}
|
||||
};
|
||||
|
||||
class nsScriptErrorWithStack : public nsScriptErrorBase {
|
||||
public:
|
||||
explicit nsScriptErrorWithStack(JS::HandleObject);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsScriptErrorWithStack)
|
||||
|
||||
NS_IMETHOD Init(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
const nsAString& sourceLine,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber,
|
||||
uint32_t flags,
|
||||
const char* category) override;
|
||||
|
||||
NS_IMETHOD GetStack(JS::MutableHandleValue) override;
|
||||
NS_IMETHOD ToString(nsACString& aResult) override;
|
||||
|
||||
private:
|
||||
virtual ~nsScriptErrorWithStack();
|
||||
// Complete stackframe where the error happened.
|
||||
// Must be SavedFrame object.
|
||||
JS::Heap<JSObject*> mStack;
|
||||
};
|
||||
|
||||
#endif /* mozilla_dom_nsScriptError_h */
|
||||
120
dom/bindings/nsScriptErrorWithStack.cpp
Normal file
120
dom/bindings/nsScriptErrorWithStack.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* nsScriptErrorWithStack implementation.
|
||||
* a main-thread-only, cycle-collected subclass of nsScriptErrorBase
|
||||
* that can store a SavedFrame stack trace object.
|
||||
*/
|
||||
|
||||
#include "nsScriptError.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace {
|
||||
|
||||
static nsCString
|
||||
FormatStackString(JSContext* cx, HandleObject aStack) {
|
||||
JS::RootedString formattedStack(cx);
|
||||
|
||||
if (!JS::BuildStackString(cx, aStack, &formattedStack)) {
|
||||
return nsCString();
|
||||
}
|
||||
|
||||
nsAutoJSString stackJSString;
|
||||
if (!stackJSString.init(cx, formattedStack)) {
|
||||
return nsCString();
|
||||
}
|
||||
|
||||
return NS_ConvertUTF16toUTF8(stackJSString.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsScriptErrorWithStack)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsScriptErrorWithStack)
|
||||
tmp->mStack = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsScriptErrorWithStack)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsScriptErrorWithStack)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mStack)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsScriptErrorWithStack)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScriptErrorWithStack)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptErrorWithStack)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIConsoleMessage)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptError)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
nsScriptErrorWithStack::nsScriptErrorWithStack(JS::HandleObject aStack)
|
||||
: mStack(aStack)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "You can't use this class on workers.");
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
nsScriptErrorWithStack::~nsScriptErrorWithStack() {
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorWithStack::Init(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
const nsAString& sourceLine,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber,
|
||||
uint32_t flags,
|
||||
const char* category)
|
||||
{
|
||||
MOZ_CRASH("nsScriptErrorWithStack requires to be initialized with a document, by using InitWithWindowID");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorWithStack::GetStack(JS::MutableHandleValue aStack) {
|
||||
aStack.setObjectOrNull(mStack);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorWithStack::ToString(nsACString& /*UTF8*/ aResult)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCString message;
|
||||
nsresult rv = nsScriptErrorBase::ToString(message);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mStack) {
|
||||
aResult.Assign(message);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(mStack)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
RootedObject stack(cx, mStack);
|
||||
nsCString stackString = FormatStackString(cx, stack);
|
||||
nsCString combined = message + NS_LITERAL_CSTRING("\n") + stackString;
|
||||
aResult.Assign(combined);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -29,7 +29,9 @@ WebGLExtensionDebugShaders::GetTranslatedShaderSource(const WebGLShader& shader,
|
|||
{
|
||||
retval.SetIsVoid(true);
|
||||
|
||||
if (mIsLost || !mContext) return;
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mContext->ValidateObject("getShaderTranslatedSource: shader", shader))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLQuery* query) const
|
||||
{
|
||||
const char funcName[] = "deleteQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->DeleteQuery(query, funcName);
|
||||
}
|
||||
|
|
@ -50,8 +52,10 @@ bool
|
|||
WebGLExtensionDisjointTimerQuery::IsQueryEXT(const WebGLQuery* query) const
|
||||
{
|
||||
const char funcName[] = "isQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return false;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mContext->IsQuery(query, funcName);
|
||||
}
|
||||
|
|
@ -60,8 +64,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, WebGLQuery& query) const
|
||||
{
|
||||
const char funcName[] = "beginQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->BeginQuery(target, query, funcName);
|
||||
}
|
||||
|
|
@ -70,8 +76,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target) const
|
||||
{
|
||||
const char funcName[] = "endQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->EndQuery(target, funcName);
|
||||
}
|
||||
|
|
@ -80,8 +88,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLQuery& query, GLenum target) const
|
||||
{
|
||||
const char funcName[] = "queryCounterEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mContext->ValidateObject(funcName, query))
|
||||
return;
|
||||
|
|
@ -95,8 +105,10 @@ WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target, GLen
|
|||
{
|
||||
const char funcName[] = "getQueryEXT";
|
||||
retval.setNull();
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->GetQuery(cx, target, pname, retval, funcName);
|
||||
}
|
||||
|
|
@ -108,8 +120,10 @@ WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
|
|||
{
|
||||
const char funcName[] = "getQueryObjectEXT";
|
||||
retval.setNull();
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->GetQueryParameter(cx, query, pname, retval, funcName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ WebGLExtensionInstancedArrays::DrawArraysInstancedANGLE(GLenum mode,
|
|||
if (mContext) {
|
||||
mContext->ErrorInvalidOperation("%s: Extension is lost.",
|
||||
"drawArraysInstancedANGLE");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->DrawArraysInstanced(mode, first, count, primcount);
|
||||
|
|
@ -49,8 +49,8 @@ WebGLExtensionInstancedArrays::DrawElementsInstancedANGLE(GLenum mode,
|
|||
if (mContext) {
|
||||
mContext->ErrorInvalidOperation("%s: Extension is lost.",
|
||||
"drawElementsInstancedANGLE");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->DrawElementsInstanced(mode, count, type, offset, primcount);
|
||||
|
|
@ -64,8 +64,8 @@ WebGLExtensionInstancedArrays::VertexAttribDivisorANGLE(GLuint index,
|
|||
if (mContext) {
|
||||
mContext->ErrorInvalidOperation("%s: Extension is lost.",
|
||||
"vertexAttribDivisorANGLE");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->VertexAttribDivisor(index, divisor);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
|
||||
#include "WebGLTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
|||
|
|
@ -1381,7 +1381,7 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't allow cross-origin 307 POST redirects.
|
||||
// Don't allow cross-origin 307/308 POST redirects.
|
||||
nsCOMPtr<nsIHttpChannel> oldHttpChannel(do_QueryInterface(oldChannel));
|
||||
if (oldHttpChannel) {
|
||||
uint32_t responseStatus;
|
||||
|
|
@ -1389,7 +1389,7 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (responseStatus == 307) {
|
||||
if (responseStatus == 307 || responseStatus == 308) {
|
||||
nsAutoCString method;
|
||||
rv = oldHttpChannel->GetRequestMethod(method);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ Wrap(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj)
|
|||
}
|
||||
|
||||
if (existing) {
|
||||
js::Wrapper::Renew(cx, existing, obj, wrapper);
|
||||
js::Wrapper::Renew(existing, obj, wrapper);
|
||||
}
|
||||
return js::Wrapper::New(cx, obj, wrapper);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@
|
|||
#include "nsProxyRelease.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsScriptError.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
#include "prthread.h"
|
||||
#include "xpcpublic.h"
|
||||
|
|
@ -281,27 +282,34 @@ struct WindowAction
|
|||
};
|
||||
|
||||
void
|
||||
LogErrorToConsole(const nsAString& aMessage,
|
||||
const nsAString& aFilename,
|
||||
const nsAString& aLine,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
uint32_t aFlags,
|
||||
uint64_t aInnerWindowId)
|
||||
LogErrorToConsole(const WorkerErrorReport& aReport, uint64_t aInnerWindowId)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIScriptError> scriptError =
|
||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
||||
RefPtr<nsScriptErrorBase> scriptError = new nsScriptError();
|
||||
NS_WARNING_ASSERTION(scriptError, "Failed to create script error!");
|
||||
|
||||
if (scriptError) {
|
||||
if (NS_FAILED(scriptError->InitWithWindowID(aMessage, aFilename, aLine,
|
||||
aLineNumber, aColumnNumber,
|
||||
aFlags, "Web Worker",
|
||||
nsAutoCString category("Web Worker");
|
||||
if (NS_FAILED(scriptError->InitWithWindowID(aReport.mMessage,
|
||||
aReport.mFilename,
|
||||
aReport.mLine,
|
||||
aReport.mLineNumber,
|
||||
aReport.mColumnNumber,
|
||||
aReport.mFlags,
|
||||
category,
|
||||
aInnerWindowId))) {
|
||||
NS_WARNING("Failed to init script error!");
|
||||
scriptError = nullptr;
|
||||
|
||||
for (size_t i = 0, len = aReport.mNotes.Length(); i < len; i++) {
|
||||
const WorkerErrorNote& note = aReport.mNotes.ElementAt(i);
|
||||
|
||||
nsScriptErrorNote* noteObject = new nsScriptErrorNote();
|
||||
noteObject->Init(note.mMessage, note.mFilename,
|
||||
note.mLineNumber, note.mColumnNumber);
|
||||
scriptError->AddNote(noteObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,23 +324,23 @@ LogErrorToConsole(const nsAString& aMessage,
|
|||
}
|
||||
NS_WARNING("LogMessage failed!");
|
||||
} else if (NS_SUCCEEDED(consoleService->LogStringMessage(
|
||||
aMessage.BeginReading()))) {
|
||||
aReport.mMessage.BeginReading()))) {
|
||||
return;
|
||||
}
|
||||
NS_WARNING("LogStringMessage failed!");
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 msg(aMessage);
|
||||
NS_ConvertUTF16toUTF8 filename(aFilename);
|
||||
NS_ConvertUTF16toUTF8 msg(aReport.mMessage);
|
||||
NS_ConvertUTF16toUTF8 filename(aReport.mFilename);
|
||||
|
||||
static const char kErrorString[] = "JS error in Web Worker: %s [%s:%u]";
|
||||
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "Gecko", kErrorString, msg.get(),
|
||||
filename.get(), aLineNumber);
|
||||
filename.get(), aReport.mLineNumber);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, kErrorString, msg.get(), filename.get(), aLineNumber);
|
||||
fprintf(stderr, kErrorString, msg.get(), filename.get(), aReport.mLineNumber);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
|
@ -536,10 +544,7 @@ private:
|
|||
}
|
||||
|
||||
if (aWorkerPrivate->IsSharedWorker()) {
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, EmptyString(),
|
||||
EmptyString(),
|
||||
EmptyString(), 0, 0,
|
||||
JSREPORT_ERROR,
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, nullptr,
|
||||
/* isErrorEvent */ false);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1060,15 +1065,7 @@ private:
|
|||
|
||||
class ReportErrorRunnable final : public WorkerRunnable
|
||||
{
|
||||
nsString mMessage;
|
||||
nsString mFilename;
|
||||
nsString mLine;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumnNumber;
|
||||
uint32_t mFlags;
|
||||
uint32_t mErrorNumber;
|
||||
JSExnType mExnType;
|
||||
bool mMutedError;
|
||||
WorkerErrorReport mReport;
|
||||
|
||||
public:
|
||||
// aWorkerPrivate is the worker thread we're on (or the main thread, if null)
|
||||
|
|
@ -1077,11 +1074,7 @@ public:
|
|||
static void
|
||||
ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aFireAtScope, WorkerPrivate* aTarget,
|
||||
const nsString& aMessage, const nsString& aFilename,
|
||||
const nsString& aLine, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber, uint32_t aFlags,
|
||||
uint32_t aErrorNumber, JSExnType aExnType,
|
||||
bool aMutedError, uint64_t aInnerWindowId,
|
||||
const WorkerErrorReport& aReport, uint64_t aInnerWindowId,
|
||||
JS::Handle<JS::Value> aException = JS::NullHandleValue)
|
||||
{
|
||||
if (aWorkerPrivate) {
|
||||
|
|
@ -1092,16 +1085,16 @@ public:
|
|||
|
||||
// We should not fire error events for warnings but instead make sure that
|
||||
// they show up in the error console.
|
||||
if (!JSREPORT_IS_WARNING(aFlags)) {
|
||||
if (!JSREPORT_IS_WARNING(aReport.mFlags)) {
|
||||
// First fire an ErrorEvent at the worker.
|
||||
RootedDictionary<ErrorEventInit> init(aCx);
|
||||
|
||||
if (aMutedError) {
|
||||
if (aReport.mMutedError) {
|
||||
init.mMessage.AssignLiteral("Script error.");
|
||||
} else {
|
||||
init.mMessage = aMessage;
|
||||
init.mFilename = aFilename;
|
||||
init.mLineno = aLineNumber;
|
||||
init.mMessage = aReport.mMessage;
|
||||
init.mFilename = aReport.mFilename;
|
||||
init.mLineno = aReport.mLineNumber;
|
||||
init.mError = aException;
|
||||
}
|
||||
|
||||
|
|
@ -1128,7 +1121,8 @@ public:
|
|||
// into an error event on our parent worker!
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this
|
||||
// better.
|
||||
if (aFireAtScope && (aTarget || aErrorNumber != JSMSG_OVER_RECURSED)) {
|
||||
if (aFireAtScope &&
|
||||
(aTarget || aReport.mErrorNumber != JSMSG_OVER_RECURSED)) {
|
||||
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
NS_ASSERTION(global, "This should never be null!");
|
||||
|
||||
|
|
@ -1145,8 +1139,8 @@ public:
|
|||
|
||||
MOZ_ASSERT_IF(globalScope, globalScope->GetWrapperPreserveColor() == global);
|
||||
if (globalScope || IsDebuggerSandbox(global)) {
|
||||
aWorkerPrivate->ReportErrorToDebugger(aFilename, aLineNumber,
|
||||
aMessage);
|
||||
aWorkerPrivate->ReportErrorToDebugger(aReport.mFilename, aReport.mLineNumber,
|
||||
aReport.mMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1193,28 +1187,20 @@ public:
|
|||
// Now fire a runnable to do the same on the parent's thread if we can.
|
||||
if (aWorkerPrivate) {
|
||||
RefPtr<ReportErrorRunnable> runnable =
|
||||
new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
|
||||
aLineNumber, aColumnNumber, aFlags,
|
||||
aErrorNumber, aExnType, aMutedError);
|
||||
new ReportErrorRunnable(aWorkerPrivate, aReport);
|
||||
runnable->Dispatch();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise log an error to the error console.
|
||||
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
|
||||
aFlags, aInnerWindowId);
|
||||
LogErrorToConsole(aReport, aInnerWindowId);
|
||||
}
|
||||
|
||||
private:
|
||||
ReportErrorRunnable(WorkerPrivate* aWorkerPrivate, const nsString& aMessage,
|
||||
const nsString& aFilename, const nsString& aLine,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
uint32_t aFlags, uint32_t aErrorNumber,
|
||||
JSExnType aExnType, bool aMutedError)
|
||||
ReportErrorRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const WorkerErrorReport& aReport)
|
||||
: WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
|
||||
mMessage(aMessage), mFilename(aFilename), mLine(aLine),
|
||||
mLineNumber(aLineNumber), mColumnNumber(aColumnNumber), mFlags(aFlags),
|
||||
mErrorNumber(aErrorNumber), mExnType(aExnType), mMutedError(aMutedError)
|
||||
mReport(aReport)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
|
|
@ -1251,9 +1237,7 @@ private:
|
|||
}
|
||||
|
||||
if (aWorkerPrivate->IsSharedWorker()) {
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
|
||||
mLine, mLineNumber,
|
||||
mColumnNumber, mFlags,
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, &mReport,
|
||||
/* isErrorEvent */ true);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1267,9 +1251,10 @@ private:
|
|||
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
|
||||
aWorkerPrivate->WorkerName(),
|
||||
aWorkerPrivate->ScriptURL(),
|
||||
mMessage,
|
||||
mFilename, mLine, mLineNumber,
|
||||
mColumnNumber, mFlags, mExnType);
|
||||
mReport.mMessage,
|
||||
mReport.mFilename, mReport.mLine, mReport.mLineNumber,
|
||||
mReport.mColumnNumber, mReport.mFlags,
|
||||
mReport.mExnType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1289,9 +1274,8 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mMessage,
|
||||
mFilename, mLine, mLineNumber, mColumnNumber, mFlags,
|
||||
mErrorNumber, mExnType, mMutedError, innerWindowId);
|
||||
ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mReport,
|
||||
innerWindowId);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -3314,21 +3298,16 @@ template <class Derived>
|
|||
void
|
||||
WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
||||
JSContext* aCx,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aFilename,
|
||||
const nsAString& aLine,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
uint32_t aFlags,
|
||||
const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (JSREPORT_IS_WARNING(aFlags)) {
|
||||
if (aIsErrorEvent && JSREPORT_IS_WARNING(aReport->mFlags)) {
|
||||
// Don't fire any events anywhere. Just log to console.
|
||||
// XXXbz should we log to all the consoles of all the relevant windows?
|
||||
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
|
||||
aFlags, 0);
|
||||
MOZ_ASSERT(aReport);
|
||||
LogErrorToConsole(*aReport, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3357,10 +3336,10 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
|||
RootedDictionary<ErrorEventInit> errorInit(aCx);
|
||||
errorInit.mBubbles = false;
|
||||
errorInit.mCancelable = true;
|
||||
errorInit.mMessage = aMessage;
|
||||
errorInit.mFilename = aFilename;
|
||||
errorInit.mLineno = aLineNumber;
|
||||
errorInit.mColno = aColumnNumber;
|
||||
errorInit.mMessage = aReport->mMessage;
|
||||
errorInit.mFilename = aReport->mFilename;
|
||||
errorInit.mLineno = aReport->mLineNumber;
|
||||
errorInit.mColno = aReport->mColumnNumber;
|
||||
|
||||
event = ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
|
||||
errorInit);
|
||||
|
|
@ -3426,9 +3405,9 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
|||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RootedDictionary<ErrorEventInit> init(aCx);
|
||||
init.mLineno = aLineNumber;
|
||||
init.mFilename = aFilename;
|
||||
init.mMessage = aMessage;
|
||||
init.mLineno = aReport->mLineNumber;
|
||||
init.mFilename = aReport->mFilename;
|
||||
init.mMessage = aReport->mMessage;
|
||||
init.mCancelable = true;
|
||||
init.mBubbles = true;
|
||||
|
||||
|
|
@ -3446,8 +3425,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
|||
|
||||
// Finally log a warning in the console if no window tried to prevent it.
|
||||
if (shouldLogErrorToConsole) {
|
||||
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
|
||||
aFlags, 0);
|
||||
MOZ_ASSERT(aReport);
|
||||
LogErrorToConsole(*aReport, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4120,7 +4099,10 @@ WorkerDebugger::ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
|
|||
listeners[index]->OnError(aFilename, aLineno, aMessage);
|
||||
}
|
||||
|
||||
LogErrorToConsole(aMessage, aFilename, nsString(), aLineno, 0, 0, 0);
|
||||
WorkerErrorReport report;
|
||||
report.mMessage = aMessage;
|
||||
report.mFilename = aFilename;
|
||||
LogErrorToConsole(report, 0);
|
||||
}
|
||||
|
||||
WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
|
||||
|
|
@ -5925,6 +5907,47 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WorkerErrorBase::AssignErrorBase(JSErrorBase* aReport)
|
||||
{
|
||||
mFilename = NS_ConvertUTF8toUTF16(aReport->filename);
|
||||
mLineNumber = aReport->lineno;
|
||||
mColumnNumber = aReport->column;
|
||||
mErrorNumber = aReport->errorNumber;
|
||||
}
|
||||
|
||||
void
|
||||
WorkerErrorNote::AssignErrorNote(JSErrorNotes::Note* aNote)
|
||||
{
|
||||
WorkerErrorBase::AssignErrorBase(aNote);
|
||||
xpc::ErrorNote::ErrorNoteToMessageString(aNote, mMessage);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerErrorReport::AssignErrorReport(JSErrorReport* aReport)
|
||||
{
|
||||
WorkerErrorBase::AssignErrorBase(aReport);
|
||||
xpc::ErrorReport::ErrorReportToMessageString(aReport, mMessage);
|
||||
|
||||
mLine.Assign(aReport->linebuf(), aReport->linebufLength());
|
||||
mFlags = aReport->flags;
|
||||
MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
|
||||
mExnType = JSExnType(aReport->exnType);
|
||||
mMutedError = aReport->isMuted;
|
||||
|
||||
if (aReport->notes) {
|
||||
if (!mNotes.SetLength(aReport->notes->length(), fallible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto&& note : *aReport->notes) {
|
||||
mNotes.ElementAt(i).AssignErrorNote(note.get());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
||||
JSErrorReport* aReport)
|
||||
|
|
@ -5947,32 +5970,17 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
|||
}
|
||||
JS_ClearPendingException(aCx);
|
||||
|
||||
nsString message, filename, line;
|
||||
uint32_t lineNumber, columnNumber, flags, errorNumber;
|
||||
JSExnType exnType = JSEXN_ERR;
|
||||
bool mutedError = aReport && aReport->isMuted;
|
||||
|
||||
WorkerErrorReport report;
|
||||
if (aReport) {
|
||||
// We want the same behavior here as xpc::ErrorReport::init here.
|
||||
xpc::ErrorReport::ErrorReportToMessageString(aReport, message);
|
||||
|
||||
filename = NS_ConvertUTF8toUTF16(aReport->filename);
|
||||
line.Assign(aReport->linebuf(), aReport->linebufLength());
|
||||
lineNumber = aReport->lineno;
|
||||
columnNumber = aReport->tokenOffset();
|
||||
flags = aReport->flags;
|
||||
errorNumber = aReport->errorNumber;
|
||||
MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
|
||||
exnType = JSExnType(aReport->exnType);
|
||||
report.AssignErrorReport(aReport);
|
||||
}
|
||||
else {
|
||||
lineNumber = columnNumber = errorNumber = 0;
|
||||
flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
|
||||
report.mFlags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
|
||||
}
|
||||
|
||||
if (message.IsEmpty() && aToStringResult) {
|
||||
if (report.mMessage.IsEmpty() && aToStringResult) {
|
||||
nsDependentCString toStringResult(aToStringResult.c_str());
|
||||
if (!AppendUTF8toUTF16(toStringResult, message, mozilla::fallible)) {
|
||||
if (!AppendUTF8toUTF16(toStringResult, report.mMessage, mozilla::fallible)) {
|
||||
// Try again, with only a 1 KB string. Do this infallibly this time.
|
||||
// If the user doesn't have 1 KB to spare we're done anyways.
|
||||
uint32_t index = std::min(uint32_t(1024), toStringResult.Length());
|
||||
|
|
@ -5982,7 +5990,7 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
|||
|
||||
nsDependentCString truncatedToStringResult(aToStringResult.c_str(),
|
||||
index);
|
||||
AppendUTF8toUTF16(truncatedToStringResult, message);
|
||||
AppendUTF8toUTF16(truncatedToStringResult, report.mMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5991,13 +5999,11 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
|||
// Don't want to run the scope's error handler if this is a recursive error or
|
||||
// if we ran out of memory.
|
||||
bool fireAtScope = mErrorHandlerRecursionCount == 1 &&
|
||||
errorNumber != JSMSG_OUT_OF_MEMORY &&
|
||||
report.mErrorNumber != JSMSG_OUT_OF_MEMORY &&
|
||||
JS::CurrentGlobalOrNull(aCx);
|
||||
|
||||
ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message,
|
||||
filename, line, lineNumber,
|
||||
columnNumber, flags, errorNumber, exnType,
|
||||
mutedError, 0, exn);
|
||||
ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, report, 0,
|
||||
exn);
|
||||
|
||||
mErrorHandlerRecursionCount--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,45 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class WorkerErrorBase {
|
||||
public:
|
||||
nsString mMessage;
|
||||
nsString mFilename;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumnNumber;
|
||||
uint32_t mErrorNumber;
|
||||
|
||||
WorkerErrorBase()
|
||||
: mLineNumber(0),
|
||||
mColumnNumber(0),
|
||||
mErrorNumber(0)
|
||||
{ }
|
||||
|
||||
void AssignErrorBase(JSErrorBase* aReport);
|
||||
};
|
||||
|
||||
class WorkerErrorNote : public WorkerErrorBase {
|
||||
public:
|
||||
void AssignErrorNote(JSErrorNotes::Note* aNote);
|
||||
};
|
||||
|
||||
class WorkerErrorReport : public WorkerErrorBase {
|
||||
public:
|
||||
nsString mLine;
|
||||
uint32_t mFlags;
|
||||
JSExnType mExnType;
|
||||
bool mMutedError;
|
||||
nsTArray<WorkerErrorNote> mNotes;
|
||||
|
||||
WorkerErrorReport()
|
||||
: mFlags(0),
|
||||
mExnType(JSEXN_ERR),
|
||||
mMutedError(false)
|
||||
{ }
|
||||
|
||||
void AssignErrorReport(JSErrorReport* aReport);
|
||||
};
|
||||
|
||||
template <class Derived>
|
||||
class WorkerPrivateParent : public DOMEventTargetHelper
|
||||
{
|
||||
|
|
@ -401,12 +440,7 @@ public:
|
|||
|
||||
void
|
||||
BroadcastErrorToSharedWorkers(JSContext* aCx,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aFilename,
|
||||
const nsAString& aLine,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
uint32_t aFlags,
|
||||
const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent);
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ LOCAL_INCLUDES += [
|
|||
'../base',
|
||||
'../system',
|
||||
'/dom/base',
|
||||
'/dom/bindings',
|
||||
'/xpcom/build',
|
||||
'/xpcom/threads',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
const errorFilename = href.substring(0, href.lastIndexOf("/") + 1) +
|
||||
filename;
|
||||
const errorLine = 91;
|
||||
const errorColumn = 0;
|
||||
const errorColumn = 11;
|
||||
|
||||
var worker = new SharedWorker(filename);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue