зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1769913 - P2 WorkerParentThreadRunnable for the runnables dispatched to worker's parent thread. r=dom-worker-reviewers,asuth
In this patch, WorkerParentThreadRunnable is extracted from WorkerThreadRunnable for runnable on the parent thread. WorkerParentControlRunnable and WorkerParentDebuggeeRunnable are also created for control runnable and debuggee runnable on the parent thread. Instead of using WorkerRunnable::Target to indicate the thread target, inheriting WorkerThreadRunnable or WorkerParentThreadRunnable to point out that this runnable should run on the worker thread or on the parent thread. So WorkerRunnable::Target is removed in this patch. This patch also move the dispatching logic into WorkerPrivate to simplify WorkerRunnable::DispatchInternal()'s implementation. Depends on D205178 Differential Revision: https://phabricator.services.mozilla.com/D205679
This commit is contained in:
Родитель
e22d6ca385
Коммит
8f38838e6e
|
@ -96,8 +96,7 @@ class TeardownRunnableOnWorker final : public WorkerControlRunnable,
|
|||
public:
|
||||
TeardownRunnableOnWorker(WorkerPrivate* aWorkerPrivate,
|
||||
BroadcastChannelChild* aActor)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "TeardownRunnableOnWorker",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "TeardownRunnableOnWorker"),
|
||||
TeardownRunnable(aActor) {}
|
||||
|
||||
bool WorkerRun(JSContext*, WorkerPrivate*) override {
|
||||
|
|
|
@ -39,8 +39,7 @@ class PerformanceEntryAdder final : public WorkerControlRunnable {
|
|||
PerformanceEntryAdder(WorkerPrivate* aWorkerPrivate,
|
||||
PerformanceStorageWorker* aStorage,
|
||||
UniquePtr<PerformanceProxyData>&& aData)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "PerformanceEntryAdder",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "PerformanceEntryAdder"),
|
||||
mStorage(aStorage),
|
||||
mData(std::move(aData)) {}
|
||||
|
||||
|
|
|
@ -278,8 +278,7 @@ class ServiceWorkerOp::ServiceWorkerOpRunnable final
|
|||
|
||||
ServiceWorkerOpRunnable(RefPtr<ServiceWorkerOp> aOwner,
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "ServiceWorkerOpRunnable",
|
||||
WorkerThread),
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "ServiceWorkerOpRunnable"),
|
||||
mOwner(std::move(aOwner)) {
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mOwner);
|
||||
|
|
|
@ -2792,8 +2792,7 @@ class WorkerRunnableDispatcher final : public WorkerThreadRunnable {
|
|||
WorkerRunnableDispatcher(WebSocketImpl* aImpl,
|
||||
ThreadSafeWorkerRef* aWorkerRef,
|
||||
already_AddRefed<nsIRunnable> aEvent)
|
||||
: WorkerThreadRunnable(aWorkerRef->Private(), "WorkerRunnableDispatcher",
|
||||
WorkerRunnable::WorkerThread),
|
||||
: WorkerThreadRunnable(aWorkerRef->Private(), "WorkerRunnableDispatcher"),
|
||||
mWebSocketImpl(aImpl),
|
||||
mEvent(std::move(aEvent)) {}
|
||||
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
namespace mozilla::dom {
|
||||
EventWithOptionsRunnable::EventWithOptionsRunnable(Worker& aWorker,
|
||||
const char* aName)
|
||||
: WorkerDebuggeeRunnable(aWorker.mWorkerPrivate, aName,
|
||||
WorkerRunnable::WorkerThread),
|
||||
: WorkerDebuggeeRunnable(aWorker.mWorkerPrivate, aName),
|
||||
StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
StructuredCloneScope::SameProcess) {}
|
||||
|
||||
|
@ -132,19 +131,6 @@ bool EventWithOptionsRunnable::BuildAndFireEvent(
|
|||
|
||||
bool EventWithOptionsRunnable::WorkerRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate) {
|
||||
if (mTarget == ParentThread) {
|
||||
// Don't fire this event if the JS object has been disconnected from the
|
||||
// private object.
|
||||
if (!aWorkerPrivate->IsAcceptingEvents()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
aWorkerPrivate->AssertInnerWindowIsCorrect();
|
||||
|
||||
return BuildAndFireEvent(aCx, aWorkerPrivate,
|
||||
aWorkerPrivate->ParentEventTargetRef());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
|
||||
MOZ_ASSERT(aWorkerPrivate->GlobalScope());
|
||||
|
||||
|
|
|
@ -14,9 +14,8 @@
|
|||
|
||||
namespace mozilla::dom {
|
||||
|
||||
MessageEventRunnable::MessageEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
Target aTarget)
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "MessageEventRunnable", aTarget),
|
||||
MessageEventRunnable::MessageEventRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "MessageEventRunnable"),
|
||||
StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
StructuredCloneScope::SameProcess) {}
|
||||
|
||||
|
@ -84,20 +83,6 @@ bool MessageEventRunnable::DispatchDOMEvent(JSContext* aCx,
|
|||
|
||||
bool MessageEventRunnable::WorkerRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate) {
|
||||
if (mTarget == ParentThread) {
|
||||
// Don't fire this event if the JS object has been disconnected from the
|
||||
// private object.
|
||||
if (!aWorkerPrivate->IsAcceptingEvents()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
aWorkerPrivate->AssertInnerWindowIsCorrect();
|
||||
|
||||
return DispatchDOMEvent(aCx, aWorkerPrivate,
|
||||
aWorkerPrivate->ParentEventTargetRef(),
|
||||
!aWorkerPrivate->GetParent());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
|
||||
MOZ_ASSERT(aWorkerPrivate->GlobalScope());
|
||||
|
||||
|
@ -124,4 +109,98 @@ void MessageEventRunnable::DispatchError(JSContext* aCx,
|
|||
aTarget->DispatchEvent(*event);
|
||||
}
|
||||
|
||||
MessageEventToParentRunnable::MessageEventToParentRunnable(
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerParentDebuggeeRunnable(aWorkerPrivate,
|
||||
"MessageEventToParentRunnable"),
|
||||
StructuredCloneHolder(CloningSupported, TransferringSupported,
|
||||
StructuredCloneScope::SameProcess) {}
|
||||
|
||||
bool MessageEventToParentRunnable::DispatchDOMEvent(
|
||||
JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
DOMEventTargetHelper* aTarget, bool aIsMainThread) {
|
||||
nsCOMPtr<nsIGlobalObject> parent = aTarget->GetParentObject();
|
||||
|
||||
// For some workers without window, parent is null and we try to find it
|
||||
// from the JS Context.
|
||||
if (!parent) {
|
||||
JS::Rooted<JSObject*> globalObject(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (NS_WARN_IF(!globalObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parent = xpc::NativeGlobal(globalObject);
|
||||
if (NS_WARN_IF(!parent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(parent);
|
||||
|
||||
JS::Rooted<JS::Value> messageData(aCx);
|
||||
IgnoredErrorResult rv;
|
||||
|
||||
JS::CloneDataPolicy cloneDataPolicy;
|
||||
if (parent->GetClientInfo().isSome() &&
|
||||
parent->GetClientInfo()->AgentClusterId().isSome() &&
|
||||
parent->GetClientInfo()->AgentClusterId()->Equals(
|
||||
aWorkerPrivate->AgentClusterId())) {
|
||||
cloneDataPolicy.allowIntraClusterClonableSharedObjects();
|
||||
}
|
||||
|
||||
if (aWorkerPrivate->IsSharedMemoryAllowed()) {
|
||||
cloneDataPolicy.allowSharedMemoryObjects();
|
||||
}
|
||||
|
||||
Read(parent, aCx, &messageData, cloneDataPolicy, rv);
|
||||
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
DispatchError(aCx, aTarget);
|
||||
return false;
|
||||
}
|
||||
|
||||
Sequence<OwningNonNull<MessagePort>> ports;
|
||||
if (!TakeTransferredPortsAsSequence(ports)) {
|
||||
DispatchError(aCx, aTarget);
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
|
||||
event->InitMessageEvent(nullptr, u"message"_ns, CanBubble::eNo,
|
||||
Cancelable::eNo, messageData, u""_ns, u""_ns, nullptr,
|
||||
ports);
|
||||
|
||||
event->SetTrusted(true);
|
||||
|
||||
aTarget->DispatchEvent(*event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MessageEventToParentRunnable::WorkerRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate) {
|
||||
if (!aWorkerPrivate->IsAcceptingEvents()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
aWorkerPrivate->AssertInnerWindowIsCorrect();
|
||||
|
||||
return DispatchDOMEvent(aCx, aWorkerPrivate,
|
||||
aWorkerPrivate->ParentEventTargetRef(),
|
||||
!aWorkerPrivate->GetParent());
|
||||
}
|
||||
|
||||
void MessageEventToParentRunnable::DispatchError(
|
||||
JSContext* aCx, DOMEventTargetHelper* aTarget) {
|
||||
RootedDictionary<MessageEventInit> init(aCx);
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
|
||||
RefPtr<Event> event =
|
||||
MessageEvent::Constructor(aTarget, u"messageerror"_ns, init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
aTarget->DispatchEvent(*event);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -20,7 +20,21 @@ namespace dom {
|
|||
class MessageEventRunnable final : public WorkerDebuggeeRunnable,
|
||||
public StructuredCloneHolder {
|
||||
public:
|
||||
MessageEventRunnable(WorkerPrivate* aWorkerPrivate, Target aTarget);
|
||||
explicit MessageEventRunnable(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
bool DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
DOMEventTargetHelper* aTarget, bool aIsMainThread);
|
||||
|
||||
private:
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
void DispatchError(JSContext* aCx, DOMEventTargetHelper* aTarget);
|
||||
};
|
||||
|
||||
class MessageEventToParentRunnable final : public WorkerParentDebuggeeRunnable,
|
||||
public StructuredCloneHolder {
|
||||
public:
|
||||
explicit MessageEventToParentRunnable(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
bool DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
DOMEventTargetHelper* aTarget, bool aIsMainThread);
|
||||
|
|
|
@ -619,8 +619,7 @@ class JSDispatchableRunnable final : public WorkerThreadRunnable {
|
|||
public:
|
||||
JSDispatchableRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
JS::Dispatchable* aDispatchable)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "JSDispatchableRunnable",
|
||||
WorkerRunnable::WorkerThread),
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "JSDispatchableRunnable"),
|
||||
mDispatchable(aDispatchable) {
|
||||
MOZ_ASSERT(mDispatchable);
|
||||
}
|
||||
|
@ -1484,8 +1483,7 @@ namespace {
|
|||
class DumpCrashInfoRunnable final : public WorkerControlRunnable {
|
||||
public:
|
||||
explicit DumpCrashInfoRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "DumpCrashInfoRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "DumpCrashInfoRunnable"),
|
||||
mMonitor("DumpCrashInfoRunnable::mMonitor") {}
|
||||
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
|
||||
|
|
|
@ -126,7 +126,7 @@ void Worker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
JS::ProfilingCategoryPair::DOM, flags);
|
||||
|
||||
RefPtr<MessageEventRunnable> runnable =
|
||||
new MessageEventRunnable(mWorkerPrivate, WorkerRunnable::WorkerThread);
|
||||
new MessageEventRunnable(mWorkerPrivate);
|
||||
|
||||
JS::CloneDataPolicy clonePolicy;
|
||||
// DedicatedWorkers are always part of the same agent cluster.
|
||||
|
|
|
@ -62,13 +62,13 @@ namespace mozilla::dom {
|
|||
|
||||
namespace {
|
||||
|
||||
class ReportErrorRunnable final : public WorkerDebuggeeRunnable {
|
||||
class ReportErrorRunnable final : public WorkerParentDebuggeeRunnable {
|
||||
UniquePtr<WorkerErrorReport> mReport;
|
||||
|
||||
public:
|
||||
ReportErrorRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
UniquePtr<WorkerErrorReport> aReport)
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "ReportErrorRunnable"),
|
||||
: WorkerParentDebuggeeRunnable(aWorkerPrivate, "ReportErrorRunnable"),
|
||||
mReport(std::move(aReport)) {}
|
||||
|
||||
private:
|
||||
|
@ -138,7 +138,7 @@ class ReportErrorRunnable final : public WorkerDebuggeeRunnable {
|
|||
}
|
||||
};
|
||||
|
||||
class ReportGenericErrorRunnable final : public WorkerDebuggeeRunnable {
|
||||
class ReportGenericErrorRunnable final : public WorkerParentDebuggeeRunnable {
|
||||
public:
|
||||
static void CreateAndDispatch(WorkerPrivate* aWorkerPrivate) {
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
|
@ -151,7 +151,8 @@ class ReportGenericErrorRunnable final : public WorkerDebuggeeRunnable {
|
|||
|
||||
private:
|
||||
explicit ReportGenericErrorRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "ReportGenericErrorRunnable") {
|
||||
: WorkerParentDebuggeeRunnable(aWorkerPrivate,
|
||||
"ReportGenericErrorRunnable") {
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ class WrappedControlRunnable final : public WorkerControlRunnable {
|
|||
public:
|
||||
WrappedControlRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
nsCOMPtr<nsIRunnable>&& aInner)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "WrappedControlRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "WrappedControlRunnable"),
|
||||
mInner(std::move(aInner)) {}
|
||||
|
||||
virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) override {
|
||||
|
|
|
@ -186,8 +186,7 @@ class ExternalRunnableWrapper final : public WorkerThreadRunnable {
|
|||
public:
|
||||
ExternalRunnableWrapper(WorkerPrivate* aWorkerPrivate,
|
||||
nsIRunnable* aWrappedRunnable)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "ExternalRunnableWrapper",
|
||||
WorkerRunnable::WorkerThread),
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "ExternalRunnableWrapper"),
|
||||
mWrappedRunnable(aWrappedRunnable) {
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
MOZ_ASSERT(aWrappedRunnable);
|
||||
|
@ -251,8 +250,7 @@ class WorkerFinishedRunnable final : public WorkerControlRunnable {
|
|||
public:
|
||||
WorkerFinishedRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
WorkerPrivate* aFinishedWorker)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "WorkerFinishedRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "WorkerFinishedRunnable"),
|
||||
mFinishedWorker(aFinishedWorker) {
|
||||
aFinishedWorker->IncreaseWorkerFinishedRunnableCount();
|
||||
}
|
||||
|
@ -339,8 +337,7 @@ class CompileScriptRunnable final : public WorkerDebuggeeRunnable {
|
|||
UniquePtr<SerializedStackHolder> aOriginStack,
|
||||
const nsAString& aScriptURL,
|
||||
const mozilla::Encoding* aDocumentEncoding)
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "CompileScriptRunnable",
|
||||
WorkerThread),
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "CompileScriptRunnable"),
|
||||
mScriptURL(aScriptURL),
|
||||
mDocumentEncoding(aDocumentEncoding),
|
||||
mOriginStack(aOriginStack.release()) {}
|
||||
|
@ -447,7 +444,7 @@ class NotifyRunnable final : public WorkerControlRunnable {
|
|||
|
||||
public:
|
||||
NotifyRunnable(WorkerPrivate* aWorkerPrivate, WorkerStatus aStatus)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "NotifyRunnable", WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "NotifyRunnable"),
|
||||
mStatus(aStatus) {
|
||||
MOZ_ASSERT(aStatus == Closing || aStatus == Canceling ||
|
||||
aStatus == Killing);
|
||||
|
@ -476,7 +473,7 @@ class NotifyRunnable final : public WorkerControlRunnable {
|
|||
class FreezeRunnable final : public WorkerControlRunnable {
|
||||
public:
|
||||
explicit FreezeRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "FreezeRunnable", WorkerThread) {}
|
||||
: WorkerControlRunnable(aWorkerPrivate, "FreezeRunnable") {}
|
||||
|
||||
private:
|
||||
virtual bool WorkerRun(JSContext* aCx,
|
||||
|
@ -488,7 +485,7 @@ class FreezeRunnable final : public WorkerControlRunnable {
|
|||
class ThawRunnable final : public WorkerControlRunnable {
|
||||
public:
|
||||
explicit ThawRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "ThawRunnable", WorkerThread) {}
|
||||
: WorkerControlRunnable(aWorkerPrivate, "ThawRunnable") {}
|
||||
|
||||
private:
|
||||
virtual bool WorkerRun(JSContext* aCx,
|
||||
|
@ -502,9 +499,9 @@ class PropagateStorageAccessPermissionGrantedRunnable final
|
|||
public:
|
||||
explicit PropagateStorageAccessPermissionGrantedRunnable(
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerControlRunnable(aWorkerPrivate,
|
||||
"PropagateStorageAccessPermissionGrantedRunnable",
|
||||
WorkerThread) {}
|
||||
: WorkerControlRunnable(
|
||||
aWorkerPrivate, "PropagateStorageAccessPermissionGrantedRunnable") {
|
||||
}
|
||||
|
||||
private:
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
|
||||
|
@ -513,7 +510,7 @@ class PropagateStorageAccessPermissionGrantedRunnable final
|
|||
}
|
||||
};
|
||||
|
||||
class ReportErrorToConsoleRunnable final : public WorkerThreadRunnable {
|
||||
class ReportErrorToConsoleRunnable final : public WorkerParentThreadRunnable {
|
||||
const char* mMessage;
|
||||
const nsTArray<nsString> mParams;
|
||||
|
||||
|
@ -545,8 +542,8 @@ class ReportErrorToConsoleRunnable final : public WorkerThreadRunnable {
|
|||
ReportErrorToConsoleRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aMessage,
|
||||
const nsTArray<nsString>& aParams)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "ReportErrorToConsoleRunnable",
|
||||
WorkerRunnable::ParentThread),
|
||||
: WorkerParentThreadRunnable(aWorkerPrivate,
|
||||
"ReportErrorToConsoleRunnable"),
|
||||
mMessage(aMessage),
|
||||
mParams(aParams.Clone()) {}
|
||||
|
||||
|
@ -573,8 +570,7 @@ class RunExpiredTimoutsRunnable final : public WorkerThreadRunnable,
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
explicit RunExpiredTimoutsRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "RunExpiredTimoutsRunnable",
|
||||
WorkerRunnable::WorkerThread) {}
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "RunExpiredTimoutsRunnable") {}
|
||||
|
||||
private:
|
||||
~RunExpiredTimoutsRunnable() = default;
|
||||
|
@ -610,8 +606,7 @@ class DebuggerImmediateRunnable final : public WorkerThreadRunnable {
|
|||
public:
|
||||
explicit DebuggerImmediateRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
dom::Function& aHandler)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "DebuggerImmediateRunnable",
|
||||
WorkerRunnable::WorkerThread),
|
||||
: WorkerThreadRunnable(aWorkerPrivate, "DebuggerImmediateRunnable"),
|
||||
mHandler(&aHandler) {}
|
||||
|
||||
private:
|
||||
|
@ -672,8 +667,7 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable {
|
|||
public:
|
||||
UpdateContextOptionsRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const JS::ContextOptions& aContextOptions)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "UpdateContextOptionsRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "UpdateContextOptionsRunnable"),
|
||||
mContextOptions(aContextOptions) {}
|
||||
|
||||
private:
|
||||
|
@ -710,8 +704,7 @@ class UpdateJSWorkerMemoryParameterRunnable final
|
|||
JSGCParamKey aKey,
|
||||
Maybe<uint32_t> aValue)
|
||||
: WorkerControlRunnable(aWorkerPrivate,
|
||||
"UpdateJSWorkerMemoryParameterRunnable",
|
||||
WorkerThread),
|
||||
"UpdateJSWorkerMemoryParameterRunnable"),
|
||||
mValue(aValue),
|
||||
mKey(aKey) {}
|
||||
|
||||
|
@ -731,8 +724,7 @@ class UpdateGCZealRunnable final : public WorkerControlRunnable {
|
|||
public:
|
||||
UpdateGCZealRunnable(WorkerPrivate* aWorkerPrivate, uint8_t aGCZeal,
|
||||
uint32_t aFrequency)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "UpdateGCZealRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "UpdateGCZealRunnable"),
|
||||
mGCZeal(aGCZeal),
|
||||
mFrequency(aFrequency) {}
|
||||
|
||||
|
@ -750,8 +742,7 @@ class SetLowMemoryStateRunnable final : public WorkerControlRunnable {
|
|||
|
||||
public:
|
||||
SetLowMemoryStateRunnable(WorkerPrivate* aWorkerPrivate, bool aState)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "SetLowMemoryStateRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "SetLowMemoryStateRunnable"),
|
||||
mState(aState) {}
|
||||
|
||||
private:
|
||||
|
@ -769,8 +760,7 @@ class GarbageCollectRunnable final : public WorkerControlRunnable {
|
|||
public:
|
||||
GarbageCollectRunnable(WorkerPrivate* aWorkerPrivate, bool aShrinking,
|
||||
bool aCollectChildren)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "GarbageCollectRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "GarbageCollectRunnable"),
|
||||
mShrinking(aShrinking),
|
||||
mCollectChildren(aCollectChildren) {}
|
||||
|
||||
|
@ -804,8 +794,7 @@ class CycleCollectRunnable final : public WorkerControlRunnable {
|
|||
|
||||
public:
|
||||
CycleCollectRunnable(WorkerPrivate* aWorkerPrivate, bool aCollectChildren)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "CycleCollectRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "CycleCollectRunnable"),
|
||||
mCollectChildren(aCollectChildren) {}
|
||||
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
|
||||
|
@ -832,8 +821,7 @@ class OfflineStatusChangeRunnable final : public WorkerThreadRunnable {
|
|||
class MemoryPressureRunnable final : public WorkerControlRunnable {
|
||||
public:
|
||||
explicit MemoryPressureRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "MemoryPressureRunnable",
|
||||
WorkerThread) {}
|
||||
: WorkerControlRunnable(aWorkerPrivate, "MemoryPressureRunnable") {}
|
||||
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
|
||||
aWorkerPrivate->MemoryPressureInternal();
|
||||
|
@ -861,11 +849,11 @@ PRThread* PRThreadFromThread(nsIThread* aThread) {
|
|||
// called. This runnable is executed on the parent process in order to cancel
|
||||
// the current runnable. It uses a normal WorkerDebuggeeRunnable in order to be
|
||||
// sure that all the pending WorkerDebuggeeRunnables are executed before this.
|
||||
class CancelingOnParentRunnable final : public WorkerDebuggeeRunnable {
|
||||
class CancelingOnParentRunnable final : public WorkerParentDebuggeeRunnable {
|
||||
public:
|
||||
explicit CancelingOnParentRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerDebuggeeRunnable(aWorkerPrivate, "CancelingOnParentRunnable",
|
||||
ParentThread) {}
|
||||
: WorkerParentDebuggeeRunnable(aWorkerPrivate,
|
||||
"CancelingOnParentRunnable") {}
|
||||
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
|
||||
aWorkerPrivate->Cancel();
|
||||
|
@ -875,12 +863,11 @@ class CancelingOnParentRunnable final : public WorkerDebuggeeRunnable {
|
|||
|
||||
// A runnable to cancel the worker from the parent process.
|
||||
class CancelingWithTimeoutOnParentRunnable final
|
||||
: public WorkerControlRunnable {
|
||||
: public WorkerParentControlRunnable {
|
||||
public:
|
||||
explicit CancelingWithTimeoutOnParentRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: WorkerControlRunnable(aWorkerPrivate,
|
||||
"CancelingWithTimeoutOnParentRunnable",
|
||||
ParentThread) {}
|
||||
: WorkerParentControlRunnable(aWorkerPrivate,
|
||||
"CancelingWithTimeoutOnParentRunnable") {}
|
||||
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
|
||||
aWorkerPrivate->AssertIsOnParentThread();
|
||||
|
@ -1561,8 +1548,48 @@ void WorkerPrivate::Traverse(nsCycleCollectionTraversalCallback& aCb) {
|
|||
nsresult WorkerPrivate::Dispatch(already_AddRefed<WorkerRunnable> aRunnable,
|
||||
nsIEventTarget* aSyncLoopTarget) {
|
||||
// May be called on any thread!
|
||||
RefPtr<WorkerRunnable> runnable(aRunnable);
|
||||
|
||||
LOGV(("WorkerPrivate::Dispatch [%p] runnable %p", this, runnable.get()));
|
||||
if (!aSyncLoopTarget) {
|
||||
// Dispatch control runnable
|
||||
if (runnable->IsControlRunnable()) {
|
||||
return DispatchControlRunnable(runnable.forget());
|
||||
}
|
||||
|
||||
// Dispatch debugger runnable
|
||||
if (runnable->IsDebuggerRunnable()) {
|
||||
return DispatchDebuggerRunnable(runnable.forget());
|
||||
}
|
||||
}
|
||||
MutexAutoLock lock(mMutex);
|
||||
return DispatchLockHeld(std::move(aRunnable), aSyncLoopTarget, lock);
|
||||
return DispatchLockHeld(runnable.forget(), aSyncLoopTarget, lock);
|
||||
}
|
||||
|
||||
nsresult WorkerPrivate::DispatchToParent(
|
||||
already_AddRefed<WorkerRunnable> aRunnable) {
|
||||
RefPtr<WorkerRunnable> runnable(aRunnable);
|
||||
|
||||
LOGV(("WorkerPrivate::DispatchToParent [%p] runnable %p", this,
|
||||
runnable.get()));
|
||||
|
||||
WorkerPrivate* parent = GetParent();
|
||||
// Dispatch to parent worker
|
||||
if (parent) {
|
||||
if (runnable->IsControlRunnable()) {
|
||||
return parent->DispatchControlRunnable(runnable.forget());
|
||||
}
|
||||
return parent->Dispatch(runnable.forget());
|
||||
}
|
||||
|
||||
// Dispatch to main thread
|
||||
if (runnable->IsDebuggeeRunnable()) {
|
||||
RefPtr<WorkerParentDebuggeeRunnable> debuggeeRunnable =
|
||||
runnable.forget().downcast<WorkerParentDebuggeeRunnable>();
|
||||
return DispatchDebuggeeToMainThread(debuggeeRunnable.forget(),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
return DispatchToMainThread(runnable.forget());
|
||||
}
|
||||
|
||||
nsresult WorkerPrivate::DispatchLockHeld(
|
||||
|
@ -1575,6 +1602,7 @@ nsresult WorkerPrivate::DispatchLockHeld(
|
|||
|
||||
MOZ_ASSERT_IF(aSyncLoopTarget, mThread);
|
||||
|
||||
// Dispatch normal worker runnable
|
||||
if (mStatus == Dead || (!aSyncLoopTarget && ParentStatus() > Canceling)) {
|
||||
NS_WARNING(
|
||||
"A runnable was posted to a worker that is already shutting "
|
||||
|
@ -1656,10 +1684,10 @@ void WorkerPrivate::DisableDebugger() {
|
|||
}
|
||||
|
||||
nsresult WorkerPrivate::DispatchControlRunnable(
|
||||
already_AddRefed<WorkerControlRunnable> aWorkerControlRunnable) {
|
||||
already_AddRefed<WorkerRunnable> aWorkerRunnable) {
|
||||
// May be called on any thread!
|
||||
RefPtr<WorkerControlRunnable> runnable(aWorkerControlRunnable);
|
||||
MOZ_ASSERT(runnable);
|
||||
RefPtr<WorkerRunnable> runnable(aWorkerRunnable);
|
||||
MOZ_ASSERT(runnable && runnable->IsControlRunnable());
|
||||
|
||||
LOG(WorkerLog(), ("WorkerPrivate::DispatchControlRunnable [%p] runnable %p",
|
||||
this, runnable.get()));
|
||||
|
@ -3162,7 +3190,7 @@ void WorkerPrivate::RunLoopNeverRan() {
|
|||
// After mStatus is set to Dead there can be no more
|
||||
// WorkerControlRunnables so no need to lock here.
|
||||
if (!mControlQueue.IsEmpty()) {
|
||||
WorkerControlRunnable* runnable = nullptr;
|
||||
WorkerRunnable* runnable = nullptr;
|
||||
while (mControlQueue.Pop(runnable)) {
|
||||
runnable->Cancel();
|
||||
runnable->Release();
|
||||
|
@ -3383,7 +3411,7 @@ void WorkerPrivate::DoRunLoop(JSContext* aCx) {
|
|||
("WorkerPrivate::DoRunLoop [%p] dropping control runnables in "
|
||||
"Dead status",
|
||||
this));
|
||||
WorkerControlRunnable* runnable = nullptr;
|
||||
WorkerRunnable* runnable = nullptr;
|
||||
while (mControlQueue.Pop(runnable)) {
|
||||
runnable->Cancel();
|
||||
runnable->Release();
|
||||
|
@ -3558,8 +3586,11 @@ nsresult WorkerPrivate::DispatchToMainThread(
|
|||
}
|
||||
|
||||
nsresult WorkerPrivate::DispatchDebuggeeToMainThread(
|
||||
already_AddRefed<WorkerDebuggeeRunnable> aRunnable, uint32_t aFlags) {
|
||||
return mMainThreadDebuggeeEventTarget->Dispatch(std::move(aRunnable), aFlags);
|
||||
already_AddRefed<WorkerRunnable> aRunnable, uint32_t aFlags) {
|
||||
RefPtr<WorkerRunnable> debuggeeRunnable = std::move(aRunnable);
|
||||
MOZ_ASSERT(debuggeeRunnable->IsDebuggeeRunnable());
|
||||
return mMainThreadDebuggeeEventTarget->Dispatch(debuggeeRunnable.forget(),
|
||||
aFlags);
|
||||
}
|
||||
|
||||
nsISerialEventTarget* WorkerPrivate::ControlEventTarget() {
|
||||
|
@ -4056,7 +4087,7 @@ WorkerPrivate::ProcessAllControlRunnablesLocked() {
|
|||
auto result = ProcessAllControlRunnablesResult::Nothing;
|
||||
|
||||
for (;;) {
|
||||
WorkerControlRunnable* event;
|
||||
WorkerRunnable* event;
|
||||
if (!mControlQueue.Pop(event)) {
|
||||
break;
|
||||
}
|
||||
|
@ -4876,8 +4907,8 @@ void WorkerPrivate::PostMessageToParent(
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<MessageEventRunnable> runnable =
|
||||
new MessageEventRunnable(this, WorkerRunnable::ParentThread);
|
||||
RefPtr<MessageEventToParentRunnable> runnable =
|
||||
new MessageEventToParentRunnable(this);
|
||||
|
||||
JS::CloneDataPolicy clonePolicy;
|
||||
|
||||
|
|
|
@ -590,7 +590,7 @@ class WorkerPrivate final
|
|||
uint32_t aFlags = NS_DISPATCH_NORMAL);
|
||||
|
||||
nsresult DispatchDebuggeeToMainThread(
|
||||
already_AddRefed<WorkerDebuggeeRunnable> aRunnable,
|
||||
already_AddRefed<WorkerRunnable> aRunnable,
|
||||
uint32_t aFlags = NS_DISPATCH_NORMAL);
|
||||
|
||||
// Get an event target that will dispatch runnables as control runnables on
|
||||
|
@ -1050,11 +1050,13 @@ class WorkerPrivate final
|
|||
nsIEventTarget* aSyncLoopTarget = nullptr);
|
||||
|
||||
nsresult DispatchControlRunnable(
|
||||
already_AddRefed<WorkerControlRunnable> aWorkerControlRunnable);
|
||||
already_AddRefed<WorkerRunnable> aWorkerRunnable);
|
||||
|
||||
nsresult DispatchDebuggerRunnable(
|
||||
already_AddRefed<WorkerRunnable> aDebuggerRunnable);
|
||||
|
||||
nsresult DispatchToParent(already_AddRefed<WorkerRunnable> aRunnable);
|
||||
|
||||
bool IsOnParentThread() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -1368,7 +1370,7 @@ class WorkerPrivate final
|
|||
|
||||
WorkerDebugger* mDebugger;
|
||||
|
||||
workerinternals::Queue<WorkerControlRunnable*, 4> mControlQueue;
|
||||
workerinternals::Queue<WorkerRunnable*, 4> mControlQueue;
|
||||
workerinternals::Queue<WorkerRunnable*, 4> mDebuggerQueue;
|
||||
|
||||
// Touched on multiple threads, protected with mMutex. Only modified on the
|
||||
|
|
|
@ -20,8 +20,7 @@ class ReleaseRefControlRunnable final : public WorkerControlRunnable {
|
|||
public:
|
||||
ReleaseRefControlRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
already_AddRefed<StrongWorkerRef> aRef)
|
||||
: WorkerControlRunnable(aWorkerPrivate, "ReleaseRefControlRunnable",
|
||||
WorkerThread),
|
||||
: WorkerControlRunnable(aWorkerPrivate, "ReleaseRefControlRunnable"),
|
||||
mRef(std::move(aRef)) {
|
||||
MOZ_ASSERT(mRef);
|
||||
}
|
||||
|
|
|
@ -53,14 +53,17 @@ const nsIID kWorkerRunnableIID = {
|
|||
|
||||
} // namespace
|
||||
|
||||
WorkerRunnable::WorkerRunnable(const char* aName, Target aTarget)
|
||||
: mTarget(aTarget),
|
||||
#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
|
||||
#ifdef DEBUG
|
||||
WorkerRunnable::WorkerRunnable(WorkerPrivate* aWorkerPrivate, const char* aName)
|
||||
: mWorkerPrivate(aWorkerPrivate),
|
||||
# ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
|
||||
mName(aName),
|
||||
#endif
|
||||
# endif
|
||||
mCallingCancelWithinRun(false) {
|
||||
LOG(("WorkerRunnable::WorkerRunnable [%p]", this));
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
}
|
||||
#endif
|
||||
|
||||
// static
|
||||
WorkerRunnable* WorkerRunnable::FromRunnable(nsIRunnable* aRunnable) {
|
||||
|
@ -77,6 +80,15 @@ WorkerRunnable* WorkerRunnable::FromRunnable(nsIRunnable* aRunnable) {
|
|||
return runnable;
|
||||
}
|
||||
|
||||
bool WorkerRunnable::Dispatch() {
|
||||
bool ok = PreDispatch(mWorkerPrivate);
|
||||
if (ok) {
|
||||
ok = DispatchInternal();
|
||||
}
|
||||
PostDispatch(mWorkerPrivate, ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP WorkerRunnable::Run() { return NS_OK; }
|
||||
|
||||
NS_IMPL_ADDREF(WorkerRunnable)
|
||||
|
@ -107,196 +119,71 @@ NS_INTERFACE_MAP_BEGIN(WorkerRunnable)
|
|||
} else
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
WorkerThreadRunnable::WorkerThreadRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName, Target aTarget)
|
||||
: WorkerRunnable(aName, aTarget), mWorkerPrivate(aWorkerPrivate) {
|
||||
LOG(("WorkerThreadRunnable::WorkerThreadRunnable [%p]", this));
|
||||
WorkerParentThreadRunnable::WorkerParentThreadRunnable(
|
||||
WorkerPrivate* aWorkerPrivate, const char* aName)
|
||||
: WorkerRunnable(aWorkerPrivate, aName) {
|
||||
LOG(("WorkerParentThreadRunnable::WorkerParentThreadRunnable [%p]", this));
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::IsDebuggerRunnable() const { return false; }
|
||||
|
||||
nsIGlobalObject* WorkerThreadRunnable::DefaultGlobalObject() const {
|
||||
if (IsDebuggerRunnable()) {
|
||||
return mWorkerPrivate->DebuggerGlobalScope();
|
||||
}
|
||||
return mWorkerPrivate->GlobalScope();
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::PreDispatch(WorkerPrivate* aWorkerPrivate) {
|
||||
bool WorkerParentThreadRunnable::PreDispatch(WorkerPrivate* aWorkerPrivate) {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
|
||||
switch (mTarget) {
|
||||
case WorkerRunnable::ParentThread:
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
break;
|
||||
|
||||
case WorkerRunnable::WorkerThread:
|
||||
aWorkerPrivate->AssertIsOnParentThread();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown behavior!");
|
||||
}
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::Dispatch() {
|
||||
bool ok = PreDispatch(mWorkerPrivate);
|
||||
if (ok) {
|
||||
ok = DispatchInternal();
|
||||
}
|
||||
PostDispatch(mWorkerPrivate, ok);
|
||||
return ok;
|
||||
bool WorkerParentThreadRunnable::DispatchInternal() {
|
||||
LOG(("WorkerParentThreadRunnable::DispatchInternal [%p]", this));
|
||||
RefPtr<WorkerParentThreadRunnable> runnable(this);
|
||||
|
||||
return NS_SUCCEEDED(mWorkerPrivate->DispatchToParent(runnable.forget()));
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::DispatchInternal() {
|
||||
LOG(("WorkerThreadRunnable::DispatchInternal [%p]", this));
|
||||
RefPtr<WorkerThreadRunnable> runnable(this);
|
||||
|
||||
if (mTarget == WorkerRunnable::WorkerThread) {
|
||||
if (IsDebuggerRunnable()) {
|
||||
return NS_SUCCEEDED(
|
||||
mWorkerPrivate->DispatchDebuggerRunnable(runnable.forget()));
|
||||
}
|
||||
return NS_SUCCEEDED(mWorkerPrivate->Dispatch(runnable.forget()));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mTarget == WorkerRunnable::ParentThread);
|
||||
|
||||
if (WorkerPrivate* parent = mWorkerPrivate->GetParent()) {
|
||||
return NS_SUCCEEDED(parent->Dispatch(runnable.forget()));
|
||||
}
|
||||
|
||||
if (IsDebuggeeRunnable()) {
|
||||
RefPtr<WorkerDebuggeeRunnable> debuggeeRunnable =
|
||||
runnable.forget().downcast<WorkerDebuggeeRunnable>();
|
||||
return NS_SUCCEEDED(mWorkerPrivate->DispatchDebuggeeToMainThread(
|
||||
debuggeeRunnable.forget(), NS_DISPATCH_NORMAL));
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
|
||||
}
|
||||
|
||||
void WorkerThreadRunnable::PostDispatch(WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) {
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
|
||||
void WorkerParentThreadRunnable::PostDispatch(WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) {
|
||||
#ifdef DEBUG
|
||||
switch (mTarget) {
|
||||
case WorkerRunnable::ParentThread:
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
break;
|
||||
|
||||
case WorkerRunnable::WorkerThread:
|
||||
aWorkerPrivate->AssertIsOnParentThread();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown behavior!");
|
||||
}
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::PreRun(WorkerPrivate* aWorkerPrivate) {
|
||||
bool WorkerParentThreadRunnable::PreRun(WorkerPrivate* aWorkerPrivate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorkerThreadRunnable::PostRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) {
|
||||
void WorkerParentThreadRunnable::PostRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) {
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
|
||||
#ifdef DEBUG
|
||||
switch (mTarget) {
|
||||
case WorkerRunnable::ParentThread:
|
||||
aWorkerPrivate->AssertIsOnParentThread();
|
||||
break;
|
||||
|
||||
case WorkerRunnable::WorkerThread:
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown behavior!");
|
||||
}
|
||||
aWorkerPrivate->AssertIsOnParentThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerThreadRunnable::Run() {
|
||||
LOG(("WorkerThreadRunnable::Run [%p]", this));
|
||||
bool targetIsWorkerThread = mTarget == WorkerThread;
|
||||
|
||||
WorkerParentThreadRunnable::Run() {
|
||||
LOG(("WorkerParentThreadRunnable::Run [%p]", this));
|
||||
#ifdef DEBUG
|
||||
if (targetIsWorkerThread) {
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
} else {
|
||||
MOZ_ASSERT(mTarget == WorkerRunnable::ParentThread);
|
||||
mWorkerPrivate->AssertIsOnParentThread();
|
||||
}
|
||||
mWorkerPrivate->AssertIsOnParentThread();
|
||||
#endif
|
||||
|
||||
if (targetIsWorkerThread && !mCallingCancelWithinRun &&
|
||||
mWorkerPrivate->CancelBeforeWorkerScopeConstructed()) {
|
||||
mCallingCancelWithinRun = true;
|
||||
Cancel();
|
||||
mCallingCancelWithinRun = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool result = PreRun(mWorkerPrivate);
|
||||
if (!result) {
|
||||
MOZ_ASSERT(targetIsWorkerThread,
|
||||
"The only PreRun implementation that can fail is "
|
||||
"ScriptExecutorRunnable");
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
MOZ_ASSERT(!JS_IsExceptionPending(mWorkerPrivate->GetJSContext()));
|
||||
// We can't enter a useful realm on the JSContext here; just pass it
|
||||
// in as-is.
|
||||
PostRun(mWorkerPrivate->GetJSContext(), mWorkerPrivate, false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(result);
|
||||
|
||||
// Track down the appropriate global, if any, to use for the AutoEntryScript.
|
||||
nsCOMPtr<nsIGlobalObject> globalObject;
|
||||
bool isMainThread = !targetIsWorkerThread && !mWorkerPrivate->GetParent();
|
||||
bool isMainThread = !mWorkerPrivate->GetParent();
|
||||
MOZ_ASSERT(isMainThread == NS_IsMainThread());
|
||||
RefPtr<WorkerPrivate> kungFuDeathGrip;
|
||||
if (targetIsWorkerThread) {
|
||||
globalObject = mWorkerPrivate->GetCurrentEventLoopGlobal();
|
||||
if (!globalObject) {
|
||||
globalObject = DefaultGlobalObject();
|
||||
// Our worker thread may not be in a good state here if there is no
|
||||
// JSContext avaliable. The way this manifests itself is that
|
||||
// globalObject ends up null (though it's not clear to me how we can be
|
||||
// running runnables at all when DefaultGlobalObject() is returning
|
||||
// false!) and then when we try to init the AutoJSAPI either
|
||||
// CycleCollectedJSContext::Get() returns null or it has a null JSContext.
|
||||
// In any case, we used to have a check for
|
||||
// GetCurrentWorkerThreadJSContext() being non-null here and that seems to
|
||||
// avoid the problem, so let's keep doing that check even if we don't need
|
||||
// the JSContext here at all.
|
||||
if (NS_WARN_IF(!globalObject && !GetCurrentWorkerThreadJSContext())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// We may still not have a globalObject here: in the case of
|
||||
// CompileScriptRunnable, we don't actually create the global object until
|
||||
// we have the script data, which happens in a syncloop under
|
||||
// CompileScriptRunnable::WorkerRun, so we can't assert that it got created
|
||||
// in the PreRun call above.
|
||||
kungFuDeathGrip = mWorkerPrivate;
|
||||
if (isMainThread) {
|
||||
globalObject = nsGlobalWindowInner::Cast(mWorkerPrivate->GetWindow());
|
||||
} else {
|
||||
kungFuDeathGrip = mWorkerPrivate;
|
||||
if (isMainThread) {
|
||||
globalObject = nsGlobalWindowInner::Cast(mWorkerPrivate->GetWindow());
|
||||
} else {
|
||||
globalObject = mWorkerPrivate->GetParent()->GlobalScope();
|
||||
}
|
||||
globalObject = mWorkerPrivate->GetParent()->GlobalScope();
|
||||
}
|
||||
|
||||
// We might run script as part of WorkerRun, so we need an AutoEntryScript.
|
||||
|
@ -308,8 +195,9 @@ WorkerThreadRunnable::Run() {
|
|||
Maybe<mozilla::dom::AutoEntryScript> aes;
|
||||
JSContext* cx;
|
||||
AutoJSAPI* jsapi;
|
||||
|
||||
if (globalObject) {
|
||||
aes.emplace(globalObject, "Worker runnable", isMainThread);
|
||||
aes.emplace(globalObject, "Worker parent thread runnable", isMainThread);
|
||||
jsapi = aes.ptr();
|
||||
cx = aes->cx();
|
||||
} else {
|
||||
|
@ -330,7 +218,7 @@ WorkerThreadRunnable::Run() {
|
|||
// definitely have a globalObject. If it _is_ the main thread, globalObject
|
||||
// can be null for workers started from JSMs or other non-window contexts,
|
||||
// sadly.
|
||||
MOZ_ASSERT_IF(!targetIsWorkerThread && !isMainThread,
|
||||
MOZ_ASSERT_IF(!isMainThread,
|
||||
mWorkerPrivate->IsDedicatedWorker() && globalObject);
|
||||
|
||||
// If we're on the parent thread we might be in a null realm in the
|
||||
|
@ -338,7 +226,7 @@ WorkerThreadRunnable::Run() {
|
|||
// the realm of the worker's reflector if there is one. There might
|
||||
// not be one if we're just starting to compile the script for this worker.
|
||||
Maybe<JSAutoRealm> ar;
|
||||
if (!targetIsWorkerThread && mWorkerPrivate->IsDedicatedWorker() &&
|
||||
if (mWorkerPrivate->IsDedicatedWorker() &&
|
||||
mWorkerPrivate->ParentEventTargetRef()->GetWrapper()) {
|
||||
JSObject* wrapper = mWorkerPrivate->ParentEventTargetRef()->GetWrapper();
|
||||
|
||||
|
@ -394,6 +282,193 @@ WorkerThreadRunnable::Run() {
|
|||
return result ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult WorkerParentThreadRunnable::Cancel() {
|
||||
LOG(("WorkerThreadRunnable::Cancel [%p]", this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
WorkerParentControlRunnable::WorkerParentControlRunnable(
|
||||
WorkerPrivate* aWorkerPrivate, const char* aName)
|
||||
: WorkerParentThreadRunnable(aWorkerPrivate, aName) {
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult WorkerParentControlRunnable::Cancel() {
|
||||
LOG(("WorkerParentControlRunnable::Cancel [%p]", this));
|
||||
if (NS_FAILED(Run())) {
|
||||
NS_WARNING("WorkerParentControlRunnable::Run() failed.");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool WorkerParentDebuggeeRunnable::PreDispatch(WorkerPrivate* aWorkerPrivate) {
|
||||
RefPtr<StrongWorkerRef> strongRef = StrongWorkerRef::Create(
|
||||
aWorkerPrivate, "WorkerDebuggeeRunnable::mSender");
|
||||
if (!strongRef) {
|
||||
return false;
|
||||
}
|
||||
mSender = new ThreadSafeWorkerRef(strongRef);
|
||||
|
||||
return WorkerParentThreadRunnable::PreDispatch(aWorkerPrivate);
|
||||
}
|
||||
|
||||
WorkerThreadRunnable::WorkerThreadRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName)
|
||||
: WorkerRunnable(aWorkerPrivate, aName) {
|
||||
LOG(("WorkerThreadRunnable::WorkerThreadRunnable [%p]", this));
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
}
|
||||
|
||||
nsIGlobalObject* WorkerThreadRunnable::DefaultGlobalObject() const {
|
||||
if (IsDebuggerRunnable()) {
|
||||
return mWorkerPrivate->DebuggerGlobalScope();
|
||||
}
|
||||
return mWorkerPrivate->GlobalScope();
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::PreDispatch(WorkerPrivate* aWorkerPrivate) {
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
#ifdef DEBUG
|
||||
aWorkerPrivate->AssertIsOnParentThread();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::DispatchInternal() {
|
||||
LOG(("WorkerThreadRunnable::DispatchInternal [%p]", this));
|
||||
RefPtr<WorkerThreadRunnable> runnable(this);
|
||||
|
||||
return NS_SUCCEEDED(mWorkerPrivate->Dispatch(runnable.forget()));
|
||||
}
|
||||
|
||||
void WorkerThreadRunnable::PostDispatch(WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) {
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
#ifdef DEBUG
|
||||
aWorkerPrivate->AssertIsOnParentThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WorkerThreadRunnable::PreRun(WorkerPrivate* aWorkerPrivate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorkerThreadRunnable::PostRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) {
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
|
||||
#ifdef DEBUG
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WorkerThreadRunnable::Run() {
|
||||
LOG(("WorkerThreadRunnable::Run [%p]", this));
|
||||
#ifdef DEBUG
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
#endif
|
||||
|
||||
if (!mCallingCancelWithinRun &&
|
||||
mWorkerPrivate->CancelBeforeWorkerScopeConstructed()) {
|
||||
mCallingCancelWithinRun = true;
|
||||
Cancel();
|
||||
mCallingCancelWithinRun = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool result = PreRun(mWorkerPrivate);
|
||||
if (!result) {
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
MOZ_ASSERT(!JS_IsExceptionPending(mWorkerPrivate->GetJSContext()));
|
||||
// We can't enter a useful realm on the JSContext here; just pass it
|
||||
// in as-is.
|
||||
PostRun(mWorkerPrivate->GetJSContext(), mWorkerPrivate, false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Track down the appropriate global, if any, to use for the AutoEntryScript.
|
||||
nsCOMPtr<nsIGlobalObject> globalObject =
|
||||
mWorkerPrivate->GetCurrentEventLoopGlobal();
|
||||
RefPtr<WorkerPrivate> kungFuDeathGrip;
|
||||
if (!globalObject) {
|
||||
globalObject = DefaultGlobalObject();
|
||||
// Our worker thread may not be in a good state here if there is no
|
||||
// JSContext avaliable. The way this manifests itself is that
|
||||
// globalObject ends up null (though it's not clear to me how we can be
|
||||
// running runnables at all when DefaultGlobalObject() is returning
|
||||
// false!) and then when we try to init the AutoJSAPI either
|
||||
// CycleCollectedJSContext::Get() returns null or it has a null JSContext.
|
||||
// In any case, we used to have a check for
|
||||
// GetCurrentWorkerThreadJSContext() being non-null here and that seems to
|
||||
// avoid the problem, so let's keep doing that check even if we don't need
|
||||
// the JSContext here at all.
|
||||
if (NS_WARN_IF(!globalObject && !GetCurrentWorkerThreadJSContext())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// We might run script as part of WorkerRun, so we need an AutoEntryScript.
|
||||
// This is part of the HTML spec for workers at:
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#run-a-worker
|
||||
// If we don't have a globalObject we have to use an AutoJSAPI instead, but
|
||||
// this is OK as we won't be running script in these circumstances.
|
||||
Maybe<mozilla::dom::AutoJSAPI> maybeJSAPI;
|
||||
Maybe<mozilla::dom::AutoEntryScript> aes;
|
||||
JSContext* cx;
|
||||
AutoJSAPI* jsapi;
|
||||
if (globalObject) {
|
||||
aes.emplace(globalObject, "Worker runnable", false);
|
||||
jsapi = aes.ptr();
|
||||
cx = aes->cx();
|
||||
} else {
|
||||
maybeJSAPI.emplace();
|
||||
maybeJSAPI->Init();
|
||||
jsapi = maybeJSAPI.ptr();
|
||||
cx = jsapi->cx();
|
||||
}
|
||||
|
||||
// Note that we can't assert anything about
|
||||
// mWorkerPrivate->ParentEventTargetRef()->GetWrapper()
|
||||
// existing, since it may in fact have been GCed (and we may be one of the
|
||||
// runnables cleaning up the worker as a result).
|
||||
|
||||
MOZ_ASSERT(!jsapi->HasException());
|
||||
result = WorkerRun(cx, mWorkerPrivate);
|
||||
jsapi->ReportException();
|
||||
|
||||
// We can't even assert that this didn't create our global, since in the case
|
||||
// of CompileScriptRunnable it _does_.
|
||||
|
||||
// It would be nice to avoid passing a JSContext to PostRun, but in the case
|
||||
// of ScriptExecutorRunnable we need to know the current compartment on the
|
||||
// JSContext (the one we set up based on the global returned from PreRun) so
|
||||
// that we can sanely do exception reporting. In particular, we want to make
|
||||
// sure that we do our JS_SetPendingException while still in that compartment,
|
||||
// because otherwise we might end up trying to create a cross-compartment
|
||||
// wrapper when we try to move the JS exception from our runnable's
|
||||
// ErrorResult to the JSContext, and that's not desirable in this case.
|
||||
//
|
||||
// We _could_ skip passing a JSContext here and then in
|
||||
// ScriptExecutorRunnable::PostRun end up grabbing it from the WorkerPrivate
|
||||
// and looking at its current compartment. But that seems like slightly weird
|
||||
// action-at-a-distance...
|
||||
//
|
||||
// In any case, we do NOT try to change the compartment on the JSContext at
|
||||
// this point; in the one case in which we could do that
|
||||
// (CompileScriptRunnable) it actually doesn't matter which compartment we're
|
||||
// in for PostRun.
|
||||
PostRun(cx, mWorkerPrivate, result);
|
||||
MOZ_ASSERT(!jsapi->HasException());
|
||||
|
||||
return result ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult WorkerThreadRunnable::Cancel() {
|
||||
LOG(("WorkerThreadRunnable::Cancel [%p]", this));
|
||||
return NS_OK;
|
||||
|
@ -405,7 +480,7 @@ void WorkerDebuggerRunnable::PostDispatch(WorkerPrivate* aWorkerPrivate,
|
|||
WorkerSyncRunnable::WorkerSyncRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
nsIEventTarget* aSyncLoopTarget,
|
||||
const char* aName)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName, WorkerRunnable::WorkerThread),
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName),
|
||||
mSyncLoopTarget(aSyncLoopTarget) {
|
||||
#ifdef DEBUG
|
||||
if (mSyncLoopTarget) {
|
||||
|
@ -417,7 +492,7 @@ WorkerSyncRunnable::WorkerSyncRunnable(WorkerPrivate* aWorkerPrivate,
|
|||
WorkerSyncRunnable::WorkerSyncRunnable(
|
||||
WorkerPrivate* aWorkerPrivate, nsCOMPtr<nsIEventTarget>&& aSyncLoopTarget,
|
||||
const char* aName)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName, WorkerRunnable::WorkerThread),
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName),
|
||||
mSyncLoopTarget(std::move(aSyncLoopTarget)) {
|
||||
#ifdef DEBUG
|
||||
if (mSyncLoopTarget) {
|
||||
|
@ -488,8 +563,8 @@ void MainThreadStopSyncLoopRunnable::PostDispatch(WorkerPrivate* aWorkerPrivate,
|
|||
|
||||
#ifdef DEBUG
|
||||
WorkerControlRunnable::WorkerControlRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName, Target aTarget)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName, aTarget) {
|
||||
const char* aName)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName) {
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
}
|
||||
#endif
|
||||
|
@ -503,21 +578,6 @@ nsresult WorkerControlRunnable::Cancel() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool WorkerControlRunnable::DispatchInternal() {
|
||||
RefPtr<WorkerControlRunnable> runnable(this);
|
||||
|
||||
if (mTarget == WorkerRunnable::WorkerThread) {
|
||||
return NS_SUCCEEDED(
|
||||
mWorkerPrivate->DispatchControlRunnable(runnable.forget()));
|
||||
}
|
||||
|
||||
if (WorkerPrivate* parent = mWorkerPrivate->GetParent()) {
|
||||
return NS_SUCCEEDED(parent->DispatchControlRunnable(runnable.forget()));
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
|
||||
}
|
||||
|
||||
WorkerMainThreadRunnable::WorkerMainThreadRunnable(
|
||||
WorkerPrivate* aWorkerPrivate, const nsACString& aTelemetryKey)
|
||||
: mozilla::Runnable("dom::WorkerMainThreadRunnable"),
|
||||
|
@ -677,18 +737,4 @@ void WorkerProxyToMainThreadRunnable::PostDispatchOnMainThread() {
|
|||
|
||||
void WorkerProxyToMainThreadRunnable::ReleaseWorker() { mWorkerRef = nullptr; }
|
||||
|
||||
bool WorkerDebuggeeRunnable::PreDispatch(WorkerPrivate* aWorkerPrivate) {
|
||||
if (mTarget == WorkerRunnable::ParentThread) {
|
||||
RefPtr<StrongWorkerRef> strongRef = StrongWorkerRef::Create(
|
||||
aWorkerPrivate, "WorkerDebuggeeRunnable::mSender");
|
||||
if (!strongRef) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mSender = new ThreadSafeWorkerRef(strongRef);
|
||||
}
|
||||
|
||||
return WorkerThreadRunnable::PreDispatch(aWorkerPrivate);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -39,19 +39,9 @@ class WorkerRunnable : public nsIRunnable
|
|||
public nsINamed
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
enum Target {
|
||||
// Target the main thread for top-level workers, otherwise target the
|
||||
// WorkerThread of the worker's parent.
|
||||
ParentThread,
|
||||
|
||||
// Target the thread where the worker event loop runs.
|
||||
WorkerThread,
|
||||
};
|
||||
|
||||
protected:
|
||||
// See above.
|
||||
Target mTarget;
|
||||
// The WorkerPrivate that this runnable is associated with.
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
|
||||
#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
|
||||
const char* mName = nullptr;
|
||||
|
@ -72,7 +62,7 @@ class WorkerRunnable : public nsIRunnable
|
|||
|
||||
// The return value is true if and only if both PreDispatch and
|
||||
// DispatchInternal return true.
|
||||
virtual bool Dispatch() = 0;
|
||||
virtual bool Dispatch();
|
||||
|
||||
// True if this runnable is handled by running JavaScript in some global that
|
||||
// could possibly be a debuggee, and thus needs to be deferred when the target
|
||||
|
@ -85,11 +75,27 @@ class WorkerRunnable : public nsIRunnable
|
|||
// support debugging the debugger server at the moment.
|
||||
virtual bool IsDebuggeeRunnable() const { return false; }
|
||||
|
||||
// True if this runnable needs to be dispatched to
|
||||
// WorkerPrivate::mControlEventTareget.
|
||||
virtual bool IsControlRunnable() const { return false; }
|
||||
|
||||
// True if this runnable should be dispatched to the debugger queue,
|
||||
// and false otherwise.
|
||||
virtual bool IsDebuggerRunnable() const { return false; }
|
||||
|
||||
static WorkerRunnable* FromRunnable(nsIRunnable* aRunnable);
|
||||
|
||||
protected:
|
||||
WorkerRunnable(const char* aName = "WorkerRunnable",
|
||||
Target aTarget = WorkerThread);
|
||||
WorkerRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerRunnable")
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
: mWorkerPrivate(aWorkerPrivate),
|
||||
mName(aName),
|
||||
mCallingCancelWithinRun(false) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// This class is reference counted.
|
||||
virtual ~WorkerRunnable() = default;
|
||||
|
@ -97,42 +103,15 @@ class WorkerRunnable : public nsIRunnable
|
|||
// Calling Run() directly is not supported. Just call Dispatch() and
|
||||
// WorkerRun() will be called on the correct thread automatically.
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
class WorkerThreadRunnable : public WorkerRunnable {
|
||||
protected:
|
||||
// The WorkerPrivate that this runnable is associated with.
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
|
||||
public:
|
||||
virtual nsresult Cancel() override;
|
||||
|
||||
// The return value is true if and only if both PreDispatch and
|
||||
// DispatchInternal return true.
|
||||
bool Dispatch() override;
|
||||
|
||||
protected:
|
||||
explicit WorkerThreadRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerThreadRunnable",
|
||||
Target aTarget = WorkerRunnable::WorkerThread);
|
||||
|
||||
// This class is reference counted.
|
||||
virtual ~WorkerThreadRunnable() = default;
|
||||
|
||||
// Returns true if this runnable should be dispatched to the debugger queue,
|
||||
// and false otherwise.
|
||||
virtual bool IsDebuggerRunnable() const;
|
||||
|
||||
nsIGlobalObject* DefaultGlobalObject() const;
|
||||
|
||||
// By default asserts that Dispatch() is being called on the right thread
|
||||
// (ParentThread if |mTarget| is WorkerThread).
|
||||
virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate);
|
||||
virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) = 0;
|
||||
|
||||
// By default asserts that Dispatch() is being called on the right thread
|
||||
// (ParentThread if |mTarget| is WorkerThread).
|
||||
virtual void PostDispatch(WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult);
|
||||
bool aDispatchResult) = 0;
|
||||
|
||||
virtual bool DispatchInternal() = 0;
|
||||
|
||||
// May be implemented by subclasses if desired if they need to do some sort of
|
||||
// setup before we try to set up our JSContext and compartment for real.
|
||||
|
@ -141,17 +120,19 @@ class WorkerThreadRunnable : public WorkerRunnable {
|
|||
//
|
||||
// If false is returned, WorkerRun will not be called at all. PostRun will
|
||||
// still be called, with false passed for aRunResult.
|
||||
virtual bool PreRun(WorkerPrivate* aWorkerPrivate);
|
||||
virtual bool PreRun(WorkerPrivate* aWorkerPrivate) = 0;
|
||||
|
||||
// Must be implemented by subclasses. Called on the target thread. The return
|
||||
// value will be passed to PostRun(). The JSContext passed in here comes from
|
||||
// an AutoJSAPI (or AutoEntryScript) that we set up on the stack. If
|
||||
// mTarget is ParentThread, it is in the compartment of
|
||||
// an AutoJSAPI (or AutoEntryScript) that we set up on the stack.
|
||||
//
|
||||
// If the runnable is for parent thread, aCx is in the compartment of
|
||||
// mWorkerPrivate's reflector (i.e. the worker object in the parent thread),
|
||||
// unless that reflector is null, in which case it's in the compartment of the
|
||||
// parent global (which is the compartment reflector would have been in), or
|
||||
// in the null compartment if there is no parent global. For other mTarget
|
||||
// values, we're running on the worker thread and aCx is in whatever
|
||||
// in the null compartment if there is no parent global.
|
||||
//
|
||||
// For runnables on the worker thread, aCx is in whatever
|
||||
// compartment GetCurrentWorkerThreadJSContext() was in when
|
||||
// nsIRunnable::Run() got called. This is actually important for cases when a
|
||||
// runnable spins a syncloop and wants everything that happens during the
|
||||
|
@ -174,9 +155,125 @@ class WorkerThreadRunnable : public WorkerRunnable {
|
|||
// exception on the JSContext and must not run script, because the incoming
|
||||
// JSContext may be in the null compartment.
|
||||
virtual void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult);
|
||||
bool aRunResult) = 0;
|
||||
};
|
||||
|
||||
virtual bool DispatchInternal();
|
||||
class WorkerParentThreadRunnable : public WorkerRunnable {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(WorkerParentThreadRunnable,
|
||||
WorkerRunnable)
|
||||
|
||||
virtual nsresult Cancel() override;
|
||||
|
||||
protected:
|
||||
explicit WorkerParentThreadRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerParentThreadRunnable");
|
||||
|
||||
// This class is reference counted.
|
||||
virtual ~WorkerParentThreadRunnable() = default;
|
||||
|
||||
virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
virtual void PostDispatch(WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override;
|
||||
|
||||
virtual bool PreRun(WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
virtual bool WorkerRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate) override = 0;
|
||||
|
||||
virtual void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) override;
|
||||
|
||||
virtual bool DispatchInternal() override;
|
||||
|
||||
// Calling Run() directly is not supported. Just call Dispatch() and
|
||||
// WorkerRun() will be called on the correct thread automatically.
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
class WorkerParentControlRunnable : public WorkerParentThreadRunnable {
|
||||
friend class WorkerPrivate;
|
||||
|
||||
protected:
|
||||
explicit WorkerParentControlRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerParentControlRunnable")
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
: WorkerParentThreadRunnable(aWorkerPrivate, aName) {
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual ~WorkerParentControlRunnable() = default;
|
||||
|
||||
nsresult Cancel() override;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(WorkerParentControlRunnable,
|
||||
WorkerParentThreadRunnable)
|
||||
|
||||
private:
|
||||
bool IsControlRunnable() const override { return true; }
|
||||
|
||||
// Should only be called by WorkerPrivate::DoRunLoop.
|
||||
using WorkerParentThreadRunnable::Cancel;
|
||||
};
|
||||
|
||||
class WorkerParentDebuggeeRunnable : public WorkerParentThreadRunnable {
|
||||
protected:
|
||||
explicit WorkerParentDebuggeeRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerParentDebuggeeRunnable")
|
||||
: WorkerParentThreadRunnable(aWorkerPrivate, aName) {}
|
||||
|
||||
bool PreDispatch(WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
private:
|
||||
// This override is deliberately private: it doesn't make sense to call it if
|
||||
// we know statically that we are a WorkerDebuggeeRunnable.
|
||||
bool IsDebuggeeRunnable() const override { return true; }
|
||||
|
||||
// Runnables sent upwards, to the content window or parent worker, must keep
|
||||
// their sender alive until they are delivered: they check back with the
|
||||
// sender in case it has been terminated after having dispatched the runnable
|
||||
// (in which case it should not be acted upon); and runnables sent to content
|
||||
// wait until delivery to determine the target window, since
|
||||
// WorkerPrivate::GetWindow may only be used on the main thread.
|
||||
RefPtr<ThreadSafeWorkerRef> mSender;
|
||||
};
|
||||
|
||||
class WorkerThreadRunnable : public WorkerRunnable {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(WorkerThreadRunnable, WorkerRunnable)
|
||||
|
||||
virtual nsresult Cancel() override;
|
||||
|
||||
protected:
|
||||
explicit WorkerThreadRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerThreadRunnable");
|
||||
|
||||
// This class is reference counted.
|
||||
virtual ~WorkerThreadRunnable() = default;
|
||||
|
||||
nsIGlobalObject* DefaultGlobalObject() const;
|
||||
|
||||
virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
virtual void PostDispatch(WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override;
|
||||
|
||||
virtual bool PreRun(WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
virtual bool WorkerRun(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate) override = 0;
|
||||
|
||||
virtual void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) override;
|
||||
|
||||
virtual bool DispatchInternal() override;
|
||||
|
||||
// Calling Run() directly is not supported. Just call Dispatch() and
|
||||
// WorkerRun() will be called on the correct thread automatically.
|
||||
|
@ -188,8 +285,7 @@ class WorkerDebuggerRunnable : public WorkerThreadRunnable {
|
|||
protected:
|
||||
explicit WorkerDebuggerRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerDebuggerRunnable")
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName,
|
||||
WorkerRunnable::WorkerThread) {}
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName) {}
|
||||
|
||||
virtual ~WorkerDebuggerRunnable() = default;
|
||||
|
||||
|
@ -268,12 +364,11 @@ class WorkerControlRunnable : public WorkerThreadRunnable {
|
|||
|
||||
protected:
|
||||
explicit WorkerControlRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerControlRunnable",
|
||||
Target aTarget = WorkerRunnable::WorkerThread)
|
||||
const char* aName = "WorkerControlRunnable")
|
||||
#ifdef DEBUG
|
||||
;
|
||||
#else
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName, aTarget) {
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -286,7 +381,7 @@ class WorkerControlRunnable : public WorkerThreadRunnable {
|
|||
WorkerThreadRunnable)
|
||||
|
||||
private:
|
||||
virtual bool DispatchInternal() override;
|
||||
bool IsControlRunnable() const override { return true; }
|
||||
|
||||
// Should only be called by WorkerPrivate::DoRunLoop.
|
||||
using WorkerThreadRunnable::Cancel;
|
||||
|
@ -299,8 +394,7 @@ class MainThreadWorkerRunnable : public WorkerThreadRunnable {
|
|||
explicit MainThreadWorkerRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "MainThreadWorkerRunnable")
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName,
|
||||
WorkerRunnable::WorkerThread) {
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName) {
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
|
@ -324,8 +418,7 @@ class MainThreadWorkerControlRunnable : public WorkerControlRunnable {
|
|||
explicit MainThreadWorkerControlRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "MainThreadWorkerControlRunnable")
|
||||
: WorkerControlRunnable(aWorkerPrivate, aName,
|
||||
WorkerRunnable::WorkerThread) {}
|
||||
: WorkerControlRunnable(aWorkerPrivate, aName) {}
|
||||
|
||||
virtual ~MainThreadWorkerControlRunnable() = default;
|
||||
|
||||
|
@ -350,8 +443,7 @@ class WorkerSameThreadRunnable : public WorkerThreadRunnable {
|
|||
explicit WorkerSameThreadRunnable(
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerSameThreadRunnable")
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName,
|
||||
WorkerRunnable::WorkerThread) {}
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName) {}
|
||||
|
||||
virtual ~WorkerSameThreadRunnable() = default;
|
||||
|
||||
|
@ -486,28 +578,13 @@ class MainThreadStopSyncLoopRunnable : public WorkerSyncRunnable {
|
|||
class WorkerDebuggeeRunnable : public WorkerThreadRunnable {
|
||||
protected:
|
||||
explicit WorkerDebuggeeRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const char* aName = "WorkerDebuggeeRunnable",
|
||||
Target aTarget = WorkerRunnable::ParentThread)
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName, aTarget) {}
|
||||
|
||||
bool PreDispatch(WorkerPrivate* aWorkerPrivate) override;
|
||||
const char* aName = "WorkerDebuggeeRunnable")
|
||||
: WorkerThreadRunnable(aWorkerPrivate, aName) {}
|
||||
|
||||
private:
|
||||
// This override is deliberately private: it doesn't make sense to call it if
|
||||
// we know statically that we are a WorkerDebuggeeRunnable.
|
||||
bool IsDebuggeeRunnable() const override { return true; }
|
||||
|
||||
// Runnables sent upwards, to the content window or parent worker, must keep
|
||||
// their sender alive until they are delivered: they check back with the
|
||||
// sender in case it has been terminated after having dispatched the runnable
|
||||
// (in which case it should not be acted upon); and runnables sent to content
|
||||
// wait until delivery to determine the target window, since
|
||||
// WorkerPrivate::GetWindow may only be used on the main thread.
|
||||
//
|
||||
// Runnables sent downwards, from content to a worker or from a worker to a
|
||||
// child, keep the sender alive because they are WorkerThread
|
||||
// runnables, and so leave this null.
|
||||
RefPtr<ThreadSafeWorkerRef> mSender;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -211,8 +211,7 @@ class CanvasDataShmemHolder {
|
|||
DestroyRunnable(dom::WorkerPrivate* aWorkerPrivate,
|
||||
CanvasDataShmemHolder* aShmemHolder)
|
||||
: dom::WorkerThreadRunnable(aWorkerPrivate,
|
||||
"CanvasDataShmemHolder::Destroy",
|
||||
dom::WorkerRunnable::WorkerThread),
|
||||
"CanvasDataShmemHolder::Destroy"),
|
||||
mShmemHolder(aShmemHolder) {}
|
||||
|
||||
bool WorkerRun(JSContext* aCx,
|
||||
|
|
|
@ -135,8 +135,7 @@ class ExtensionListenerCallWorkerRunnable final
|
|||
ListenerCallOptions* aCallOptions,
|
||||
RefPtr<dom::Promise> aPromiseRetval = nullptr)
|
||||
: WorkerThreadRunnable(aExtensionEventListener->GetWorkerPrivate(),
|
||||
"ExtensionListenerCallWorkerRunnable",
|
||||
WorkerRunnable::WorkerThread),
|
||||
"ExtensionListenerCallWorkerRunnable"),
|
||||
mListener(aExtensionEventListener),
|
||||
mArgsHolder(std::move(aArgsHolder)),
|
||||
mPromiseResult(std::move(aPromiseRetval)),
|
||||
|
|
Загрузка…
Ссылка в новой задаче