Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / workers / WorkerEventTarget.cpp
blobcb58b4f8edd2007d6ddc13d2340c7382acf7231e
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 "WorkerEventTarget.h"
8 #include "WorkerPrivate.h"
9 #include "WorkerRunnable.h"
11 #include "mozilla/Logging.h"
12 #include "mozilla/dom/ReferrerInfo.h"
14 namespace mozilla::dom {
16 static mozilla::LazyLogModule sWorkerEventTargetLog("WorkerEventTarget");
18 #ifdef LOG
19 # undef LOG
20 #endif
21 #ifdef LOGV
22 # undef LOGV
23 #endif
24 #define LOG(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Debug, args);
25 #define LOGV(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Verbose, args);
27 namespace {
29 class WrappedControlRunnable final : public WorkerControlRunnable {
30 nsCOMPtr<nsIRunnable> mInner;
32 ~WrappedControlRunnable() = default;
34 public:
35 WrappedControlRunnable(WorkerPrivate* aWorkerPrivate,
36 nsCOMPtr<nsIRunnable>&& aInner)
37 : WorkerControlRunnable(aWorkerPrivate, "WrappedControlRunnable",
38 WorkerThread),
39 mInner(std::move(aInner)) {}
41 virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) override {
42 // Silence bad assertions, this can be dispatched from any thread.
43 return true;
46 virtual void PostDispatch(WorkerPrivate* aWorkerPrivate,
47 bool aDispatchResult) override {
48 // Silence bad assertions, this can be dispatched from any thread.
51 bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
52 mInner->Run();
53 return true;
56 nsresult Cancel() override {
57 nsCOMPtr<nsICancelableRunnable> cr = do_QueryInterface(mInner);
59 // If the inner runnable is not cancellable, then just do the normal
60 // WorkerControlRunnable thing. This will end up calling Run().
61 if (!cr) {
62 return Run();
65 // Otherwise call the inner runnable's Cancel() and treat this like
66 // a WorkerRunnable cancel. We can't call WorkerControlRunnable::Cancel()
67 // in this case since that would result in both Run() and the inner
68 // Cancel() being called.
69 return cr->Cancel();
73 } // anonymous namespace
75 NS_IMPL_ISUPPORTS(WorkerEventTarget, nsIEventTarget, nsISerialEventTarget)
77 WorkerEventTarget::WorkerEventTarget(WorkerPrivate* aWorkerPrivate,
78 Behavior aBehavior)
79 : mMutex("WorkerEventTarget"),
80 mWorkerPrivate(aWorkerPrivate),
81 mBehavior(aBehavior) {
82 LOG(("WorkerEventTarget::WorkerEventTarget [%p] aBehavior: %u", this,
83 (uint8_t)aBehavior));
84 MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate);
87 void WorkerEventTarget::ForgetWorkerPrivate(WorkerPrivate* aWorkerPrivate) {
88 LOG(("WorkerEventTarget::ForgetWorkerPrivate [%p] aWorkerPrivate: %p", this,
89 aWorkerPrivate));
90 MutexAutoLock lock(mMutex);
91 MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate || mWorkerPrivate == aWorkerPrivate);
92 mWorkerPrivate = nullptr;
95 NS_IMETHODIMP
96 WorkerEventTarget::DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags) {
97 LOGV(("WorkerEventTarget::DispatchFromScript [%p] aRunnable: %p", this,
98 aRunnable));
99 nsCOMPtr<nsIRunnable> runnable(aRunnable);
100 return Dispatch(runnable.forget(), aFlags);
103 NS_IMETHODIMP
104 WorkerEventTarget::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
105 uint32_t aFlags) {
106 nsCOMPtr<nsIRunnable> runnable(aRunnable);
107 LOGV(
108 ("WorkerEventTarget::Dispatch [%p] aRunnable: %p", this, runnable.get()));
110 MutexAutoLock lock(mMutex);
112 if (!mWorkerPrivate) {
113 return NS_ERROR_FAILURE;
116 if (mBehavior == Behavior::Hybrid) {
117 LOGV(("WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p)",
118 this, runnable.get()));
120 RefPtr<WorkerRunnable> r =
121 mWorkerPrivate->MaybeWrapAsWorkerRunnable(runnable.forget());
122 if (r->Dispatch()) {
123 return NS_OK;
125 runnable = std::move(r);
126 LOGV((
127 "WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p) fail",
128 this, runnable.get()));
131 RefPtr<WorkerControlRunnable> r =
132 new WrappedControlRunnable(mWorkerPrivate, std::move(runnable));
133 LOGV(
134 ("WorkerEventTarget::Dispatch [%p] Wrapped runnable as control "
135 "runnable(%p)",
136 this, r.get()));
137 if (!r->Dispatch()) {
138 LOGV(
139 ("WorkerEventTarget::Dispatch [%p] Dispatch as control runnable(%p) "
140 "fail",
141 this, r.get()));
142 return NS_ERROR_FAILURE;
145 return NS_OK;
148 NS_IMETHODIMP
149 WorkerEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) {
150 return NS_ERROR_NOT_IMPLEMENTED;
153 NS_IMETHODIMP
154 WorkerEventTarget::RegisterShutdownTask(nsITargetShutdownTask* aTask) {
155 NS_ENSURE_ARG(aTask);
157 MutexAutoLock lock(mMutex);
159 // If mWorkerPrivate is gone, the event target is already late during
160 // shutdown, return NS_ERROR_UNEXPECTED as documented in `nsIEventTarget.idl`.
161 if (!mWorkerPrivate) {
162 return NS_ERROR_UNEXPECTED;
165 return mWorkerPrivate->RegisterShutdownTask(aTask);
168 NS_IMETHODIMP
169 WorkerEventTarget::UnregisterShutdownTask(nsITargetShutdownTask* aTask) {
170 NS_ENSURE_ARG(aTask);
172 MutexAutoLock lock(mMutex);
174 if (!mWorkerPrivate) {
175 return NS_ERROR_UNEXPECTED;
178 return mWorkerPrivate->UnregisterShutdownTask(aTask);
181 NS_IMETHODIMP_(bool)
182 WorkerEventTarget::IsOnCurrentThreadInfallible() {
183 MutexAutoLock lock(mMutex);
185 if (!mWorkerPrivate) {
186 return false;
189 return mWorkerPrivate->IsOnCurrentThread();
192 NS_IMETHODIMP
193 WorkerEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) {
194 MOZ_ASSERT(aIsOnCurrentThread);
195 *aIsOnCurrentThread = IsOnCurrentThreadInfallible();
196 return NS_OK;
199 } // namespace mozilla::dom