mirror of
https://github.com/lexmount/moli.git
synced 2026-10-30 16:07:24 +00:00
perf(layout): remove per-style anonymous provenance
This commit is contained in:
@@ -1,33 +1,45 @@
|
||||
use crate::ResolvedLayoutStyle;
|
||||
|
||||
/// Renderer-assigned provenance of a projected style. Pass identities must
|
||||
/// remain unique while any of their styles can still be used as parents.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct LayoutStyleOrigin {
|
||||
pass: u64,
|
||||
owner: u64,
|
||||
}
|
||||
|
||||
impl LayoutStyleOrigin {
|
||||
pub const fn new(pass: u64, owner: u64) -> Self {
|
||||
Self { pass, owner }
|
||||
}
|
||||
}
|
||||
use crate::{LayoutBox, ResolvedLayoutStyle};
|
||||
|
||||
/// Inheritance input for an anonymous box in the resolver's prepared pass.
|
||||
/// The owner supplies provenance and diagnostics; it does not select a style
|
||||
/// world or request another element-style observation.
|
||||
/// Owner and style are borrowed from the same parent box. During construction,
|
||||
/// layout may also pair a newly resolved style with its source before its box
|
||||
/// exists. Renderers consume this input without selecting another style world
|
||||
/// or observing the owner's element style again.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct LayoutAnonymousStyleContext<'a, N> {
|
||||
pub owner: N,
|
||||
pub parent_style: &'a ResolvedLayoutStyle,
|
||||
owner: N,
|
||||
parent_style: &'a ResolvedLayoutStyle,
|
||||
}
|
||||
|
||||
impl<'a, N> LayoutAnonymousStyleContext<'a, N> {
|
||||
pub const fn new(owner: N, parent_style: &'a ResolvedLayoutStyle) -> Self {
|
||||
pub(crate) const fn new(owner: N, parent_style: &'a ResolvedLayoutStyle) -> Self {
|
||||
Self {
|
||||
owner,
|
||||
parent_style,
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives both inputs from one parent instead of accepting an unrelated
|
||||
/// owner and style. A parent without a source or anonymous owner has no
|
||||
/// native inheritance context.
|
||||
pub fn from_parent(parent: &'a LayoutBox<N>) -> Option<Self>
|
||||
where
|
||||
N: Copy,
|
||||
{
|
||||
Some(Self::new(
|
||||
parent.source().or(parent.owner())?,
|
||||
parent.style(),
|
||||
))
|
||||
}
|
||||
|
||||
pub const fn owner(&self) -> N
|
||||
where
|
||||
N: Copy,
|
||||
{
|
||||
self.owner
|
||||
}
|
||||
|
||||
pub const fn parent_style(&self) -> &'a ResolvedLayoutStyle {
|
||||
self.parent_style
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,8 @@ where
|
||||
None
|
||||
};
|
||||
let editor_style = styles.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, &world.boxes[control.index()].style),
|
||||
LayoutAnonymousStyleContext::from_parent(&world.boxes[control.index()])
|
||||
.expect("form control has a source owner"),
|
||||
LayoutDisplay::Block,
|
||||
)?;
|
||||
let selection = world.boxes[control.index()].text_selection;
|
||||
|
||||
@@ -41,7 +41,7 @@ mod taffy_tree;
|
||||
mod text;
|
||||
mod world;
|
||||
|
||||
pub use anonymous_style::{LayoutAnonymousStyleContext, LayoutStyleOrigin};
|
||||
pub use anonymous_style::LayoutAnonymousStyleContext;
|
||||
pub use builder::build_layout_world;
|
||||
pub use capture::{
|
||||
FULL_DOCUMENT_CAPTURE_CSS_DIMENSION_LIMIT, PaintCaptureRegion, PaintCaptureRequest,
|
||||
|
||||
@@ -666,7 +666,7 @@ where
|
||||
display: crate::LayoutDisplay,
|
||||
) -> Result<ResolvedLayoutStyle, LayoutError> {
|
||||
Ok(ResolvedLayoutStyle::anonymous_from(
|
||||
context.parent_style,
|
||||
context.parent_style(),
|
||||
display,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -482,7 +482,6 @@ impl ResolvedLayoutTransform {
|
||||
/// invalid.
|
||||
#[derive(Clone)]
|
||||
pub struct ResolvedLayoutStyle {
|
||||
source_origin: Option<crate::LayoutStyleOrigin>,
|
||||
pub(crate) computed: Option<ServoArc<ComputedValues>>,
|
||||
pub(crate) taffy: Style<Atom>,
|
||||
preferred_aspect_ratio: PreferredAspectRatio,
|
||||
@@ -866,7 +865,6 @@ impl ResolvedLayoutStyle {
|
||||
};
|
||||
}
|
||||
Self {
|
||||
source_origin: None,
|
||||
computed: Some(computed),
|
||||
taffy,
|
||||
preferred_aspect_ratio,
|
||||
@@ -944,7 +942,6 @@ impl ResolvedLayoutStyle {
|
||||
};
|
||||
let sticky_inset = taffy.inset;
|
||||
Self {
|
||||
source_origin: None,
|
||||
computed: None,
|
||||
taffy,
|
||||
preferred_aspect_ratio,
|
||||
@@ -1170,17 +1167,6 @@ impl ResolvedLayoutStyle {
|
||||
self.computed.as_ref()
|
||||
}
|
||||
|
||||
/// Binds a renderer projection to its pass and source. Cloning and
|
||||
/// deriving anonymous/text styles preserve this identity.
|
||||
pub fn with_source_origin(mut self, origin: crate::LayoutStyleOrigin) -> Self {
|
||||
self.source_origin = Some(origin);
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn source_origin(&self) -> Option<crate::LayoutStyleOrigin> {
|
||||
self.source_origin
|
||||
}
|
||||
|
||||
pub fn background_color(&self) -> PaintColor {
|
||||
self.background_color
|
||||
}
|
||||
@@ -1993,7 +1979,6 @@ impl ResolvedLayoutStyle {
|
||||
|
||||
pub(crate) fn text_leaf_from(parent: &Self) -> Self {
|
||||
Self {
|
||||
source_origin: parent.source_origin,
|
||||
computed: parent.computed.clone(),
|
||||
taffy: Style {
|
||||
display: TaffyDisplay::Block,
|
||||
@@ -2061,7 +2046,6 @@ impl ResolvedLayoutStyle {
|
||||
/// Stylo allocation (primarily DOM-free tests and conservative fallback).
|
||||
pub fn anonymous_from(parent: &Self, display: LayoutDisplay) -> Self {
|
||||
Self {
|
||||
source_origin: parent.source_origin,
|
||||
computed: parent.computed.clone(),
|
||||
taffy: Style {
|
||||
display: taffy_display(display),
|
||||
|
||||
@@ -196,9 +196,9 @@ impl LayoutStyleResolver<usize> for TestStyles {
|
||||
context: moli_layout::LayoutAnonymousStyleContext<'_, usize>,
|
||||
display: LayoutDisplay,
|
||||
) -> Result<ResolvedLayoutStyle, LayoutError> {
|
||||
self.anonymous_queries.push((context.owner, display));
|
||||
self.anonymous_queries.push((context.owner(), display));
|
||||
Ok(ResolvedLayoutStyle::anonymous_from(
|
||||
context.parent_style,
|
||||
context.parent_style(),
|
||||
display,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ impl LayoutStyleResolver<usize> for FixtureStyles {
|
||||
display: LayoutDisplay,
|
||||
) -> Result<ResolvedLayoutStyle, LayoutError> {
|
||||
Ok(ResolvedLayoutStyle::anonymous_from(
|
||||
context.parent_style,
|
||||
context.parent_style(),
|
||||
display,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
use moli_layout::{
|
||||
LayoutAnonymousStyleContext, LayoutDisplay, LayoutError, LayoutStyleOrigin,
|
||||
LayoutStyleResolver, LayoutViewport, ResolvedLayoutElementStyles, ResolvedLayoutPseudoStyle,
|
||||
ResolvedLayoutStyle,
|
||||
};
|
||||
use std::{
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
time::Instant,
|
||||
LayoutAnonymousStyleContext, LayoutDisplay, LayoutError, LayoutStyleResolver, LayoutViewport,
|
||||
ResolvedLayoutElementStyles, ResolvedLayoutPseudoStyle, ResolvedLayoutStyle,
|
||||
};
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::{
|
||||
document_runtime::DomHandle,
|
||||
@@ -17,13 +13,10 @@ use crate::{
|
||||
style_engine::{StyleViewport, StyloAnonymousBoxKind},
|
||||
};
|
||||
|
||||
static NEXT_STYLE_PASS: AtomicU64 = AtomicU64::new(1);
|
||||
|
||||
pub(super) struct NativeLayoutStyleResolver<'a> {
|
||||
runtime: &'a JsContextHost,
|
||||
reads: StyleObservation<'a>,
|
||||
anonymous_context: Option<PreparedAnonymousStyleContext<'a>>,
|
||||
pass_id: u64,
|
||||
scripting_enabled: bool,
|
||||
profile: Option<NativeLayoutStyleResolverProfile>,
|
||||
}
|
||||
@@ -59,21 +52,12 @@ impl<'a> NativeLayoutStyleResolver<'a> {
|
||||
runtime,
|
||||
reads,
|
||||
anonymous_context,
|
||||
pass_id: NEXT_STYLE_PASS
|
||||
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |next| {
|
||||
next.checked_add(1)
|
||||
})
|
||||
.expect("layout style pass identity exhausted"),
|
||||
scripting_enabled: runtime.document_scripting_enabled(document),
|
||||
profile: moli_trace::cpu_profile_enabled()
|
||||
.then(NativeLayoutStyleResolverProfile::default),
|
||||
}
|
||||
}
|
||||
|
||||
fn style_origin(&self, owner: DomHandle) -> LayoutStyleOrigin {
|
||||
LayoutStyleOrigin::new(self.pass_id, u64::from(owner.index_u32()))
|
||||
}
|
||||
|
||||
pub(super) fn trace_profile(&self, document: crate::document_runtime::DomHandle) {
|
||||
let Some(profile) = self.profile.as_ref() else {
|
||||
return;
|
||||
@@ -152,8 +136,7 @@ impl LayoutStyleResolver<DomHandle> for NativeLayoutStyleResolver<'_> {
|
||||
);
|
||||
}
|
||||
let phase_started = self.profile.as_ref().map(|_| Instant::now());
|
||||
let origin = self.style_origin(node);
|
||||
let mut resolved = ResolvedLayoutStyle::from_stylo(computed).with_source_origin(origin);
|
||||
let mut resolved = ResolvedLayoutStyle::from_stylo(computed);
|
||||
if let Some(profile) = self.profile.as_mut() {
|
||||
profile.primary_projection_ns = profile.primary_projection_ns.saturating_add(
|
||||
phase_started
|
||||
@@ -162,10 +145,8 @@ impl LayoutStyleResolver<DomHandle> for NativeLayoutStyleResolver<'_> {
|
||||
);
|
||||
}
|
||||
let phase_started = self.profile.as_ref().map(|_| Instant::now());
|
||||
let before = before
|
||||
.map(|computed| ResolvedLayoutStyle::from_stylo(computed).with_source_origin(origin));
|
||||
let after = after
|
||||
.map(|computed| ResolvedLayoutStyle::from_stylo(computed).with_source_origin(origin));
|
||||
let before = before.map(ResolvedLayoutStyle::from_stylo);
|
||||
let after = after.map(ResolvedLayoutStyle::from_stylo);
|
||||
if let Some(profile) = self.profile.as_mut() {
|
||||
profile.eager_pseudo_count = profile
|
||||
.eager_pseudo_count
|
||||
@@ -217,11 +198,8 @@ impl LayoutStyleResolver<DomHandle> for NativeLayoutStyleResolver<'_> {
|
||||
);
|
||||
}
|
||||
let phase_started = self.profile.as_ref().map(|_| Instant::now());
|
||||
let origin = self.style_origin(node);
|
||||
let resolved = computed.map(|computed| {
|
||||
ResolvedLayoutPseudoStyle::new(
|
||||
ResolvedLayoutStyle::from_stylo(computed).with_source_origin(origin),
|
||||
)
|
||||
ResolvedLayoutPseudoStyle::new(ResolvedLayoutStyle::from_stylo(computed))
|
||||
});
|
||||
if let Some(profile) = self.profile.as_mut() {
|
||||
profile.marker_projection_ns = profile.marker_projection_ns.saturating_add(
|
||||
@@ -237,15 +215,12 @@ impl LayoutStyleResolver<DomHandle> for NativeLayoutStyleResolver<'_> {
|
||||
&mut self,
|
||||
node: DomHandle,
|
||||
) -> Result<Option<ResolvedLayoutPseudoStyle>, LayoutError> {
|
||||
let origin = self.style_origin(node);
|
||||
Ok(self
|
||||
.reads
|
||||
.read(node)
|
||||
.pseudo_computed_values("placeholder")
|
||||
.map(|computed| {
|
||||
ResolvedLayoutPseudoStyle::new(
|
||||
ResolvedLayoutStyle::from_stylo(computed).with_source_origin(origin),
|
||||
)
|
||||
ResolvedLayoutPseudoStyle::new(ResolvedLayoutStyle::from_stylo(computed))
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -254,8 +229,8 @@ impl LayoutStyleResolver<DomHandle> for NativeLayoutStyleResolver<'_> {
|
||||
context: LayoutAnonymousStyleContext<'_, DomHandle>,
|
||||
display: LayoutDisplay,
|
||||
) -> Result<ResolvedLayoutStyle, LayoutError> {
|
||||
let owner = context.owner;
|
||||
let parent = context.parent_style;
|
||||
let owner = context.owner();
|
||||
let parent = context.parent_style();
|
||||
let parent_computed = parent.stylo_computed_values().ok_or_else(|| {
|
||||
LayoutError::style_resolution(
|
||||
format!("{owner:?}"),
|
||||
@@ -276,13 +251,6 @@ impl LayoutStyleResolver<DomHandle> for NativeLayoutStyleResolver<'_> {
|
||||
"anonymous owner document does not match the prepared style context",
|
||||
));
|
||||
}
|
||||
let origin = self.style_origin(owner);
|
||||
if parent.source_origin() != Some(origin) {
|
||||
return Err(LayoutError::style_resolution(
|
||||
format!("{owner:?}"),
|
||||
"anonymous parent style does not match its owner and layout pass",
|
||||
));
|
||||
}
|
||||
let computed = prepared
|
||||
.computed_values(owner, parent_computed.as_ref(), anonymous_kind)
|
||||
.ok_or_else(|| {
|
||||
@@ -300,7 +268,7 @@ impl LayoutStyleResolver<DomHandle> for NativeLayoutStyleResolver<'_> {
|
||||
);
|
||||
}
|
||||
let phase_started = self.profile.as_ref().map(|_| Instant::now());
|
||||
let mut resolved = ResolvedLayoutStyle::from_stylo(computed).with_source_origin(origin);
|
||||
let mut resolved = ResolvedLayoutStyle::from_stylo(computed);
|
||||
resolved.force_layout_display(display);
|
||||
if let Some(profile) = self.profile.as_mut() {
|
||||
profile.anonymous_projection_ns = profile.anonymous_projection_ns.saturating_add(
|
||||
@@ -368,12 +336,20 @@ mod tests {
|
||||
vm
|
||||
}
|
||||
|
||||
fn parent_style(
|
||||
fn layout_world(
|
||||
resolver: &mut NativeLayoutStyleResolver<'_>,
|
||||
root: DomHandle,
|
||||
) -> moli_layout::LayoutWorld<DomHandle> {
|
||||
let source = super::super::source_view::NativeLayoutSourceView::new(resolver.runtime, root);
|
||||
moli_layout::build_layout_world(&source, resolver).unwrap()
|
||||
}
|
||||
|
||||
fn parent_context(
|
||||
world: &moli_layout::LayoutWorld<DomHandle>,
|
||||
owner: DomHandle,
|
||||
) -> ResolvedLayoutStyle {
|
||||
ResolvedLayoutStyle::from_stylo(resolver.reads.read(owner).computed_values().unwrap())
|
||||
.with_source_origin(resolver.style_origin(owner))
|
||||
) -> LayoutAnonymousStyleContext<'_, DomHandle> {
|
||||
let parent = world.box_by_id(world.source_box(owner).unwrap()).unwrap();
|
||||
LayoutAnonymousStyleContext::from_parent(parent).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -386,16 +362,14 @@ mod tests {
|
||||
let owner = host.dom_host().element_handle_by_id("owner").unwrap();
|
||||
let viewport = host.layout_viewport_for_document(document);
|
||||
let mut resolver = NativeLayoutStyleResolver::new(&host, root, document, viewport);
|
||||
let parent = parent_style(&mut resolver, owner);
|
||||
let world = layout_world(&mut resolver, root);
|
||||
let parent = parent_context(&world, owner);
|
||||
let reads = resolver.reads.read_count_for_test();
|
||||
for _ in 0..3 {
|
||||
resolver.profile = Some(NativeLayoutStyleResolverProfile::default());
|
||||
for _ in 0..10_000 {
|
||||
let style = resolver
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, &parent),
|
||||
LayoutDisplay::Block,
|
||||
)
|
||||
.anonymous_style(parent, LayoutDisplay::Block)
|
||||
.unwrap();
|
||||
assert_eq!(style.display(), LayoutDisplay::Block);
|
||||
std::hint::black_box(style);
|
||||
@@ -415,7 +389,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anonymous_styles_reject_mismatched_owners_documents_and_passes() {
|
||||
fn anonymous_styles_reject_foreign_documents() {
|
||||
let mut vm = fixture();
|
||||
vm.eval("document.getElementById('frame').contentDocument.body.textContent = 'child'")
|
||||
.unwrap();
|
||||
@@ -424,38 +398,10 @@ mod tests {
|
||||
let document = host.document_handle();
|
||||
let root = host.dom_host().document_element_handle().unwrap();
|
||||
let owner = host.dom_host().element_handle_by_id("owner").unwrap();
|
||||
let other = host.dom_host().element_handle_by_id("other").unwrap();
|
||||
let viewport = host.layout_viewport_for_document(document);
|
||||
let mut resolver = NativeLayoutStyleResolver::new(&host, root, document, viewport);
|
||||
let parent = parent_style(&mut resolver, owner);
|
||||
let other_parent = parent_style(&mut resolver, other);
|
||||
for (owner, parent) in [(owner, &other_parent), (other, &parent)] {
|
||||
let error = resolver
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, parent),
|
||||
LayoutDisplay::Block,
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(
|
||||
error.to_string().contains("owner and layout pass"),
|
||||
"{error}"
|
||||
);
|
||||
}
|
||||
|
||||
let mut inherited = parent.clone();
|
||||
let reads = resolver.reads.read_count_for_test();
|
||||
for display in [
|
||||
LayoutDisplay::Table,
|
||||
LayoutDisplay::TableRow,
|
||||
LayoutDisplay::TableCell,
|
||||
] {
|
||||
inherited = resolver
|
||||
.anonymous_style(LayoutAnonymousStyleContext::new(owner, &inherited), display)
|
||||
.unwrap();
|
||||
assert_eq!(inherited.font_size(), parent.font_size());
|
||||
assert_eq!(inherited.source_origin(), parent.source_origin());
|
||||
}
|
||||
assert_eq!(resolver.reads.read_count_for_test(), reads);
|
||||
let world = layout_world(&mut resolver, root);
|
||||
let parent = parent_context(&world, owner);
|
||||
|
||||
let frame = host.dom_host().element_handle_by_id("frame").unwrap();
|
||||
let foreign_document = host.child_browsing_context_document_handle(frame).unwrap();
|
||||
@@ -466,30 +412,17 @@ mod tests {
|
||||
.unwrap();
|
||||
let mut foreign =
|
||||
NativeLayoutStyleResolver::new(&host, foreign_root, foreign_document, viewport);
|
||||
let foreign_parent = parent_style(&mut foreign, foreign_root);
|
||||
let foreign_world = layout_world(&mut foreign, foreign_root);
|
||||
let foreign_parent = parent_context(&foreign_world, foreign_root);
|
||||
assert!(
|
||||
foreign
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(foreign_root, &foreign_parent),
|
||||
LayoutDisplay::Block
|
||||
)
|
||||
.anonymous_style(foreign_parent, LayoutDisplay::Block)
|
||||
.is_ok()
|
||||
);
|
||||
let error = resolver
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(foreign_root, &foreign_parent),
|
||||
LayoutDisplay::Block,
|
||||
)
|
||||
.anonymous_style(foreign_parent, LayoutDisplay::Block)
|
||||
.unwrap_err();
|
||||
assert!(error.to_string().contains("owner document"), "{error}");
|
||||
assert!(
|
||||
resolver
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, &foreign_parent),
|
||||
LayoutDisplay::Block
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
assert!(
|
||||
resolver
|
||||
.anonymous_context
|
||||
@@ -497,27 +430,70 @@ mod tests {
|
||||
.unwrap()
|
||||
.computed_values(
|
||||
foreign_root,
|
||||
parent.stylo_computed_values().unwrap(),
|
||||
parent.parent_style().stylo_computed_values().unwrap(),
|
||||
StyloAnonymousBoxKind::Generic
|
||||
)
|
||||
.is_none()
|
||||
);
|
||||
}
|
||||
|
||||
let mut next = NativeLayoutStyleResolver::new(&host, root, document, viewport);
|
||||
assert!(
|
||||
next.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, &parent),
|
||||
LayoutDisplay::Block
|
||||
)
|
||||
.is_err()
|
||||
#[test]
|
||||
fn anonymous_table_styles_inherit_from_their_parent_boxes() {
|
||||
let mut vm = fixture();
|
||||
vm.eval(
|
||||
r#"document.getElementById('owner').innerHTML = '<span style="display:table-cell">one</span><span style="display:table-row">two</span>'"#,
|
||||
)
|
||||
.unwrap();
|
||||
vm.sync_live_document_style_sources();
|
||||
let host = vm.context_host_weak_for_test().upgrade().unwrap();
|
||||
let host = host.borrow();
|
||||
let document = host.document_handle();
|
||||
let root = host.dom_host().document_element_handle().unwrap();
|
||||
let owner = host.dom_host().element_handle_by_id("owner").unwrap();
|
||||
let mut resolver = NativeLayoutStyleResolver::new(
|
||||
&host,
|
||||
root,
|
||||
document,
|
||||
host.layout_viewport_for_document(document),
|
||||
);
|
||||
let world = layout_world(&mut resolver, root);
|
||||
let reads = resolver.reads.read_count_for_test();
|
||||
let mut pending = vec![world.source_box(owner).unwrap()];
|
||||
let mut displays = Vec::new();
|
||||
while let Some(id) = pending.pop() {
|
||||
let parent = world.box_by_id(id).unwrap();
|
||||
pending.extend_from_slice(parent.children());
|
||||
if parent.anonymous_reason().is_none() {
|
||||
continue;
|
||||
}
|
||||
let context = LayoutAnonymousStyleContext::from_parent(parent).unwrap();
|
||||
assert_eq!(context.owner(), parent.owner().unwrap());
|
||||
assert_eq!(context.parent_style().font_size(), 23.0);
|
||||
let anonymous = resolver
|
||||
.anonymous_style(context, LayoutDisplay::Block)
|
||||
.unwrap();
|
||||
assert_eq!(anonymous.font_size(), 23.0);
|
||||
displays.push(parent.style().display());
|
||||
}
|
||||
for display in [
|
||||
LayoutDisplay::Table,
|
||||
LayoutDisplay::TableRowGroup,
|
||||
LayoutDisplay::TableRow,
|
||||
LayoutDisplay::TableCell,
|
||||
] {
|
||||
assert!(
|
||||
displays.contains(&display),
|
||||
"missing {display:?}: {displays:?}"
|
||||
);
|
||||
}
|
||||
assert_eq!(resolver.reads.read_count_for_test(), reads);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anonymous_styles_prepare_pending_invalidations_for_each_pass() {
|
||||
let mut vm = fixture();
|
||||
vm.sync_live_document_style_sources();
|
||||
let initial = {
|
||||
{
|
||||
let host = vm.context_host_weak_for_test().upgrade().unwrap();
|
||||
let host = host.borrow();
|
||||
let document = host.document_handle();
|
||||
@@ -529,20 +505,17 @@ mod tests {
|
||||
document,
|
||||
host.layout_viewport_for_document(document),
|
||||
);
|
||||
let parent = parent_style(&mut resolver, owner);
|
||||
assert_eq!(parent.font_size(), 23.0);
|
||||
let world = layout_world(&mut resolver, root);
|
||||
let parent = parent_context(&world, owner);
|
||||
assert_eq!(parent.parent_style().font_size(), 23.0);
|
||||
assert_eq!(
|
||||
resolver
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, &parent),
|
||||
LayoutDisplay::Block
|
||||
)
|
||||
.anonymous_style(parent, LayoutDisplay::Block)
|
||||
.unwrap()
|
||||
.font_size(),
|
||||
23.0
|
||||
);
|
||||
parent
|
||||
};
|
||||
}
|
||||
for (mutation, expected) in [
|
||||
(
|
||||
"document.getElementById('owner').style.fontSize = '37px'",
|
||||
@@ -566,25 +539,15 @@ mod tests {
|
||||
document,
|
||||
host.layout_viewport_for_document(document),
|
||||
);
|
||||
let parent = parent_style(&mut resolver, owner);
|
||||
assert_eq!(parent.font_size(), expected);
|
||||
let world = layout_world(&mut resolver, root);
|
||||
let parent = parent_context(&world, owner);
|
||||
assert_eq!(parent.parent_style().font_size(), expected);
|
||||
let reads = resolver.reads.read_count_for_test();
|
||||
let anonymous = resolver
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, &parent),
|
||||
LayoutDisplay::Block,
|
||||
)
|
||||
.anonymous_style(parent, LayoutDisplay::Block)
|
||||
.unwrap();
|
||||
assert_eq!(anonymous.font_size(), expected);
|
||||
assert_eq!(resolver.reads.read_count_for_test(), reads);
|
||||
assert!(
|
||||
resolver
|
||||
.anonymous_style(
|
||||
LayoutAnonymousStyleContext::new(owner, &initial),
|
||||
LayoutDisplay::Block
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user