mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-28 01:57:30 +09:00
Bug 1288768 - Better error reporting for network errors in workers
This commit is contained in:
parent
8f4e22e819
commit
12f3d0302c
5 changed files with 132 additions and 26 deletions
|
|
@ -412,8 +412,17 @@ Event::Constructor(const GlobalObject& aGlobal,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
|
nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
RefPtr<Event> e = new Event(t, nullptr, nullptr);
|
return Constructor(t, aType, aParam);
|
||||||
bool trusted = e->Init(t);
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
already_AddRefed<Event>
|
||||||
|
Event::Constructor(EventTarget* aEventTarget,
|
||||||
|
const nsAString& aType,
|
||||||
|
const EventInit& aParam)
|
||||||
|
{
|
||||||
|
RefPtr<Event> e = new Event(aEventTarget, nullptr, nullptr);
|
||||||
|
bool trusted = e->Init(aEventTarget);
|
||||||
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
|
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
|
||||||
e->SetTrusted(trusted);
|
e->SetTrusted(trusted);
|
||||||
e->SetComposed(aParam.mComposed);
|
e->SetComposed(aParam.mComposed);
|
||||||
|
|
@ -1209,7 +1218,7 @@ Event::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(void)
|
NS_IMETHODIMP_(void)
|
||||||
Event::SetOwner(mozilla::dom::EventTarget* aOwner)
|
Event::SetOwner(EventTarget* aOwner)
|
||||||
{
|
{
|
||||||
mOwner = nullptr;
|
mOwner = nullptr;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,10 @@ public:
|
||||||
LayoutDeviceIntPoint aPoint,
|
LayoutDeviceIntPoint aPoint,
|
||||||
CSSIntPoint aDefaultPoint);
|
CSSIntPoint aDefaultPoint);
|
||||||
|
|
||||||
|
static already_AddRefed<Event> Constructor(EventTarget* aEventTarget,
|
||||||
|
const nsAString& aType,
|
||||||
|
const EventInit& aParam);
|
||||||
|
|
||||||
static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal,
|
static already_AddRefed<Event> Constructor(const GlobalObject& aGlobal,
|
||||||
const nsAString& aType,
|
const nsAString& aType,
|
||||||
const EventInit& aParam,
|
const EventInit& aParam,
|
||||||
|
|
|
||||||
|
|
@ -495,6 +495,82 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ReportCompileErrorRunnable final : public WorkerRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void
|
||||||
|
CreateAndDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
RefPtr<ReportCompileErrorRunnable> runnable =
|
||||||
|
new ReportCompileErrorRunnable(aCx, aWorkerPrivate);
|
||||||
|
runnable->Dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReportCompileErrorRunnable(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||||
|
: WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount)
|
||||||
|
{
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
|
||||||
|
{
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
// Dispatch may fail if the worker was canceled, no need to report that as
|
||||||
|
// an error, so don't call base class PostDispatch.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
|
{
|
||||||
|
if (aWorkerPrivate->IsFrozen() ||
|
||||||
|
aWorkerPrivate->IsParentWindowPaused()) {
|
||||||
|
MOZ_ASSERT(!IsDebuggerRunnable());
|
||||||
|
aWorkerPrivate->QueueRunnable(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aWorkerPrivate->IsSharedWorker()) {
|
||||||
|
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, EmptyString(),
|
||||||
|
EmptyString(),
|
||||||
|
EmptyString(), 0, 0,
|
||||||
|
JSREPORT_ERROR,
|
||||||
|
/* isErrorEvent */ false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aWorkerPrivate->IsServiceWorker()) {
|
||||||
|
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||||
|
if (swm) {
|
||||||
|
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
|
||||||
|
aWorkerPrivate->WorkerName(),
|
||||||
|
aWorkerPrivate->ScriptURL(),
|
||||||
|
EmptyString(), EmptyString(), EmptyString(),
|
||||||
|
0, 0, JSREPORT_ERROR, JSEXN_ERR);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aWorkerPrivate->IsAcceptingEvents()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Event> event =
|
||||||
|
Event::Constructor(aWorkerPrivate, NS_LITERAL_STRING("error"),
|
||||||
|
EventInit());
|
||||||
|
event->SetTrusted(true);
|
||||||
|
|
||||||
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
|
aWorkerPrivate->DispatchDOMEvent(nullptr, event, nullptr, &status);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class CompileScriptRunnable final : public WorkerRunnable
|
class CompileScriptRunnable final : public WorkerRunnable
|
||||||
{
|
{
|
||||||
nsString mScriptURL;
|
nsString mScriptURL;
|
||||||
|
|
@ -538,9 +614,15 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to propagate exceptions from rv onto aCx, so that they will get
|
// Make sure to propagate exceptions from rv onto aCx, so that they will get
|
||||||
// reported after we return. We do this for all failures on rv, because now
|
// reported after we return. We want to propagate just JS exceptions,
|
||||||
// we're using rv to track all the state we care about.
|
// because all the other errors are handled when the script is loaded.
|
||||||
//
|
// See: https://dom.spec.whatwg.org/#concept-event-fire
|
||||||
|
if (rv.Failed() && !rv.IsJSException()) {
|
||||||
|
ReportCompileErrorRunnable::CreateAndDispatch(aCx, aWorkerPrivate);
|
||||||
|
rv.SuppressException();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// This is a little dumb, but aCx is in the null compartment here because we
|
// This is a little dumb, but aCx is in the null compartment here because we
|
||||||
// set it up that way in our Run(), since we had not created the global at
|
// set it up that way in our Run(), since we had not created the global at
|
||||||
// that point yet. So we need to enter the compartment of our global,
|
// that point yet. So we need to enter the compartment of our global,
|
||||||
|
|
@ -1171,7 +1253,8 @@ private:
|
||||||
if (aWorkerPrivate->IsSharedWorker()) {
|
if (aWorkerPrivate->IsSharedWorker()) {
|
||||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
|
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
|
||||||
mLine, mLineNumber,
|
mLine, mLineNumber,
|
||||||
mColumnNumber, mFlags);
|
mColumnNumber, mFlags,
|
||||||
|
/* isErrorEvent */ true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3250,7 +3333,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
||||||
const nsAString& aLine,
|
const nsAString& aLine,
|
||||||
uint32_t aLineNumber,
|
uint32_t aLineNumber,
|
||||||
uint32_t aColumnNumber,
|
uint32_t aColumnNumber,
|
||||||
uint32_t aFlags)
|
uint32_t aFlags,
|
||||||
|
bool aIsErrorEvent)
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
|
@ -3281,31 +3365,42 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
||||||
// May be null.
|
// May be null.
|
||||||
nsPIDOMWindowInner* window = sharedWorker->GetOwner();
|
nsPIDOMWindowInner* window = sharedWorker->GetOwner();
|
||||||
|
|
||||||
RootedDictionary<ErrorEventInit> errorInit(aCx);
|
RefPtr<Event> event;
|
||||||
errorInit.mBubbles = false;
|
|
||||||
errorInit.mCancelable = true;
|
|
||||||
errorInit.mMessage = aMessage;
|
|
||||||
errorInit.mFilename = aFilename;
|
|
||||||
errorInit.mLineno = aLineNumber;
|
|
||||||
errorInit.mColno = aColumnNumber;
|
|
||||||
|
|
||||||
RefPtr<ErrorEvent> errorEvent =
|
if (aIsErrorEvent) {
|
||||||
ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
|
RootedDictionary<ErrorEventInit> errorInit(aCx);
|
||||||
errorInit);
|
errorInit.mBubbles = false;
|
||||||
if (!errorEvent) {
|
errorInit.mCancelable = true;
|
||||||
|
errorInit.mMessage = aMessage;
|
||||||
|
errorInit.mFilename = aFilename;
|
||||||
|
errorInit.mLineno = aLineNumber;
|
||||||
|
errorInit.mColno = aColumnNumber;
|
||||||
|
|
||||||
|
event = ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
|
||||||
|
errorInit);
|
||||||
|
} else {
|
||||||
|
event = Event::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
|
||||||
|
EventInit());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event) {
|
||||||
ThrowAndReport(window, NS_ERROR_UNEXPECTED);
|
ThrowAndReport(window, NS_ERROR_UNEXPECTED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorEvent->SetTrusted(true);
|
event->SetTrusted(true);
|
||||||
|
|
||||||
bool defaultActionEnabled;
|
bool defaultActionEnabled;
|
||||||
nsresult rv = sharedWorker->DispatchEvent(errorEvent, &defaultActionEnabled);
|
nsresult rv = sharedWorker->DispatchEvent(event, &defaultActionEnabled);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
ThrowAndReport(window, rv);
|
ThrowAndReport(window, rv);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!aIsErrorEvent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (defaultActionEnabled) {
|
if (defaultActionEnabled) {
|
||||||
// Add the owning window to our list so that we will fire an error event
|
// Add the owning window to our list so that we will fire an error event
|
||||||
// at it later.
|
// at it later.
|
||||||
|
|
|
||||||
|
|
@ -408,7 +408,8 @@ public:
|
||||||
const nsAString& aLine,
|
const nsAString& aLine,
|
||||||
uint32_t aLineNumber,
|
uint32_t aLineNumber,
|
||||||
uint32_t aColumnNumber,
|
uint32_t aColumnNumber,
|
||||||
uint32_t aFlags);
|
uint32_t aFlags,
|
||||||
|
bool aIsErrorEvent);
|
||||||
|
|
||||||
void
|
void
|
||||||
WorkerScriptLoaded();
|
WorkerScriptLoaded();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
[worker.html]
|
|
||||||
type: testharness
|
|
||||||
expected: ERROR
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue