Bug 1708070 - Use VsyncTaskManager::WillRunTask to change InputVsyncState r=smaug

Currently, we use `VsyncTaskManager::DidRunTask` to change state from
`RunVsync` to `NoPendingVsync`, however, the issue is that if the vsync
starts an event loop (for instance, by using requestAnimationFrame), and
the event loop starts another input task, Firefox crashes because input
tasks don't expect the state to be `RunVsync`.

So instead of using `DidRunTask`, we start to use `WillRunTask` to fix
it.

Differential Revision: https://phabricator.services.mozilla.com/D113613
This commit is contained in:
Sean Feng 2021-04-29 16:39:30 +00:00
Родитель 4fab3e6602
Коммит 53d05dfbc0
7 изменённых файлов: 69 добавлений и 6 удалений

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

@ -243,6 +243,7 @@ support-files =
!/dom/events/test/event_leak_utils.js
../../../toolkit/components/pdfjs/test/file_pdfjs_test.pdf
green.png
slow.sjs
[test_anchor_area_referrer.html]
[test_anchor_area_referrer_changing.html]
@ -683,6 +684,7 @@ skip-if = (processor == 'aarch64' && os == 'win') # aarch64 due to 1530895
[test_innersize_scrollport.html]
skip-if = (verify && (os == 'win' || os == 'mac'))
[test_input_vsync_alignment_lower_than_normal.html]
[test_input_vsync_alignment_input_while_vsync.html]
[test_integer_attr_with_leading_zero.html]
[test_intersectionobservers.html]
[test_link_prefetch.html]

11
dom/base/test/slow.sjs Normal file
Просмотреть файл

@ -0,0 +1,11 @@
function handleRequest(request, response)
{
response.processAsync();
timer = Components.classes["@mozilla.org/timer;1"].
createInstance(Components.interfaces.nsITimer);
timer.init(function() {
response.write("Here the content. But slowly.");
response.finish();
}, 5000, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
}

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

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body >
<input />
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
function triggerKey() {
SpecialPowers.loadChromeScript(() => {
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { EventUtils } = ChromeUtils.import(
"resource://specialpowers/SpecialPowersEventUtils.jsm"
);
var win = Services.wm.getMostRecentBrowserWindow();
for (let i = 0; i < 200; ++i) {
EventUtils.synthesizeKey("a", {}, win);
}
});
}
function runTest() {
const input = document.querySelector("input");
input.focus();
let didInputRun = false;
input.addEventListener("input", function() {
if (!didInputRun) {
didInputRun = true;
window.requestAnimationFrame(() => {
var xhr = new XMLHttpRequest();
xhr.open("GET", "slow.sjs", false);
xhr.send();
ok(true, "Didn't crash!");
SimpleTest.finish();
});
}
});
triggerKey();
}
runTest();
</script>
</body>
</html>

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

@ -143,7 +143,7 @@ void InputTaskManager::InputPriorityController::EnterPendingVsyncState(
mRunInputStartTime = TimeStamp::Now();
}
void InputTaskManager::InputPriorityController::DidVsync() {
void InputTaskManager::InputPriorityController::WillRunVsync() {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
if (mInputVsyncState == InputVsyncState::RunVsync ||

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

@ -84,7 +84,7 @@ class InputTaskManager : public TaskManager {
void NotifyVsync() {
MOZ_ASSERT(StaticPrefs::dom_input_events_strict_input_vsync_alignment());
mInputPriorityController.DidVsync();
mInputPriorityController.WillRunVsync();
}
private:
@ -97,7 +97,7 @@ class InputTaskManager : public TaskManager {
// tasks
bool ShouldUseHighestPriority(InputTaskManager*);
void DidVsync();
void WillRunVsync();
// Gets called when a input task is finished to run; If the current
// input vsync state is `HasPendingVsync`, determines whether we

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

@ -15,8 +15,8 @@ void VsyncTaskManager::Init() {
gHighPriorityTaskManager = new VsyncTaskManager();
}
void VsyncTaskManager::DidRunTask() {
TaskManager::DidRunTask();
void VsyncTaskManager::WillRunTask() {
TaskManager::WillRunTask();
if (StaticPrefs::dom_input_events_strict_input_vsync_alignment()) {
InputTaskManager::Get()->NotifyVsync();

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

@ -16,7 +16,7 @@ class VsyncTaskManager : public TaskManager {
static void Cleanup() { gHighPriorityTaskManager = nullptr; }
static void Init();
void DidRunTask() override;
void WillRunTask() override;
private:
static StaticRefPtr<VsyncTaskManager> gHighPriorityTaskManager;