/* -*- 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/. */
// Service workers do not have a main thread parent global, so normal // worker error reporting will crash. Instead, pass the error to // the ServiceWorkerManager to report on any controlled documents. if (aWorkerPrivate->IsServiceWorker()) {
RefPtr<RemoteWorkerChild> actor(
aWorkerPrivate->GetRemoteWorkerController());
Unused << NS_WARN_IF(!actor);
if (actor) {
actor->ErrorPropagationOnMainThread(nullptr, false);
}
returntrue;
}
// The innerWindowId is only required if we are going to ReportError // below, which is gated on this condition. The inner window correctness // check is only going to succeed when the worker is accepting events. if (workerIsAcceptingEvents) {
aWorkerPrivate->AssertInnerWindowIsCorrect();
innerWindowId = aWorkerPrivate->WindowID();
}
}
// Don't fire this event if the JS object has been disconnected from the // private object. if (!workerIsAcceptingEvents) { returntrue;
}
class ReportGenericErrorRunnable final : public WorkerParentDebuggeeRunnable { public: staticvoid CreateAndDispatch(WorkerPrivate* aWorkerPrivate) {
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
RefPtr<ReportGenericErrorRunnable> runnable = new ReportGenericErrorRunnable(aWorkerPrivate);
runnable->Dispatch(aWorkerPrivate);
}
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++;
}
}
}
// aWorkerPrivate is the worker thread we're on (or the main thread, if null) // aTarget is the worker object that we are going to fire an error at // (if any). /* static */ void WorkerErrorReport::ReportError(
JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aFireAtScope,
DOMEventTargetHelper* aTarget, UniquePtr<WorkerErrorReport> aReport,
uint64_t aInnerWindowId, JS::Handle<JS::Value> aException) { if (aWorkerPrivate) {
aWorkerPrivate->AssertIsOnWorkerThread();
} else {
AssertIsOnMainThread();
}
// We should not fire error events for warnings but instead make sure that // they show up in the error console. if (!aReport->mIsWarning) { // First fire an ErrorEvent at the worker.
RootedDictionary<ErrorEventInit> init(aCx);
// Now fire an event at the global object, but don't do that if the error // code is too much recursion and this is the same script threw the error. // XXXbz the interaction of this with worker errors seems kinda broken. // An overrecursion in the debugger or debugger sandbox will get turned // into an error event on our parent worker! // https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this // better. if (aFireAtScope &&
(aTarget || aReport->mErrorNumber != JSMSG_OVER_RECURSED)) {
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
NS_ASSERTION(global, "This should never be null!");
nsEventStatus status = nsEventStatus_eIgnore;
if (aWorkerPrivate) {
RefPtr<WorkerGlobalScope> globalScope;
UNWRAP_OBJECT(WorkerGlobalScope, &global, globalScope);
if (!globalScope) {
WorkerDebuggerGlobalScope* globalScope = nullptr;
UNWRAP_OBJECT(WorkerDebuggerGlobalScope, &global, globalScope);
MOZ_ASSERT(SimpleGlobalObject::SimpleGlobalType(global) ==
SimpleGlobalObject::GlobalType::BindingDetail); // XXXbz We should really log this to console, but unwinding out of // this stuff without ending up firing any events is ... hard. Just // return for now. // https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks // making this better. return;
}
if (NS_FAILED(EventDispatcher::DispatchDOMEvent(
globalScope, nullptr, event, nullptr, &status))) {
NS_WARNING("Failed to dispatch worker thread error event!");
status = nsEventStatus_eIgnore;
}
} elseif (nsGlobalWindowInner* win = xpc::WindowOrNull(global)) {
MOZ_ASSERT(NS_IsMainThread());
if (!win->HandleScriptError(init, &status)) {
NS_WARNING("Failed to dispatch main thread error event!");
status = nsEventStatus_eIgnore;
}
}
// Was preventDefault() called? if (status == nsEventStatus_eConsumeNoDefault) { return;
}
}
}
// Now fire a runnable to do the same on the parent's thread if we can. if (aWorkerPrivate) {
RefPtr<ReportErrorRunnable> runnable = new ReportErrorRunnable(aWorkerPrivate, std::move(aReport));
runnable->Dispatch(aWorkerPrivate); return;
}
// Otherwise log an error to the error console.
WorkerErrorReport::LogErrorToConsole(aCx, *aReport, aInnerWindowId);
}
for (const ErrorDataNote& note : aReport.notes()) {
nsScriptErrorNote* noteObject = new nsScriptErrorNote();
noteObject->Init(note.message(), note.filename(), 0, note.lineNumber(),
note.columnNumber());
scriptError->AddNote(noteObject);
}
}
nsCOMPtr<nsIConsoleService> consoleService =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
NS_WARNING_ASSERTION(consoleService, "Failed to get console service!");
if (consoleService) { if (scriptError) { if (NS_SUCCEEDED(consoleService->LogMessage(scriptError))) { return;
}
NS_WARNING("LogMessage failed!");
} elseif (NS_SUCCEEDED(consoleService->LogStringMessage(
aReport.message().BeginReading()))) { return;
}
NS_WARNING("LogStringMessage failed!");
}
NS_ConvertUTF16toUTF8 msg(aReport.message());
staticconstchar kErrorString[] = "JS error in Web Worker: %s [%s:%u]";
nsCOMPtr<nsIConsoleService> consoleService =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
NS_WARNING_ASSERTION(consoleService, "Failed to get console service!");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.