1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* This test is based on
https://searchfox.org/mozilla-central/rev/e082df56bbfeaff0f388e7da9da401ff414df18f/gfx/layers/apz/test/mochitest/browser_test_select_zoom.js
*/
// In order for this test to test the original bug we need:
// 1) At least e10s enabled so that apz is enabled so we can create an
// nsDisplayAsyncZoom item
// (the insertion of this item without marking the required frame modified
// is what causes the bug in the retained display list merging)
// 2) a root content document, again so that we can create a nsDisplayAsyncZoom
// item
// 3) the root content document cannot have a display port to start
// (if it has a display port then it gets a nsDisplayAsyncZoom, but we need
// that to be created after the anonymous content we insert into the
// document)
// Point 3) requires the root content document to be in the parent process,
// since if it is in a content process it will get a displayport for being at
// the root of a process.
// Creating an in-process root content document I think is not possible in
// mochitest-plain. mochitest-chrome does not have e10s enabled. So this has to
// be a mochitest-browser-chrome test.
// Outline of this test:
// Open a new tab with a pretty simple content file, that is not scrollable
// Use the anonymous content api to insert into that content doc
// Set a displayport on the root scroll frame of the content doc directly.
// Then we have to be careful not to do anything that causes a full display
// list rebuild.
// And finally we change the color of the fixed element which covers the whole
// viewport which causes us to do a partial display list update including the
// anonymous content, which hits the assert we are aiming to test.
add_task(async function () {
function getChromeURL(filename) {
let chromeURL = getRootDirectory(gTestPath) + filename;
return chromeURL;
}
// We need this otherwise there is a burst animation on the new tab when it
// loads and that somehow scrolls a scroll frame, which makes it active,
// which makes the scrolled frame an AGR, which means we have multiple AGRs
// (the display port makes the root scroll frame active and an AGR) so we hit
// this
// https://searchfox.org/mozilla-central/rev/e082df56bbfeaff0f388e7da9da401ff414df18f/layout/painting/RetainedDisplayListBuilder.cpp#1179
// and are forced to do a full display list rebuild and that prevents us from
// testing the original bug.
await SpecialPowers.pushPrefEnv({
set: [["ui.prefersReducedMotion", 1]],
});
const pageUrl = getChromeURL("helper_bug1701027-2.html");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
const [theX, theY] = await SpecialPowers.spawn(
tab.linkedBrowser,
[],
async () => {
content.document.body.offsetWidth;
await new Promise(r => content.window.requestAnimationFrame(r));
const rect = content.document
.getElementById("fd")
.getBoundingClientRect();
const x = content.window.mozInnerScreenX + rect.left + rect.width / 2;
const y = content.window.mozInnerScreenY + rect.top + rect.height / 2;
let doc = SpecialPowers.wrap(content.document);
var bq = doc.createElement("blockquote");
bq.textContent = "This blockquote text.";
var div = doc.createElement("div");
div.textContent = " This div text.";
bq.appendChild(div);
var ac = doc.insertAnonymousContent(bq);
content.document.body.offsetWidth;
await new Promise(r => content.window.requestAnimationFrame(r));
await new Promise(r => content.window.requestAnimationFrame(r));
content.window.windowUtils.setDisplayPortMarginsForElement(
0,
0,
0,
0,
doc.documentElement,
1
);
content.window.windowUtils.setDisplayPortBaseForElement(
0,
0,
100,
100,
doc.documentElement
);
await new Promise(r => content.window.requestAnimationFrame(r));
await new Promise(r => content.window.requestAnimationFrame(r));
return [x, y];
}
);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
content.document.getElementById("fd").style.backgroundColor = "blue";
});
await new Promise(resolve => setTimeout(resolve, 0));
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await new Promise(r => content.window.requestAnimationFrame(r));
await new Promise(r => content.window.requestAnimationFrame(r));
});
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
content.document.getElementById("fd").style.backgroundColor = "red";
});
await new Promise(resolve => setTimeout(resolve, 0));
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await new Promise(r => content.window.requestAnimationFrame(r));
await new Promise(r => content.window.requestAnimationFrame(r));
});
BrowserTestUtils.removeTab(tab);
ok(true, "didn't crash");
});
|