Bug 1193414 - SharedWorkers thread should be kept alive also when the SharedWorker object is CCed, r=khuey

This commit is contained in:
Andrea Marchesini 2015-09-23 06:54:29 +01:00
Родитель 787b689f00
Коммит abdc1eebce
8 изменённых файлов: 93 добавлений и 68 удалений

Просмотреть файл

@ -1694,16 +1694,10 @@ RuntimeService::UnregisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
aWorkerPrivate->CreationTimeStamp());
}
if (aWorkerPrivate->IsSharedWorker()) {
if (aWorkerPrivate->IsSharedWorker() ||
aWorkerPrivate->IsServiceWorker()) {
AssertIsOnMainThread();
nsAutoTArray<nsRefPtr<SharedWorker>, 5> sharedWorkersToNotify;
aWorkerPrivate->GetAllSharedWorkers(sharedWorkersToNotify);
for (uint32_t index = 0; index < sharedWorkersToNotify.Length(); index++) {
MOZ_ASSERT(sharedWorkersToNotify[index]);
sharedWorkersToNotify[index]->NoteDeadWorker(aCx);
}
aWorkerPrivate->CloseAllSharedWorkers();
}
if (parent) {

Просмотреть файл

@ -28,19 +28,19 @@ USING_WORKERS_NAMESPACE
SharedWorker::SharedWorker(nsPIDOMWindow* aWindow,
WorkerPrivate* aWorkerPrivate,
MessagePort* aMessagePort)
: DOMEventTargetHelper(aWindow), mWorkerPrivate(aWorkerPrivate)
, mMessagePort(aMessagePort)
, mFrozen(false)
: DOMEventTargetHelper(aWindow)
, mWorkerPrivate(aWorkerPrivate)
, mMessagePort(aMessagePort)
, mFrozen(false)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(aMessagePort);
}
SharedWorker::~SharedWorker()
{
AssertIsOnMainThread();
Close();
MOZ_ASSERT(!mWorkerPrivate);
}
// static
@ -136,11 +136,7 @@ SharedWorker::Close()
if (mMessagePort) {
mMessagePort->Close();
}
if (mWorkerPrivate) {
AutoSafeJSContext cx;
NoteDeadWorker(cx);
mMessagePort = nullptr;
}
}
@ -156,16 +152,6 @@ SharedWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
mMessagePort->PostMessage(aCx, aMessage, aTransferable, aRv);
}
void
SharedWorker::NoteDeadWorker(JSContext* aCx)
{
AssertIsOnMainThread();
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->UnregisterSharedWorker(aCx, this);
mWorkerPrivate = nullptr;
}
NS_IMPL_ADDREF_INHERITED(SharedWorker, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(SharedWorker, DOMEventTargetHelper)
@ -182,7 +168,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SharedWorker,
DOMEventTargetHelper)
tmp->Close();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagePort)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrozenEvents)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

Просмотреть файл

@ -98,10 +98,6 @@ private:
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv);
// Only called by RuntimeService.
void
NoteDeadWorker(JSContext* aCx);
};
END_WORKERS_NAMESPACE

Просмотреть файл

@ -2951,31 +2951,6 @@ WorkerPrivateParent<Derived>::RegisterSharedWorker(JSContext* aCx,
return true;
}
template <class Derived>
void
WorkerPrivateParent<Derived>::UnregisterSharedWorker(
JSContext* aCx,
SharedWorker* aSharedWorker)
{
AssertIsOnMainThread();
MOZ_ASSERT(aSharedWorker);
MOZ_ASSERT(IsSharedWorker() || IsServiceWorker());
MOZ_ASSERT(mSharedWorkers.Contains(aSharedWorker));
mSharedWorkers.RemoveElement(aSharedWorker);
// If there are still SharedWorker objects attached to this worker then they
// may all be frozen and this worker would need to be frozen. Otherwise,
// if that was the last SharedWorker then it's time to cancel this worker.
if (!mSharedWorkers.IsEmpty()) {
if (!Freeze(aCx, nullptr)) {
JS_ReportPendingException(aCx);
}
} else if (!Cancel(aCx)) {
JS_ReportPendingException(aCx);
}
}
template <class Derived>
void
WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
@ -3123,19 +3098,55 @@ WorkerPrivateParent<Derived>::CloseSharedWorkersForWindow(
MOZ_ASSERT(IsSharedWorker() || IsServiceWorker());
MOZ_ASSERT(aWindow);
nsAutoTArray<nsRefPtr<SharedWorker>, 10> sharedWorkers;
bool someRemoved = false;
for (uint32_t i = 0; i < mSharedWorkers.Length(); ++i) {
for (uint32_t i = 0; i < mSharedWorkers.Length();) {
if (mSharedWorkers[i]->GetOwner() == aWindow) {
sharedWorkers.AppendElement(mSharedWorkers[i]);
mSharedWorkers[i]->Close();
mSharedWorkers.RemoveElementAt(i);
someRemoved = true;
} else {
MOZ_ASSERT(!SameCOMIdentity(mSharedWorkers[i]->GetOwner(),
aWindow));
++i;
}
}
for (uint32_t index = 0; index < sharedWorkers.Length(); index++) {
sharedWorkers[index]->Close();
if (!someRemoved) {
return;
}
// If there are still SharedWorker objects attached to this worker then they
// may all be frozen and this worker would need to be frozen. Otherwise,
// if that was the last SharedWorker then it's time to cancel this worker.
AutoSafeJSContext cx;
if (!mSharedWorkers.IsEmpty()) {
if (!Freeze(cx, nullptr)) {
JS_ReportPendingException(cx);
}
} else if (!Cancel(cx)) {
JS_ReportPendingException(cx);
}
}
template <class Derived>
void
WorkerPrivateParent<Derived>::CloseAllSharedWorkers()
{
AssertIsOnMainThread();
MOZ_ASSERT(IsSharedWorker() || IsServiceWorker());
for (uint32_t i = 0; i < mSharedWorkers.Length(); ++i) {
mSharedWorkers[i]->Close();
}
mSharedWorkers.Clear();
AutoSafeJSContext cx;
if (!Cancel(cx)) {
JS_ReportPendingException(cx);
}
}

Просмотреть файл

@ -178,7 +178,7 @@ private:
// Only touched on the parent thread (currently this is always the main
// thread as SharedWorkers are always top-level).
nsTArray<SharedWorker*> mSharedWorkers;
nsTArray<nsRefPtr<SharedWorker>> mSharedWorkers;
uint64_t mBusyCount;
Status mParentStatus;
@ -368,9 +368,6 @@ public:
RegisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker,
MessagePort* aPort);
void
UnregisterSharedWorker(JSContext* aCx, SharedWorker* aSharedWorker);
void
BroadcastErrorToSharedWorkers(JSContext* aCx,
const nsAString& aMessage,
@ -770,6 +767,9 @@ public:
void
CloseSharedWorkersForWindow(nsPIDOMWindow* aWindow);
void
CloseAllSharedWorkers();
void
UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup);

Просмотреть файл

@ -111,6 +111,7 @@ support-files =
referrer.sjs
performance_observer.html
sharedWorker_ports.js
sharedWorker_lifetime.js
[test_404.html]
[test_atob.html]
@ -223,3 +224,4 @@ skip-if = (os == "win") || (os == "mac") || toolkit == 'android' || e10s #bug 79
[test_xhrAbort.html]
[test_referrer.html]
[test_sharedWorker_ports.html]
[test_sharedWorker_lifetime.html]

Просмотреть файл

@ -0,0 +1,5 @@
onconnect = function(e) {
setTimeout(function() {
e.ports[0].postMessage("Still alive!");
}, 500);
}

Просмотреть файл

@ -0,0 +1,32 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for MessagePort and SharedWorkers</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<script class="testbody" type="text/javascript">
var gced = false;
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
function() {
var sw = new SharedWorker('sharedWorker_lifetime.js');
sw.port.onmessage = function(event) {
ok(gced, "The SW is still alive also after GC");
SimpleTest.finish();
}
sw = null;
SpecialPowers.forceGC();
gced = true;
});
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>