mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Don't re-resolve already-resolved generated content
This fixes #7846, a failure in the "quotes-036.htm" test. Servo lays out this test correctly in its initial layout, but then messes it up in any relayout (whether it's an incremental or full layout). The problem is that the ResolveGeneratedContent traversal is not safe to run more than once on the same flow. It mutates some GeneratedContent fragments into ScannedText fragments, but leaves others unmodified (in particular, those that generate empty content). The next time layout runs, these remaining GeneratedContent fragments are processed *again* but with an incorrect correct quote nesting level (because some of the surrounding GeneratedContent fragments are gone). This patch ensures that each GeneratedContent fragment is resolved only once.
This commit is contained in:
parent
53aca4b80e
commit
5104d8244f
5 changed files with 16 additions and 11 deletions
|
@ -256,6 +256,8 @@ fn clamp_size(size: Au,
|
|||
pub enum GeneratedContentInfo {
|
||||
ListItem,
|
||||
ContentItem(ContentItem),
|
||||
/// Placeholder for elements with generated content that did not generate any fragments.
|
||||
Empty,
|
||||
}
|
||||
|
||||
/// A hypothetical box (see CSS 2.1 § 10.3.7) for an absolutely-positioned block that was declared
|
||||
|
@ -1291,8 +1293,9 @@ impl Fragment {
|
|||
}
|
||||
|
||||
/// Returns true if and only if this fragment is a generated content fragment.
|
||||
pub fn is_generated_content(&self) -> bool {
|
||||
pub fn is_unscanned_generated_content(&self) -> bool {
|
||||
match self.specific {
|
||||
SpecificFragmentInfo::GeneratedContent(box GeneratedContentInfo::Empty) => false,
|
||||
SpecificFragmentInfo::GeneratedContent(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -180,6 +180,7 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
|
|||
list_style_type,
|
||||
RenderingMode::Suffix(".\u{00a0}"))
|
||||
}
|
||||
GeneratedContentInfo::Empty |
|
||||
GeneratedContentInfo::ContentItem(ContentItem::String(_)) => {
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
@ -242,9 +243,14 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
|
|||
}
|
||||
};
|
||||
|
||||
if let Some(new_info) = new_info {
|
||||
fragment.specific = new_info
|
||||
}
|
||||
fragment.specific = match new_info {
|
||||
Some(new_info) => new_info,
|
||||
// If the fragment did not generate any content, replace it with a no-op placeholder
|
||||
// so that it isn't processed again on the next layout. FIXME (mbrubeck): When
|
||||
// processing an inline flow, this traversal should be allowed to insert or remove
|
||||
// fragments. Then we can just remove these fragments rather than adding placeholders.
|
||||
None => SpecificFragmentInfo::GeneratedContent(box GeneratedContentInfo::Empty)
|
||||
};
|
||||
}
|
||||
|
||||
fn reset_and_increment_counters_as_necessary(&mut self, fragment: &mut Fragment) {
|
||||
|
|
|
@ -846,10 +846,8 @@ impl InlineFlow {
|
|||
first_line_indentation: Au(0),
|
||||
};
|
||||
|
||||
for fragment in &flow.fragments.fragments {
|
||||
if fragment.is_generated_content() {
|
||||
flow.base.restyle_damage.insert(RESOLVE_GENERATED_CONTENT)
|
||||
}
|
||||
if flow.fragments.fragments.iter().any(Fragment::is_unscanned_generated_content) {
|
||||
flow.base.restyle_damage.insert(RESOLVE_GENERATED_CONTENT);
|
||||
}
|
||||
|
||||
flow
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![feature(as_unsafe_cell)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(custom_derive)]
|
||||
#![feature(mpsc_select)]
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[quotes-036.htm]
|
||||
type: reftest
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue