Bug 1602741 - Ensure shell drainJobQueue() function always drains the job queue r=sfink

Previously this wouldn't drain any jobs queued by FinalizationGroup callbacks.

Differential Revision: https://phabricator.services.mozilla.com/D56538

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jon Coppeard 2019-12-10 20:26:20 +00:00
Родитель 3292e920dc
Коммит 47fa72c92f
2 изменённых файлов: 46 добавлений и 8 удалений

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

@ -0,0 +1,26 @@
// |jit-test| --enable-weak-refs
// Test that drainJobQueue() drains all jobs, including those queued
// by FinalizationGroup callbacks.
let finalizeRan = false;
let promiseRan = false;
let fg = new FinalizationGroup(() => {
finalizeRan = true;
Promise.resolve().then(() => {
promiseRan = true;
});
});
fg.register({}, {});
gc();
assertEq(finalizeRan, false);
assertEq(promiseRan, false);
drainJobQueue();
assertEq(finalizeRan, true);
assertEq(promiseRan, true);

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

@ -1030,13 +1030,16 @@ static void ShellCleanupFinalizationGroupCallback(JSObject* group, void* data) {
} }
} }
static void MaybeRunFinalizationGroupCleanupTasks(JSContext* cx) { // Run any FinalizationGroup cleanup tasks and return whether any ran.
static bool MaybeRunFinalizationGroupCleanupTasks(JSContext* cx) {
ShellContext* sc = GetShellContext(cx); ShellContext* sc = GetShellContext(cx);
MOZ_ASSERT(!sc->quitting); MOZ_ASSERT(!sc->quitting);
Rooted<ShellContext::ObjectVector> groups(cx); Rooted<ShellContext::ObjectVector> groups(cx);
std::swap(groups.get(), sc->finalizationGroupsToCleanUp.get()); std::swap(groups.get(), sc->finalizationGroupsToCleanUp.get());
bool ranTasks = false;
RootedObject group(cx); RootedObject group(cx);
for (const auto& g : groups) { for (const auto& g : groups) {
group = g; group = g;
@ -1048,10 +1051,14 @@ static void MaybeRunFinalizationGroupCleanupTasks(JSContext* cx) {
mozilla::Unused << JS::CleanupQueuedFinalizationGroup(cx, group); mozilla::Unused << JS::CleanupQueuedFinalizationGroup(cx, group);
} }
ranTasks = true;
if (sc->quitting) { if (sc->quitting) {
break; break;
} }
} }
return ranTasks;
} }
static bool EnqueueJob(JSContext* cx, unsigned argc, Value* vp) { static bool EnqueueJob(JSContext* cx, unsigned argc, Value* vp) {
@ -1074,14 +1081,19 @@ static void RunShellJobs(JSContext* cx) {
return; return;
} }
// Run microtasks. while (true) {
js::RunJobs(cx); // Run microtasks.
if (sc->quitting) { js::RunJobs(cx);
return; if (sc->quitting) {
} return;
}
// Run tasks (only finalization group clean tasks are possible). // Run tasks (only finalization group clean tasks are possible).
MaybeRunFinalizationGroupCleanupTasks(cx); bool ranTasks = MaybeRunFinalizationGroupCleanupTasks(cx);
if (!ranTasks) {
break;
}
}
} }
static bool DrainJobQueue(JSContext* cx, unsigned argc, Value* vp) { static bool DrainJobQueue(JSContext* cx, unsigned argc, Value* vp) {