1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WorkerRunnable.h"
9 #include "WorkerScope.h"
10 #include "js/RootingAPI.h"
12 #include "jsfriendapi.h"
13 #include "mozilla/AlreadyAddRefed.h"
14 #include "mozilla/AppShutdown.h"
15 #include "mozilla/Assertions.h"
16 #include "mozilla/CycleCollectedJSContext.h"
17 #include "mozilla/DebugOnly.h"
18 #include "mozilla/ErrorResult.h"
19 #include "mozilla/Logging.h"
20 #include "mozilla/Maybe.h"
21 #include "mozilla/Telemetry.h"
22 #include "mozilla/TelemetryHistogramEnums.h"
23 #include "mozilla/TimeStamp.h"
24 #include "mozilla/Unused.h"
25 #include "mozilla/dom/ScriptSettings.h"
26 #include "mozilla/dom/Worker.h"
27 #include "mozilla/dom/WorkerCommon.h"
29 #include "nsGlobalWindowInner.h"
31 #include "nsIEventTarget.h"
32 #include "nsIGlobalObject.h"
33 #include "nsIRunnable.h"
34 #include "nsThreadUtils.h"
35 #include "nsWrapperCacheInlines.h"
37 namespace mozilla::dom
{
39 static mozilla::LazyLogModule
sWorkerRunnableLog("WorkerRunnable");
44 #define LOG(args) MOZ_LOG(sWorkerRunnableLog, LogLevel::Verbose, args);
48 const nsIID kWorkerRunnableIID
= {
52 {0x88, 0x6e, 0xca, 0x6a, 0x81, 0xe4, 0x1d, 0x68}};
57 WorkerRunnable::WorkerRunnable(WorkerPrivate
* aWorkerPrivate
, const char* aName
,
59 : mWorkerPrivate(aWorkerPrivate
),
61 # ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
64 mCallingCancelWithinRun(false) {
65 LOG(("WorkerRunnable::WorkerRunnable [%p]", this));
66 MOZ_ASSERT(aWorkerPrivate
);
70 bool WorkerRunnable::IsDebuggerRunnable() const { return false; }
72 nsIGlobalObject
* WorkerRunnable::DefaultGlobalObject() const {
73 if (IsDebuggerRunnable()) {
74 return mWorkerPrivate
->DebuggerGlobalScope();
76 return mWorkerPrivate
->GlobalScope();
80 bool WorkerRunnable::PreDispatch(WorkerPrivate
* aWorkerPrivate
) {
82 MOZ_ASSERT(aWorkerPrivate
);
86 aWorkerPrivate
->AssertIsOnWorkerThread();
90 aWorkerPrivate
->AssertIsOnParentThread();
94 MOZ_ASSERT_UNREACHABLE("Unknown behavior!");
100 bool WorkerRunnable::Dispatch() {
101 bool ok
= PreDispatch(mWorkerPrivate
);
103 ok
= DispatchInternal();
105 PostDispatch(mWorkerPrivate
, ok
);
109 bool WorkerRunnable::DispatchInternal() {
110 LOG(("WorkerRunnable::DispatchInternal [%p]", this));
111 RefPtr
<WorkerRunnable
> runnable(this);
113 if (mTarget
== WorkerThread
) {
114 if (IsDebuggerRunnable()) {
116 mWorkerPrivate
->DispatchDebuggerRunnable(runnable
.forget()));
118 return NS_SUCCEEDED(mWorkerPrivate
->Dispatch(runnable
.forget()));
122 MOZ_ASSERT(mTarget
== ParentThread
);
124 if (WorkerPrivate
* parent
= mWorkerPrivate
->GetParent()) {
125 return NS_SUCCEEDED(parent
->Dispatch(runnable
.forget()));
128 if (IsDebuggeeRunnable()) {
129 RefPtr
<WorkerDebuggeeRunnable
> debuggeeRunnable
=
130 runnable
.forget().downcast
<WorkerDebuggeeRunnable
>();
131 return NS_SUCCEEDED(mWorkerPrivate
->DispatchDebuggeeToMainThread(
132 debuggeeRunnable
.forget(), NS_DISPATCH_NORMAL
));
135 return NS_SUCCEEDED(mWorkerPrivate
->DispatchToMainThread(runnable
.forget()));
138 void WorkerRunnable::PostDispatch(WorkerPrivate
* aWorkerPrivate
,
139 bool aDispatchResult
) {
140 MOZ_ASSERT(aWorkerPrivate
);
145 aWorkerPrivate
->AssertIsOnWorkerThread();
149 aWorkerPrivate
->AssertIsOnParentThread();
153 MOZ_ASSERT_UNREACHABLE("Unknown behavior!");
158 bool WorkerRunnable::PreRun(WorkerPrivate
* aWorkerPrivate
) { return true; }
160 void WorkerRunnable::PostRun(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
,
163 MOZ_ASSERT(aWorkerPrivate
);
168 aWorkerPrivate
->AssertIsOnParentThread();
172 aWorkerPrivate
->AssertIsOnWorkerThread();
176 MOZ_ASSERT_UNREACHABLE("Unknown behavior!");
182 WorkerRunnable
* WorkerRunnable::FromRunnable(nsIRunnable
* aRunnable
) {
183 MOZ_ASSERT(aRunnable
);
185 WorkerRunnable
* runnable
;
186 nsresult rv
= aRunnable
->QueryInterface(kWorkerRunnableIID
,
187 reinterpret_cast<void**>(&runnable
));
192 MOZ_ASSERT(runnable
);
196 NS_IMPL_ADDREF(WorkerRunnable
)
197 NS_IMPL_RELEASE(WorkerRunnable
)
199 #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
201 WorkerRunnable::GetName(nsACString
& aName
) {
203 aName
.AssignASCII(mName
);
211 NS_INTERFACE_MAP_BEGIN(WorkerRunnable
)
212 NS_INTERFACE_MAP_ENTRY(nsIRunnable
)
213 #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
214 NS_INTERFACE_MAP_ENTRY(nsINamed
)
216 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIRunnable
)
217 // kWorkerRunnableIID is special in that it does not AddRef its result.
218 if (aIID
.Equals(kWorkerRunnableIID
)) {
219 *aInstancePtr
= this;
225 WorkerRunnable::Run() {
226 LOG(("WorkerRunnable::Run [%p]", this));
227 bool targetIsWorkerThread
= mTarget
== WorkerThread
;
230 if (targetIsWorkerThread
) {
231 mWorkerPrivate
->AssertIsOnWorkerThread();
233 MOZ_ASSERT(mTarget
== ParentThread
);
234 mWorkerPrivate
->AssertIsOnParentThread();
238 if (targetIsWorkerThread
&& !mCallingCancelWithinRun
&&
239 mWorkerPrivate
->CancelBeforeWorkerScopeConstructed()) {
240 mCallingCancelWithinRun
= true;
242 mCallingCancelWithinRun
= false;
246 bool result
= PreRun(mWorkerPrivate
);
248 MOZ_ASSERT(targetIsWorkerThread
,
249 "The only PreRun implementation that can fail is "
250 "ScriptExecutorRunnable");
251 mWorkerPrivate
->AssertIsOnWorkerThread();
252 MOZ_ASSERT(!JS_IsExceptionPending(mWorkerPrivate
->GetJSContext()));
253 // We can't enter a useful realm on the JSContext here; just pass it
255 PostRun(mWorkerPrivate
->GetJSContext(), mWorkerPrivate
, false);
256 return NS_ERROR_FAILURE
;
259 // Track down the appropriate global, if any, to use for the AutoEntryScript.
260 nsCOMPtr
<nsIGlobalObject
> globalObject
;
261 bool isMainThread
= !targetIsWorkerThread
&& !mWorkerPrivate
->GetParent();
262 MOZ_ASSERT(isMainThread
== NS_IsMainThread());
263 RefPtr
<WorkerPrivate
> kungFuDeathGrip
;
264 if (targetIsWorkerThread
) {
265 globalObject
= mWorkerPrivate
->GetCurrentEventLoopGlobal();
267 globalObject
= DefaultGlobalObject();
268 // Our worker thread may not be in a good state here if there is no
269 // JSContext avaliable. The way this manifests itself is that
270 // globalObject ends up null (though it's not clear to me how we can be
271 // running runnables at all when DefaultGlobalObject() is returning
272 // false!) and then when we try to init the AutoJSAPI either
273 // CycleCollectedJSContext::Get() returns null or it has a null JSContext.
274 // In any case, we used to have a check for
275 // GetCurrentWorkerThreadJSContext() being non-null here and that seems to
276 // avoid the problem, so let's keep doing that check even if we don't need
277 // the JSContext here at all.
278 if (NS_WARN_IF(!globalObject
&& !GetCurrentWorkerThreadJSContext())) {
279 return NS_ERROR_FAILURE
;
283 // We may still not have a globalObject here: in the case of
284 // CompileScriptRunnable, we don't actually create the global object until
285 // we have the script data, which happens in a syncloop under
286 // CompileScriptRunnable::WorkerRun, so we can't assert that it got created
287 // in the PreRun call above.
289 kungFuDeathGrip
= mWorkerPrivate
;
291 globalObject
= nsGlobalWindowInner::Cast(mWorkerPrivate
->GetWindow());
293 globalObject
= mWorkerPrivate
->GetParent()->GlobalScope();
297 // We might run script as part of WorkerRun, so we need an AutoEntryScript.
298 // This is part of the HTML spec for workers at:
299 // http://www.whatwg.org/specs/web-apps/current-work/#run-a-worker
300 // If we don't have a globalObject we have to use an AutoJSAPI instead, but
301 // this is OK as we won't be running script in these circumstances.
302 Maybe
<mozilla::dom::AutoJSAPI
> maybeJSAPI
;
303 Maybe
<mozilla::dom::AutoEntryScript
> aes
;
307 aes
.emplace(globalObject
, "Worker runnable", isMainThread
);
311 maybeJSAPI
.emplace();
313 jsapi
= maybeJSAPI
.ptr();
317 // Note that we can't assert anything about
318 // mWorkerPrivate->ParentEventTargetRef()->GetWrapper()
319 // existing, since it may in fact have been GCed (and we may be one of the
320 // runnables cleaning up the worker as a result).
322 // If we are on the parent thread and that thread is not the main thread,
323 // then we must be a dedicated worker (because there are no
324 // Shared/ServiceWorkers whose parent is itself a worker) and then we
325 // definitely have a globalObject. If it _is_ the main thread, globalObject
326 // can be null for workers started from JSMs or other non-window contexts,
328 MOZ_ASSERT_IF(!targetIsWorkerThread
&& !isMainThread
,
329 mWorkerPrivate
->IsDedicatedWorker() && globalObject
);
331 // If we're on the parent thread we might be in a null realm in the
332 // situation described above when globalObject is null. Make sure to enter
333 // the realm of the worker's reflector if there is one. There might
334 // not be one if we're just starting to compile the script for this worker.
335 Maybe
<JSAutoRealm
> ar
;
336 if (!targetIsWorkerThread
&& mWorkerPrivate
->IsDedicatedWorker() &&
337 mWorkerPrivate
->ParentEventTargetRef()->GetWrapper()) {
338 JSObject
* wrapper
= mWorkerPrivate
->ParentEventTargetRef()->GetWrapper();
340 // If we're on the parent thread and have a reflector and a globalObject,
341 // then the realms of cx, globalObject, and the worker's reflector
343 MOZ_ASSERT_IF(globalObject
,
344 js::GetNonCCWObjectRealm(wrapper
) == js::GetContextRealm(cx
));
345 MOZ_ASSERT_IF(globalObject
,
346 js::GetNonCCWObjectRealm(wrapper
) ==
347 js::GetNonCCWObjectRealm(
348 globalObject
->GetGlobalJSObjectPreserveColor()));
350 // If we're on the parent thread and have a reflector, then our
351 // JSContext had better be either in the null realm (and hence
352 // have no globalObject) or in the realm of our reflector.
353 MOZ_ASSERT(!js::GetContextRealm(cx
) ||
354 js::GetNonCCWObjectRealm(wrapper
) == js::GetContextRealm(cx
),
355 "Must either be in the null compartment or in our reflector "
358 ar
.emplace(cx
, wrapper
);
361 MOZ_ASSERT(!jsapi
->HasException());
362 result
= WorkerRun(cx
, mWorkerPrivate
);
363 jsapi
->ReportException();
365 // We can't even assert that this didn't create our global, since in the case
366 // of CompileScriptRunnable it _does_.
368 // It would be nice to avoid passing a JSContext to PostRun, but in the case
369 // of ScriptExecutorRunnable we need to know the current compartment on the
370 // JSContext (the one we set up based on the global returned from PreRun) so
371 // that we can sanely do exception reporting. In particular, we want to make
372 // sure that we do our JS_SetPendingException while still in that compartment,
373 // because otherwise we might end up trying to create a cross-compartment
374 // wrapper when we try to move the JS exception from our runnable's
375 // ErrorResult to the JSContext, and that's not desirable in this case.
377 // We _could_ skip passing a JSContext here and then in
378 // ScriptExecutorRunnable::PostRun end up grabbing it from the WorkerPrivate
379 // and looking at its current compartment. But that seems like slightly weird
380 // action-at-a-distance...
382 // In any case, we do NOT try to change the compartment on the JSContext at
383 // this point; in the one case in which we could do that
384 // (CompileScriptRunnable) it actually doesn't matter which compartment we're
386 PostRun(cx
, mWorkerPrivate
, result
);
387 MOZ_ASSERT(!jsapi
->HasException());
389 return result
? NS_OK
: NS_ERROR_FAILURE
;
392 nsresult
WorkerRunnable::Cancel() {
393 LOG(("WorkerRunnable::Cancel [%p]", this));
397 void WorkerDebuggerRunnable::PostDispatch(WorkerPrivate
* aWorkerPrivate
,
398 bool aDispatchResult
) {}
400 WorkerSyncRunnable::WorkerSyncRunnable(WorkerPrivate
* aWorkerPrivate
,
401 nsIEventTarget
* aSyncLoopTarget
,
403 : WorkerRunnable(aWorkerPrivate
, aName
, WorkerThread
),
404 mSyncLoopTarget(aSyncLoopTarget
) {
406 if (mSyncLoopTarget
) {
407 mWorkerPrivate
->AssertValidSyncLoop(mSyncLoopTarget
);
412 WorkerSyncRunnable::WorkerSyncRunnable(
413 WorkerPrivate
* aWorkerPrivate
, nsCOMPtr
<nsIEventTarget
>&& aSyncLoopTarget
,
415 : WorkerRunnable(aWorkerPrivate
, aName
, WorkerThread
),
416 mSyncLoopTarget(std::move(aSyncLoopTarget
)) {
418 if (mSyncLoopTarget
) {
419 mWorkerPrivate
->AssertValidSyncLoop(mSyncLoopTarget
);
424 WorkerSyncRunnable::~WorkerSyncRunnable() = default;
426 bool WorkerSyncRunnable::DispatchInternal() {
427 if (mSyncLoopTarget
) {
428 RefPtr
<WorkerSyncRunnable
> runnable(this);
430 mSyncLoopTarget
->Dispatch(runnable
.forget(), NS_DISPATCH_NORMAL
));
433 return WorkerRunnable::DispatchInternal();
436 void MainThreadWorkerSyncRunnable::PostDispatch(WorkerPrivate
* aWorkerPrivate
,
437 bool aDispatchResult
) {}
439 MainThreadStopSyncLoopRunnable::MainThreadStopSyncLoopRunnable(
440 WorkerPrivate
* aWorkerPrivate
, nsCOMPtr
<nsIEventTarget
>&& aSyncLoopTarget
,
442 : WorkerSyncRunnable(aWorkerPrivate
, std::move(aSyncLoopTarget
)),
444 LOG(("MainThreadStopSyncLoopRunnable::MainThreadStopSyncLoopRunnable [%p]",
447 AssertIsOnMainThread();
449 mWorkerPrivate
->AssertValidSyncLoop(mSyncLoopTarget
);
453 nsresult
MainThreadStopSyncLoopRunnable::Cancel() {
454 LOG(("MainThreadStopSyncLoopRunnable::Cancel [%p]", this));
456 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv
), "Run() failed");
461 bool MainThreadStopSyncLoopRunnable::WorkerRun(JSContext
* aCx
,
462 WorkerPrivate
* aWorkerPrivate
) {
463 aWorkerPrivate
->AssertIsOnWorkerThread();
464 MOZ_ASSERT(mSyncLoopTarget
);
466 nsCOMPtr
<nsIEventTarget
> syncLoopTarget
;
467 mSyncLoopTarget
.swap(syncLoopTarget
);
469 aWorkerPrivate
->StopSyncLoop(syncLoopTarget
, mResult
);
473 bool MainThreadStopSyncLoopRunnable::DispatchInternal() {
474 MOZ_ASSERT(mSyncLoopTarget
);
476 RefPtr
<MainThreadStopSyncLoopRunnable
> runnable(this);
478 mSyncLoopTarget
->Dispatch(runnable
.forget(), NS_DISPATCH_NORMAL
));
481 void MainThreadStopSyncLoopRunnable::PostDispatch(WorkerPrivate
* aWorkerPrivate
,
482 bool aDispatchResult
) {}
485 WorkerControlRunnable::WorkerControlRunnable(WorkerPrivate
* aWorkerPrivate
,
486 const char* aName
, Target aTarget
)
487 : WorkerRunnable(aWorkerPrivate
, aName
, aTarget
) {
488 MOZ_ASSERT(aWorkerPrivate
);
492 nsresult
WorkerControlRunnable::Cancel() {
493 LOG(("WorkerControlRunnable::Cancel [%p]", this));
494 if (NS_FAILED(Run())) {
495 NS_WARNING("WorkerControlRunnable::Run() failed.");
501 bool WorkerControlRunnable::DispatchInternal() {
502 RefPtr
<WorkerControlRunnable
> runnable(this);
504 if (mTarget
== WorkerThread
) {
506 mWorkerPrivate
->DispatchControlRunnable(runnable
.forget()));
509 if (WorkerPrivate
* parent
= mWorkerPrivate
->GetParent()) {
510 return NS_SUCCEEDED(parent
->DispatchControlRunnable(runnable
.forget()));
513 return NS_SUCCEEDED(mWorkerPrivate
->DispatchToMainThread(runnable
.forget()));
516 WorkerMainThreadRunnable::WorkerMainThreadRunnable(
517 WorkerPrivate
* aWorkerPrivate
, const nsACString
& aTelemetryKey
)
518 : mozilla::Runnable("dom::WorkerMainThreadRunnable"),
519 mWorkerPrivate(aWorkerPrivate
),
520 mTelemetryKey(aTelemetryKey
) {
521 mWorkerPrivate
->AssertIsOnWorkerThread();
524 WorkerMainThreadRunnable::~WorkerMainThreadRunnable() = default;
526 void WorkerMainThreadRunnable::Dispatch(WorkerStatus aFailStatus
,
527 mozilla::ErrorResult
& aRv
) {
528 mWorkerPrivate
->AssertIsOnWorkerThread();
530 TimeStamp startTime
= TimeStamp::NowLoRes();
532 AutoSyncLoopHolder
syncLoop(mWorkerPrivate
, aFailStatus
);
534 mSyncLoopTarget
= syncLoop
.GetSerialEventTarget();
535 if (!mSyncLoopTarget
) {
536 // SyncLoop creation can fail if the worker is shutting down.
537 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
541 DebugOnly
<nsresult
> rv
= mWorkerPrivate
->DispatchToMainThread(this);
544 "Should only fail after xpcom-shutdown-threads and we're gone by then");
546 bool success
= NS_SUCCEEDED(syncLoop
.Run());
548 Telemetry::Accumulate(
549 Telemetry::SYNC_WORKER_OPERATION
, mTelemetryKey
,
550 static_cast<uint32_t>(
551 (TimeStamp::NowLoRes() - startTime
).ToMilliseconds()));
553 Unused
<< startTime
; // Shut the compiler up.
556 aRv
.ThrowUncatchableException();
561 WorkerMainThreadRunnable::Run() {
562 AssertIsOnMainThread();
564 // This shouldn't be necessary once we're better about making sure no workers
565 // are created during shutdown in earlier phases.
566 if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownThreads
)) {
567 return NS_ERROR_ILLEGAL_DURING_SHUTDOWN
;
570 bool runResult
= MainThreadRun();
572 RefPtr
<MainThreadStopSyncLoopRunnable
> response
=
573 new MainThreadStopSyncLoopRunnable(mWorkerPrivate
,
574 std::move(mSyncLoopTarget
),
575 runResult
? NS_OK
: NS_ERROR_FAILURE
);
577 MOZ_ALWAYS_TRUE(response
->Dispatch());
582 bool WorkerSameThreadRunnable::PreDispatch(WorkerPrivate
* aWorkerPrivate
) {
583 aWorkerPrivate
->AssertIsOnWorkerThread();
587 void WorkerSameThreadRunnable::PostDispatch(WorkerPrivate
* aWorkerPrivate
,
588 bool aDispatchResult
) {
589 aWorkerPrivate
->AssertIsOnWorkerThread();
592 WorkerProxyToMainThreadRunnable::WorkerProxyToMainThreadRunnable()
593 : mozilla::Runnable("dom::WorkerProxyToMainThreadRunnable") {}
595 WorkerProxyToMainThreadRunnable::~WorkerProxyToMainThreadRunnable() = default;
597 bool WorkerProxyToMainThreadRunnable::Dispatch(WorkerPrivate
* aWorkerPrivate
) {
598 MOZ_ASSERT(aWorkerPrivate
);
599 aWorkerPrivate
->AssertIsOnWorkerThread();
601 RefPtr
<StrongWorkerRef
> workerRef
= StrongWorkerRef::Create(
602 aWorkerPrivate
, "WorkerProxyToMainThreadRunnable");
603 if (NS_WARN_IF(!workerRef
)) {
604 RunBackOnWorkerThreadForCleanup(aWorkerPrivate
);
608 MOZ_ASSERT(!mWorkerRef
);
609 mWorkerRef
= new ThreadSafeWorkerRef(workerRef
);
612 ? NS_WARN_IF(NS_FAILED(
613 aWorkerPrivate
->DispatchToMainThreadForMessaging(this)))
614 : NS_WARN_IF(NS_FAILED(aWorkerPrivate
->DispatchToMainThread(this)))) {
616 RunBackOnWorkerThreadForCleanup(aWorkerPrivate
);
624 WorkerProxyToMainThreadRunnable::Run() {
625 AssertIsOnMainThread();
626 RunOnMainThread(mWorkerRef
->Private());
627 PostDispatchOnMainThread();
631 void WorkerProxyToMainThreadRunnable::PostDispatchOnMainThread() {
632 class ReleaseRunnable final
: public MainThreadWorkerControlRunnable
{
633 RefPtr
<WorkerProxyToMainThreadRunnable
> mRunnable
;
636 ReleaseRunnable(WorkerPrivate
* aWorkerPrivate
,
637 WorkerProxyToMainThreadRunnable
* aRunnable
)
638 : MainThreadWorkerControlRunnable(aWorkerPrivate
),
639 mRunnable(aRunnable
) {
640 MOZ_ASSERT(aRunnable
);
643 virtual nsresult
Cancel() override
{
644 Unused
<< WorkerRun(nullptr, mWorkerPrivate
);
648 virtual bool WorkerRun(JSContext
* aCx
,
649 WorkerPrivate
* aWorkerPrivate
) override
{
650 MOZ_ASSERT(aWorkerPrivate
);
651 aWorkerPrivate
->AssertIsOnWorkerThread();
654 mRunnable
->RunBackOnWorkerThreadForCleanup(aWorkerPrivate
);
656 // Let's release the worker thread.
657 mRunnable
->ReleaseWorker();
665 ~ReleaseRunnable() = default;
668 RefPtr
<WorkerControlRunnable
> runnable
=
669 new ReleaseRunnable(mWorkerRef
->Private(), this);
670 Unused
<< NS_WARN_IF(!runnable
->Dispatch());
673 void WorkerProxyToMainThreadRunnable::ReleaseWorker() { mWorkerRef
= nullptr; }
675 bool WorkerDebuggeeRunnable::PreDispatch(WorkerPrivate
* aWorkerPrivate
) {
676 if (mTarget
== ParentThread
) {
677 RefPtr
<StrongWorkerRef
> strongRef
= StrongWorkerRef::Create(
678 aWorkerPrivate
, "WorkerDebuggeeRunnable::mSender");
683 mSender
= new ThreadSafeWorkerRef(strongRef
);
686 return WorkerRunnable::PreDispatch(aWorkerPrivate
);
689 } // namespace mozilla::dom