зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1193414 - SharedWorkers thread should be kept alive also when the SharedWorker object is CCed, r=khuey
This commit is contained in:
Родитель
787b689f00
Коммит
abdc1eebce
|
@ -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>
|
Загрузка…
Ссылка в новой задаче