зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1435196 - Move the webidl binding interfaces out of WorkerPrivate - part 1 - WebIDL bindings, r=bkelly
This commit is contained in:
Родитель
6e437ccf06
Коммит
f6957bfded
|
@ -144,11 +144,6 @@ DOMInterfaces = {
|
|||
'concrete': False
|
||||
},
|
||||
|
||||
'ChromeWorker': {
|
||||
'headerFile': 'mozilla/dom/WorkerPrivate.h',
|
||||
'nativeType': 'mozilla::dom::ChromeWorkerPrivate',
|
||||
},
|
||||
|
||||
'console': {
|
||||
'nativeType': 'mozilla::dom::Console',
|
||||
},
|
||||
|
@ -1351,11 +1346,6 @@ DOMInterfaces = {
|
|||
'nativeType': 'nsWindowRoot'
|
||||
},
|
||||
|
||||
'Worker': {
|
||||
'headerFile': 'mozilla/dom/WorkerPrivate.h',
|
||||
'nativeType': 'mozilla::dom::WorkerPrivate',
|
||||
},
|
||||
|
||||
'WorkerDebuggerGlobalScope': {
|
||||
'headerFile': 'mozilla/dom/WorkerScope.h',
|
||||
'implicitJSContext': [
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html
|
||||
* https://html.spec.whatwg.org/multipage/workers.html
|
||||
*
|
||||
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera
|
||||
* Software ASA.
|
||||
|
@ -33,7 +33,7 @@ dictionary WorkerOptions {
|
|||
};
|
||||
|
||||
[Constructor(USVString scriptURL),
|
||||
Func="mozilla::dom::ChromeWorkerPrivate::WorkerAvailable",
|
||||
Func="mozilla::dom::ChromeWorker::WorkerAvailable",
|
||||
Exposed=(Window,DedicatedWorker,SharedWorker,System)]
|
||||
interface ChromeWorker : Worker {
|
||||
};
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ChromeWorker.h"
|
||||
|
||||
#include "mozilla/dom/WorkerBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/* static */ already_AddRefed<ChromeWorker>
|
||||
ChromeWorker::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aScriptURL,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
|
||||
RefPtr<WorkerPrivate> workerPrivate =
|
||||
WorkerPrivate::Constructor(cx, aScriptURL, true /* aIsChromeWorker */,
|
||||
WorkerTypeDedicated, EmptyString(),
|
||||
VoidCString(), nullptr /*aLoadInfo */, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> globalObject =
|
||||
do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
RefPtr<ChromeWorker> worker =
|
||||
new ChromeWorker(globalObject, workerPrivate.forget());
|
||||
return worker.forget();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ChromeWorker::WorkerAvailable(JSContext* aCx, JSObject* /* unused */)
|
||||
{
|
||||
// Chrome is always allowed to use workers, and content is never
|
||||
// allowed to use ChromeWorker, so all we have to check is the
|
||||
// caller. However, chrome workers apparently might not have a
|
||||
// system principal, so we have to check for them manually.
|
||||
if (NS_IsMainThread()) {
|
||||
return nsContentUtils::IsSystemCaller(aCx);
|
||||
}
|
||||
|
||||
return GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
|
||||
}
|
||||
|
||||
ChromeWorker::ChromeWorker(nsIGlobalObject* aGlobalObject,
|
||||
already_AddRefed<WorkerPrivate> aWorkerPrivate)
|
||||
: Worker(aGlobalObject, Move(aWorkerPrivate))
|
||||
{}
|
||||
|
||||
ChromeWorker::~ChromeWorker() = default;
|
||||
|
||||
JSObject*
|
||||
ChromeWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
JS::Rooted<JSObject*> wrapper(aCx,
|
||||
ChromeWorkerBinding::Wrap(aCx, this, aGivenProto));
|
||||
if (wrapper) {
|
||||
// Most DOM objects don't assume they have a reflector. If they don't have
|
||||
// one and need one, they create it. But in workers code, we assume that the
|
||||
// reflector is always present. In order to guarantee that it's always
|
||||
// present, we have to preserve it. Otherwise the GC will happily collect it
|
||||
// as needed.
|
||||
MOZ_ALWAYS_TRUE(TryPreserveWrapper(wrapper));
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ChromeWorker_h
|
||||
#define mozilla_dom_ChromeWorker_h
|
||||
|
||||
#include "mozilla/dom/Worker.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ChromeWorker final : public Worker
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<ChromeWorker>
|
||||
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static bool
|
||||
WorkerAvailable(JSContext* aCx, JSObject* /* unused */);
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
private:
|
||||
ChromeWorker(nsIGlobalObject* aGlobalObject,
|
||||
already_AddRefed<WorkerPrivate> aWorkerPrivate);
|
||||
~ChromeWorker();
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif /* mozilla_dom_ChromeWorker_h */
|
|
@ -126,7 +126,8 @@ MessageEventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
|
||||
aWorkerPrivate->AssertInnerWindowIsCorrect();
|
||||
|
||||
return DispatchDOMEvent(aCx, aWorkerPrivate, aWorkerPrivate,
|
||||
return DispatchDOMEvent(aCx, aWorkerPrivate,
|
||||
aWorkerPrivate->ParentEventTargetRef(),
|
||||
!aWorkerPrivate->GetParent());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Worker.h"
|
||||
|
||||
#include "MessageEventRunnable.h"
|
||||
#include "mozilla/dom/WorkerBinding.h"
|
||||
#include "mozilla/TimelineConsumers.h"
|
||||
#include "mozilla/WorkerTimelineMarker.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/* static */ already_AddRefed<Worker>
|
||||
Worker::Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
|
||||
const WorkerOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
|
||||
RefPtr<WorkerPrivate> workerPrivate =
|
||||
WorkerPrivate::Constructor(cx, aScriptURL, false /* aIsChromeWorker */,
|
||||
WorkerTypeDedicated, aOptions.mName,
|
||||
VoidCString(), nullptr /*aLoadInfo */, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> globalObject =
|
||||
do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
RefPtr<Worker> worker = new Worker(globalObject, workerPrivate.forget());
|
||||
return worker.forget();
|
||||
}
|
||||
|
||||
Worker::Worker(nsIGlobalObject* aGlobalObject,
|
||||
already_AddRefed<WorkerPrivate> aWorkerPrivate)
|
||||
: DOMEventTargetHelper(aGlobalObject)
|
||||
, mWorkerPrivate(Move(aWorkerPrivate))
|
||||
{
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
mWorkerPrivate->SetParentEventTargetRef(this);
|
||||
}
|
||||
|
||||
Worker::~Worker()
|
||||
{
|
||||
Terminate();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Worker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
JS::Rooted<JSObject*> wrapper(aCx,
|
||||
WorkerBinding::Wrap(aCx, this, aGivenProto));
|
||||
if (wrapper) {
|
||||
// Most DOM objects don't assume they have a reflector. If they don't have
|
||||
// one and need one, they create it. But in workers code, we assume that the
|
||||
// reflector is always present. In order to guarantee that it's always
|
||||
// present, we have to preserve it. Otherwise the GC will happily collect it
|
||||
// as needed.
|
||||
MOZ_ALWAYS_TRUE(TryPreserveWrapper(wrapper));
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
void
|
||||
Worker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Worker);
|
||||
|
||||
if (!mWorkerPrivate ||
|
||||
mWorkerPrivate->ParentStatusProtected() > Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
|
||||
aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
|
||||
&transferable);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<MessageEventRunnable> runnable =
|
||||
new MessageEventRunnable(mWorkerPrivate,
|
||||
WorkerRunnable::WorkerThreadModifyBusyCount);
|
||||
|
||||
UniquePtr<AbstractTimelineMarker> start;
|
||||
UniquePtr<AbstractTimelineMarker> end;
|
||||
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
|
||||
bool isTimelineRecording = timelines && !timelines->IsEmpty();
|
||||
|
||||
if (isTimelineRecording) {
|
||||
start = MakeUnique<WorkerTimelineMarker>(NS_IsMainThread()
|
||||
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
|
||||
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
|
||||
MarkerTracingType::START);
|
||||
}
|
||||
|
||||
runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), aRv);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
end = MakeUnique<WorkerTimelineMarker>(NS_IsMainThread()
|
||||
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
|
||||
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
|
||||
MarkerTracingType::END);
|
||||
timelines->AddMarkerForAllObservedDocShells(start);
|
||||
timelines->AddMarkerForAllObservedDocShells(end);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!runnable->Dispatch()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Worker::Terminate()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Worker);
|
||||
|
||||
if (mWorkerPrivate) {
|
||||
mWorkerPrivate->Terminate();
|
||||
mWorkerPrivate = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Worker)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Worker, DOMEventTargetHelper)
|
||||
if (tmp->mWorkerPrivate) {
|
||||
tmp->mWorkerPrivate->Traverse(cb);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Worker, DOMEventTargetHelper)
|
||||
tmp->Terminate();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(Worker, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Worker)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(Worker, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(Worker, DOMEventTargetHelper)
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_Worker_h
|
||||
#define mozilla_dom_Worker_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct WorkerOptions;
|
||||
class WorkerPrivate;
|
||||
|
||||
class Worker : public DOMEventTargetHelper
|
||||
, public SupportsWeakPtr<Worker>
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(Worker,
|
||||
DOMEventTargetHelper)
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Worker)
|
||||
|
||||
static already_AddRefed<Worker>
|
||||
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
|
||||
const WorkerOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Terminate();
|
||||
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
IMPL_EVENT_HANDLER(message)
|
||||
IMPL_EVENT_HANDLER(messageerror)
|
||||
|
||||
protected:
|
||||
Worker(nsIGlobalObject* aGlobalObject,
|
||||
already_AddRefed<WorkerPrivate> aWorkerPrivate);
|
||||
~Worker();
|
||||
|
||||
RefPtr<WorkerPrivate> mWorkerPrivate;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif /* mozilla_dom_Worker_h */
|
|
@ -35,7 +35,7 @@ public:
|
|||
// (if any).
|
||||
static void
|
||||
ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aFireAtScope, WorkerPrivate* aTarget,
|
||||
bool aFireAtScope, DOMEventTargetHelper* aTarget,
|
||||
const WorkerErrorReport& aReport, uint64_t aInnerWindowId,
|
||||
JS::Handle<JS::Value> aException = JS::NullHandleValue)
|
||||
{
|
||||
|
@ -177,8 +177,6 @@ private:
|
|||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
JS::Rooted<JSObject*> target(aCx, aWorkerPrivate->GetWrapper());
|
||||
|
||||
uint64_t innerWindowId;
|
||||
bool fireAtScope = true;
|
||||
|
||||
|
@ -236,8 +234,9 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mReport,
|
||||
innerWindowId);
|
||||
ReportError(aCx, parent, fireAtScope,
|
||||
aWorkerPrivate->ParentEventTargetRef(),
|
||||
mReport, innerWindowId);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using namespace workerinternals;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WorkerNavigator, mStorageManager,
|
||||
mConnection);
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ private:
|
|||
|
||||
runtime->UnregisterWorker(mFinishedWorker);
|
||||
|
||||
mFinishedWorker->ClearSelfRef();
|
||||
mFinishedWorker->ClearSelfAndParentEventTargetRef();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -287,7 +287,7 @@ private:
|
|||
NS_WARNING("Failed to dispatch, going to leak!");
|
||||
}
|
||||
|
||||
mFinishedWorker->ClearSelfRef();
|
||||
mFinishedWorker->ClearSelfAndParentEventTargetRef();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
@ -384,13 +384,15 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::dom::EventTarget> parentEventTarget =
|
||||
aWorkerPrivate->ParentEventTargetRef();
|
||||
RefPtr<Event> event =
|
||||
Event::Constructor(aWorkerPrivate, NS_LITERAL_STRING("error"),
|
||||
Event::Constructor(parentEventTarget, NS_LITERAL_STRING("error"),
|
||||
EventInit());
|
||||
event->SetTrusted(true);
|
||||
|
||||
bool dummy;
|
||||
aWorkerPrivate->DispatchEvent(event, &dummy);
|
||||
parentEventTarget->DispatchEvent(event, &dummy);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -1546,14 +1548,6 @@ WorkerPrivateParent<Derived>::SetReferrerPolicyFromHeaderValue(
|
|||
SetReferrerPolicy(policy);
|
||||
}
|
||||
|
||||
|
||||
// Can't use NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerPrivateParent) because of the
|
||||
// templates.
|
||||
template <class Derived>
|
||||
typename WorkerPrivateParent<Derived>::cycleCollection
|
||||
WorkerPrivateParent<Derived>::_cycleCollectorGlobal =
|
||||
WorkerPrivateParent<Derived>::cycleCollection();
|
||||
|
||||
template <class Derived>
|
||||
WorkerPrivateParent<Derived>::WorkerPrivateParent(
|
||||
WorkerPrivate* aParent,
|
||||
|
@ -1576,11 +1570,6 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
|
|||
{
|
||||
MOZ_ASSERT_IF(!IsDedicatedWorker(), NS_IsMainThread());
|
||||
|
||||
if (aLoadInfo.mWindow) {
|
||||
AssertIsOnMainThread();
|
||||
BindToOwner(aLoadInfo.mWindow);
|
||||
}
|
||||
|
||||
mLoadInfo.StealFrom(aLoadInfo);
|
||||
|
||||
if (aParent) {
|
||||
|
@ -1644,23 +1633,23 @@ WorkerPrivateParent<Derived>::~WorkerPrivateParent()
|
|||
}
|
||||
|
||||
template <class Derived>
|
||||
JSObject*
|
||||
WorkerPrivateParent<Derived>::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
void
|
||||
WorkerPrivateParent<Derived>::Traverse(nsCycleCollectionTraversalCallback& aCb)
|
||||
{
|
||||
MOZ_ASSERT(!IsSharedWorker(),
|
||||
"We should never wrap a WorkerPrivate for a SharedWorker");
|
||||
|
||||
AssertIsOnParentThread();
|
||||
|
||||
// XXXkhuey this should not need to be rooted, the analysis is dumb.
|
||||
// See bug 980181.
|
||||
JS::Rooted<JSObject*> wrapper(aCx,
|
||||
WorkerBinding::Wrap(aCx, ParentAsWorkerPrivate(), aGivenProto));
|
||||
if (wrapper) {
|
||||
MOZ_ALWAYS_TRUE(TryPreserveWrapper(wrapper));
|
||||
// The WorkerPrivate::mParentEventTargetRef has a reference to the exposed
|
||||
// Worker object, which is really held by the worker thread. We traverse this
|
||||
// reference if and only if our busy count is zero and we have not released
|
||||
// the main thread reference. We do not unlink it. This allows the CC to
|
||||
// break cycles involving the Worker and begin shutting it down (which does
|
||||
// happen in unlink) but ensures that the WorkerPrivate won't be deleted
|
||||
// before we're done shutting down the thread.
|
||||
if (!mBusyCount && !mMainThreadObjectsForgotten) {
|
||||
nsCycleCollectionTraversalCallback& cb = aCb;
|
||||
WorkerPrivateParent<Derived>* tmp = this;
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentEventTargetRef);
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
|
@ -2145,76 +2134,6 @@ WorkerPrivateParent<Derived>::ProxyReleaseMainThreadObjects()
|
|||
return result;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessageInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mParentStatus > Running) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
|
||||
|
||||
aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
|
||||
&transferable);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<MessageEventRunnable> runnable =
|
||||
new MessageEventRunnable(ParentAsWorkerPrivate(),
|
||||
WorkerRunnable::WorkerThreadModifyBusyCount);
|
||||
|
||||
UniquePtr<AbstractTimelineMarker> start;
|
||||
UniquePtr<AbstractTimelineMarker> end;
|
||||
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
|
||||
bool isTimelineRecording = timelines && !timelines->IsEmpty();
|
||||
|
||||
if (isTimelineRecording) {
|
||||
start = MakeUnique<WorkerTimelineMarker>(NS_IsMainThread()
|
||||
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
|
||||
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
|
||||
MarkerTracingType::START);
|
||||
}
|
||||
|
||||
runnable->Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), aRv);
|
||||
|
||||
if (isTimelineRecording) {
|
||||
end = MakeUnique<WorkerTimelineMarker>(NS_IsMainThread()
|
||||
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
|
||||
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
|
||||
MarkerTracingType::END);
|
||||
timelines->AddMarkerForAllObservedDocShells(start);
|
||||
timelines->AddMarkerForAllObservedDocShells(end);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!runnable->Dispatch()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessage(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::UpdateContextOptions(
|
||||
|
@ -2780,48 +2699,6 @@ WorkerPrivateParent<Derived>::FlushReportsToSharedWorkers(
|
|||
aReporter->ClearConsoleReports();
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
NS_IMPL_ADDREF_INHERITED(WorkerPrivateParent<Derived>, DOMEventTargetHelper)
|
||||
|
||||
template <class Derived>
|
||||
NS_IMPL_RELEASE_INHERITED(WorkerPrivateParent<Derived>, DOMEventTargetHelper)
|
||||
|
||||
template <class Derived>
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerPrivateParent<Derived>)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
template <class Derived>
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerPrivateParent<Derived>,
|
||||
DOMEventTargetHelper)
|
||||
tmp->AssertIsOnParentThread();
|
||||
|
||||
// The WorkerPrivate::mSelfRef has a reference to itself, which is really
|
||||
// held by the worker thread. We traverse this reference if and only if our
|
||||
// busy count is zero and we have not released the main thread reference.
|
||||
// We do not unlink it. This allows the CC to break cycles involving the
|
||||
// WorkerPrivate and begin shutting it down (which does happen in unlink) but
|
||||
// ensures that the WorkerPrivate won't be deleted before we're done shutting
|
||||
// down the thread.
|
||||
|
||||
if (!tmp->mBusyCount && !tmp->mMainThreadObjectsForgotten) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelfRef)
|
||||
}
|
||||
|
||||
// The various strong references in LoadInfo are managed manually and cannot
|
||||
// be cycle collected.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
template <class Derived>
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerPrivateParent<Derived>,
|
||||
DOMEventTargetHelper)
|
||||
tmp->Terminate();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
template <class Derived>
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerPrivateParent<Derived>,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
template <class Derived>
|
||||
|
@ -2954,58 +2831,6 @@ WorkerPrivate::~WorkerPrivate()
|
|||
mWorkerHybridEventTarget->ForgetWorkerPrivate(this);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<WorkerPrivate>
|
||||
WorkerPrivate::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aScriptURL,
|
||||
const WorkerOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return WorkerPrivate::Constructor(aGlobal, aScriptURL, false,
|
||||
WorkerTypeDedicated,
|
||||
aOptions.mName, nullptr, aRv);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<ChromeWorkerPrivate>
|
||||
ChromeWorkerPrivate::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aScriptURL,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return WorkerPrivate::Constructor(aGlobal, aScriptURL, true,
|
||||
WorkerTypeDedicated, EmptyString(),
|
||||
nullptr, aRv)
|
||||
.downcast<ChromeWorkerPrivate>();
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
ChromeWorkerPrivate::WorkerAvailable(JSContext* aCx, JSObject* /* unused */)
|
||||
{
|
||||
// Chrome is always allowed to use workers, and content is never
|
||||
// allowed to use ChromeWorker, so all we have to check is the
|
||||
// caller. However, chrome workers apparently might not have a
|
||||
// system principal, so we have to check for them manually.
|
||||
if (NS_IsMainThread()) {
|
||||
return nsContentUtils::IsSystemCaller(aCx);
|
||||
}
|
||||
|
||||
return GetWorkerPrivateFromContext(aCx)->IsChromeWorker();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<WorkerPrivate>
|
||||
WorkerPrivate::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aScriptURL,
|
||||
bool aIsChromeWorker, WorkerType aWorkerType,
|
||||
const nsAString& aWorkerName,
|
||||
WorkerLoadInfo* aLoadInfo, ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
return Constructor(cx, aScriptURL, aIsChromeWorker, aWorkerType,
|
||||
aWorkerName, VoidCString(), aLoadInfo, aRv);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<WorkerPrivate>
|
||||
WorkerPrivate::Constructor(JSContext* aCx,
|
||||
|
|
|
@ -14,15 +14,12 @@
|
|||
#include "nsIEventTarget.h"
|
||||
#include "nsTObserverArray.h"
|
||||
|
||||
#include "mozilla/dom/Worker.h"
|
||||
#include "mozilla/dom/WorkerHolder.h"
|
||||
#include "mozilla/dom/WorkerLoadInfo.h"
|
||||
#include "mozilla/dom/workerinternals/JSSettings.h"
|
||||
#include "mozilla/dom/workerinternals/Queue.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
#endif
|
||||
|
||||
class nsIConsoleReportCollector;
|
||||
class nsIThreadInternal;
|
||||
|
||||
|
@ -51,7 +48,6 @@ class WorkerDebuggerGlobalScope;
|
|||
class WorkerErrorReport;
|
||||
class WorkerEventTarget;
|
||||
class WorkerGlobalScope;
|
||||
struct WorkerOptions;
|
||||
class WorkerRunnable;
|
||||
class WorkerThread;
|
||||
|
||||
|
@ -105,7 +101,7 @@ public:
|
|||
};
|
||||
|
||||
template <class Derived>
|
||||
class WorkerPrivateParent : public DOMEventTargetHelper
|
||||
class WorkerPrivateParent
|
||||
{
|
||||
protected:
|
||||
class EventTarget;
|
||||
|
@ -184,8 +180,9 @@ private:
|
|||
|
||||
protected:
|
||||
// The worker is owned by its thread, which is represented here. This is set
|
||||
// in Construct() and emptied by WorkerFinishedRunnable, and conditionally
|
||||
// in Constructor() and emptied by WorkerFinishedRunnable, and conditionally
|
||||
// traversed by the cycle collector if the busy count is zero.
|
||||
RefPtr<Worker> mParentEventTargetRef;
|
||||
RefPtr<WorkerPrivate> mSelfRef;
|
||||
|
||||
WorkerPrivateParent(WorkerPrivate* aParent,
|
||||
|
@ -195,7 +192,7 @@ protected:
|
|||
const nsACString& aServiceWorkerScope,
|
||||
WorkerLoadInfo& aLoadInfo);
|
||||
|
||||
~WorkerPrivateParent();
|
||||
virtual ~WorkerPrivateParent();
|
||||
|
||||
private:
|
||||
Derived*
|
||||
|
@ -213,21 +210,14 @@ private:
|
|||
return NotifyPrivate(Terminating);
|
||||
}
|
||||
|
||||
void
|
||||
PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult
|
||||
DispatchPrivate(already_AddRefed<WorkerRunnable> aRunnable, nsIEventTarget* aSyncLoopTarget);
|
||||
|
||||
public:
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
NS_INLINE_DECL_REFCOUNTING(WorkerPrivateParent)
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerPrivateParent,
|
||||
DOMEventTargetHelper)
|
||||
void
|
||||
Traverse(nsCycleCollectionTraversalCallback& aCb);
|
||||
|
||||
void
|
||||
EnableDebugger();
|
||||
|
@ -236,10 +226,11 @@ public:
|
|||
DisableDebugger();
|
||||
|
||||
void
|
||||
ClearSelfRef()
|
||||
ClearSelfAndParentEventTargetRef()
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
MOZ_ASSERT(mSelfRef);
|
||||
mParentEventTargetRef = nullptr;
|
||||
mSelfRef = nullptr;
|
||||
}
|
||||
|
||||
|
@ -318,11 +309,6 @@ public:
|
|||
bool
|
||||
ProxyReleaseMainThreadObjects();
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
UpdateContextOptions(const JS::ContextOptions& aContextOptions);
|
||||
|
||||
|
@ -394,7 +380,15 @@ public:
|
|||
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mParentStatus < Terminating;
|
||||
}
|
||||
}
|
||||
|
||||
WorkerStatus
|
||||
ParentStatusProtected()
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
MutexAutoLock lock(mMutex);
|
||||
return mParentStatus;
|
||||
}
|
||||
|
||||
WorkerStatus
|
||||
ParentStatus() const
|
||||
|
@ -829,10 +823,6 @@ public:
|
|||
void
|
||||
FlushReportsToSharedWorkers(nsIConsoleReportCollector* aReporter);
|
||||
|
||||
IMPL_EVENT_HANDLER(message)
|
||||
IMPL_EVENT_HANDLER(messageerror)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
|
||||
// Check whether this worker is a secure context. For use from the parent
|
||||
// thread only; the canonical "is secure context" boolean is stored on the
|
||||
// compartment of the worker global. The only reason we don't
|
||||
|
@ -968,17 +958,6 @@ protected:
|
|||
~WorkerPrivate();
|
||||
|
||||
public:
|
||||
static already_AddRefed<WorkerPrivate>
|
||||
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
|
||||
const WorkerOptions& aOptions,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<WorkerPrivate>
|
||||
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
|
||||
bool aIsChromeWorker, WorkerType aWorkerType,
|
||||
const nsAString& aWorkerName,
|
||||
WorkerLoadInfo* aLoadInfo, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<WorkerPrivate>
|
||||
Constructor(JSContext* aCx, const nsAString& aScriptURL, bool aIsChromeWorker,
|
||||
WorkerType aWorkerType, const nsAString& aWorkerName,
|
||||
|
@ -1389,6 +1368,21 @@ public:
|
|||
PerformanceStorage*
|
||||
GetPerformanceStorage();
|
||||
|
||||
Worker*
|
||||
ParentEventTargetRef() const
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mParentEventTargetRef);
|
||||
return mParentEventTargetRef;
|
||||
}
|
||||
|
||||
void
|
||||
SetParentEventTargetRef(Worker* aParentEventTargetRef)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aParentEventTargetRef);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mParentEventTargetRef);
|
||||
mParentEventTargetRef = aParentEventTargetRef;
|
||||
}
|
||||
|
||||
private:
|
||||
WorkerPrivate(WorkerPrivate* aParent,
|
||||
const nsAString& aScriptURL, bool aIsChromeWorker,
|
||||
|
@ -1491,25 +1485,6 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
// This class is only used to trick the DOM bindings. We never create
|
||||
// instances of it, and static_casting to it is fine since it doesn't add
|
||||
// anything to WorkerPrivate.
|
||||
class ChromeWorkerPrivate : public WorkerPrivate
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<ChromeWorkerPrivate>
|
||||
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
|
||||
ErrorResult& rv);
|
||||
|
||||
static bool
|
||||
WorkerAvailable(JSContext* aCx, JSObject* /* unused */);
|
||||
|
||||
private:
|
||||
ChromeWorkerPrivate() = delete;
|
||||
ChromeWorkerPrivate(const ChromeWorkerPrivate& aRHS) = delete;
|
||||
ChromeWorkerPrivate& operator =(const ChromeWorkerPrivate& aRHS) = delete;
|
||||
};
|
||||
|
||||
class AutoSyncLoopHolder
|
||||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
|
|
|
@ -330,7 +330,8 @@ WorkerRunnable::Run()
|
|||
cx = jsapi->cx();
|
||||
}
|
||||
|
||||
// Note that we can't assert anything about mWorkerPrivate->GetWrapper()
|
||||
// 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).
|
||||
|
||||
|
@ -348,27 +349,31 @@ WorkerRunnable::Run()
|
|||
// the compartment 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<JSAutoCompartment> ac;
|
||||
if (!targetIsWorkerThread && mWorkerPrivate->GetWrapper()) {
|
||||
if (!targetIsWorkerThread &&
|
||||
mWorkerPrivate->IsDedicatedWorker() &&
|
||||
mWorkerPrivate->ParentEventTargetRef()->GetWrapper()) {
|
||||
JSObject* wrapper = mWorkerPrivate->ParentEventTargetRef()->GetWrapper();
|
||||
|
||||
// If we're on the parent thread and have a reflector and a globalObject,
|
||||
// then the compartments of cx, globalObject, and the worker's reflector
|
||||
// should all match.
|
||||
MOZ_ASSERT_IF(globalObject,
|
||||
js::GetObjectCompartment(mWorkerPrivate->GetWrapper()) ==
|
||||
js::GetObjectCompartment(wrapper) ==
|
||||
js::GetContextCompartment(cx));
|
||||
MOZ_ASSERT_IF(globalObject,
|
||||
js::GetObjectCompartment(mWorkerPrivate->GetWrapper()) ==
|
||||
js::GetObjectCompartment(wrapper) ==
|
||||
js::GetObjectCompartment(globalObject->GetGlobalJSObject()));
|
||||
|
||||
// If we're on the parent thread and have a reflector, then our
|
||||
// JSContext had better be either in the null compartment (and hence
|
||||
// have no globalObject) or in the compartment of our reflector.
|
||||
MOZ_ASSERT(!js::GetContextCompartment(cx) ||
|
||||
js::GetObjectCompartment(mWorkerPrivate->GetWrapper()) ==
|
||||
js::GetObjectCompartment(wrapper) ==
|
||||
js::GetContextCompartment(cx),
|
||||
"Must either be in the null compartment or in our reflector "
|
||||
"compartment");
|
||||
|
||||
ac.emplace(cx, mWorkerPrivate->GetWrapper());
|
||||
ac.emplace(cx, wrapper);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!jsapi->HasException());
|
||||
|
|
|
@ -9,7 +9,9 @@ with Files("**"):
|
|||
|
||||
# Public stuff.
|
||||
EXPORTS.mozilla.dom += [
|
||||
'ChromeWorker.h',
|
||||
'SharedWorker.h',
|
||||
'Worker.h',
|
||||
'WorkerCommon.h',
|
||||
'WorkerDebugger.h',
|
||||
'WorkerDebuggerManager.h',
|
||||
|
@ -38,6 +40,7 @@ XPIDL_SOURCES += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'ChromeWorker.cpp',
|
||||
'ChromeWorkerScope.cpp',
|
||||
'MessageEventRunnable.cpp',
|
||||
'Principal.cpp',
|
||||
|
@ -45,6 +48,7 @@ UNIFIED_SOURCES += [
|
|||
'RuntimeService.cpp',
|
||||
'ScriptLoader.cpp',
|
||||
'SharedWorker.cpp',
|
||||
'Worker.cpp',
|
||||
'WorkerDebugger.cpp',
|
||||
'WorkerDebuggerManager.cpp',
|
||||
'WorkerError.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче