diff options
24 files changed, 474 insertions, 297 deletions
diff --git a/components/domobject_derive/lib.rs b/components/domobject_derive/lib.rs index fdc2c84b26e..c103bb73ece 100644 --- a/components/domobject_derive/lib.rs +++ b/components/domobject_derive/lib.rs @@ -58,7 +58,7 @@ fn expand_dom_object(input: syn::DeriveInput) -> proc_macro2::TokenStream { } impl #impl_generics crate::dom::bindings::reflector::MutDomObject for #name #ty_generics #where_clause { - fn init_reflector(&mut self, obj: *mut js::jsapi::JSObject) { + unsafe fn init_reflector(&self, obj: *mut js::jsapi::JSObject) { self.#first_field_name.init_reflector(obj); } } diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs index 11b45edab91..1d2bb10c838 100644 --- a/components/layout_2020/display_list/mod.rs +++ b/components/layout_2020/display_list/mod.rs @@ -37,7 +37,12 @@ type ItemTag = (u64, u16); type HitInfo = Option<ItemTag>; pub struct DisplayListBuilder<'a> { + /// The current SpatialId and ClipId information for this `DisplayListBuilder`. current_space_and_clip: wr::SpaceAndClipInfo, + + /// The id of the nearest ancestor reference frame for this `DisplayListBuilder`. + nearest_reference_frame: wr::SpatialId, + pub context: &'a LayoutContext<'a>, pub wr: wr::DisplayListBuilder, @@ -56,6 +61,7 @@ impl<'a> DisplayListBuilder<'a> { ) -> Self { Self { current_space_and_clip: wr::SpaceAndClipInfo::root_scroll(pipeline_id), + nearest_reference_frame: wr::SpatialId::root_reference_frame(pipeline_id), is_contentful: false, context, wr: wr::DisplayListBuilder::new(pipeline_id, viewport_size), @@ -68,9 +74,14 @@ impl<'a> DisplayListBuilder<'a> { } fn clipping_and_scrolling_scope<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { - let previous = self.current_space_and_clip; + let previous_space_and_clip = self.current_space_and_clip; + let previous_nearest_reference_frame = self.nearest_reference_frame; + let result = f(self); - self.current_space_and_clip = previous; + + self.current_space_and_clip = previous_space_and_clip; + self.nearest_reference_frame = previous_nearest_reference_frame; + result } } diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs index 7e4d27e2357..83299a38b52 100644 --- a/components/layout_2020/display_list/stacking_context.rs +++ b/components/layout_2020/display_list/stacking_context.rs @@ -6,6 +6,7 @@ use crate::display_list::conversions::ToWebRender; use crate::display_list::DisplayListBuilder; use crate::fragments::{AnonymousFragment, BoxFragment, Fragment}; use crate::geom::PhysicalRect; +use crate::style_ext::ComputedValuesExt; use euclid::default::Rect; use gfx_traits::{combine_id_with_fragment_type, FragmentType}; use std::cmp::Ordering; @@ -14,7 +15,6 @@ use style::computed_values::float::T as ComputedFloat; use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode; use style::computed_values::overflow_x::T as ComputedOverflow; use style::computed_values::position::T as ComputedPosition; -use style::computed_values::transform_style::T as ComputedTransformStyle; use style::values::computed::Length; use style::values::generics::box_::Perspective; use style::values::generics::transform; @@ -96,7 +96,7 @@ impl<'a> StackingContext<'a> { fn z_index(&self) -> i32 { match self.initializing_fragment { - Some(fragment) => fragment.effective_z_index(), + Some(fragment) => fragment.style.effective_z_index(), None => 0, } } @@ -259,7 +259,7 @@ impl Fragment { impl BoxFragment { fn get_stacking_context_type(&self) -> Option<StackingContextType> { - if self.establishes_stacking_context() { + if self.style.establishes_stacking_context() { return Some(StackingContextType::Real); } @@ -291,68 +291,6 @@ impl BoxFragment { StackingContextSection::BlockBackgroundsAndBorders } - /// Returns true if this fragment establishes a new stacking context and false otherwise. - fn establishes_stacking_context(&self) -> bool { - let effects = self.style.get_effects(); - if effects.opacity != 1.0 { - return true; - } - - if effects.mix_blend_mode != ComputedMixBlendMode::Normal { - return true; - } - - if self.has_transform_or_perspective() { - return true; - } - - if !self.style.get_effects().filter.0.is_empty() { - return true; - } - - if self.style.get_box().transform_style == ComputedTransformStyle::Preserve3d || - self.style.overrides_transform_style() - { - return true; - } - - // Fixed position and sticky position always create stacking contexts. - // TODO(mrobinson): We need to handle sticky positioning here when we support it. - if self.style.get_box().position == ComputedPosition::Fixed { - return true; - } - - // Statically positioned fragments don't establish stacking contexts if the previous - // conditions are not fulfilled. Furthermore, z-index doesn't apply to statically - // positioned fragments. - if self.style.get_box().position == ComputedPosition::Static { - return false; - } - - // For absolutely and relatively positioned fragments we only establish a stacking - // context if there is a z-index set. - // See https://www.w3.org/TR/CSS2/visuren.html#z-index - !self.style.get_position().z_index.is_auto() - } - - // Get the effective z-index of this fragment. Z-indices only apply to positioned element - // per CSS 2 9.9.1 (http://www.w3.org/TR/CSS2/visuren.html#z-index), so this value may differ - // from the value specified in the style. - fn effective_z_index(&self) -> i32 { - match self.style.get_box().position { - ComputedPosition::Static => {}, - _ => return self.style.get_position().z_index.integer_or(0), - } - - 0 - } - - /// Returns true if this fragment has a transform, or perspective property set. - fn has_transform_or_perspective(&self) -> bool { - !self.style.get_box().transform.0.is_empty() || - self.style.get_box().perspective != Perspective::None - } - fn build_stacking_context_tree<'a>( &'a self, fragment: &'a Fragment, @@ -452,8 +390,7 @@ impl BoxFragment { // TODO(mrobinson): Eventually this should use the spatial id of the reference // frame that is the parent of this one once we have full support for stacking // contexts and transforms. - builder.current_space_and_clip.spatial_id = - wr::SpatialId::root_reference_frame(builder.wr.pipeline_id); + builder.current_space_and_clip.spatial_id = builder.nearest_reference_frame; } fn build_scroll_frame_if_necessary( @@ -505,7 +442,7 @@ impl BoxFragment { builder: &mut DisplayListBuilder, border_rect: &PhysicalRect<Length>, ) -> bool { - if !self.has_transform_or_perspective() { + if !self.style.has_transform_or_perspective() { return false; } let untyped_border_rect = border_rect.to_untyped(); @@ -535,6 +472,7 @@ impl BoxFragment { wr::PropertyBinding::Value(reference_frame_transform), reference_frame_kind, ); + builder.nearest_reference_frame = builder.current_space_and_clip.spatial_id; true } diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index d6ab15071f6..bc50177fe1e 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -223,7 +223,8 @@ fn layout_block_level_children<'a>( }) .collect() } else { - let has_positioned_ancestor = positioning_context.has_positioned_ancestor(); + let collects_for_nearest_positioned_ancestor = + positioning_context.collects_for_nearest_positioned_ancestor(); let mut fragments = child_boxes .par_iter() .enumerate() @@ -238,7 +239,7 @@ fn layout_block_level_children<'a>( /* float_context = */ None, ) }, - || PositioningContext::new_for_rayon(has_positioned_ancestor), + || PositioningContext::new_for_rayon(collects_for_nearest_positioned_ancestor), PositioningContext::append, ) .collect(); @@ -275,7 +276,7 @@ impl BlockLevelBox { tag, style, contents, - } => Fragment::Box(positioning_context.for_maybe_position_relative( + } => Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( layout_context, containing_block, style, @@ -293,7 +294,7 @@ impl BlockLevelBox { }, )), BlockLevelBox::Independent(contents) => { - Fragment::Box(positioning_context.for_maybe_position_relative( + Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( layout_context, containing_block, &contents.style, @@ -326,8 +327,7 @@ impl BlockLevelBox { )) }, BlockLevelBox::OutOfFlowFloatBox(_box_) => { - // FIXME: call for_maybe_position_relative here - // TODO + // FIXME: call layout_maybe_position_relative_fragment here Fragment::Anonymous(AnonymousFragment::no_op( containing_block.style.writing_mode, )) diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index f1fcad7fd45..6932e66acf1 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -137,7 +137,8 @@ impl BoxTreeRoot { }; let dummy_tree_rank = 0; - let mut positioning_context = PositioningContext::new_for_initial_containing_block(); + let mut positioning_context = + PositioningContext::new_for_containing_block_for_all_descendants(); let mut independent_layout = self.0.layout( layout_context, &mut positioning_context, @@ -145,7 +146,7 @@ impl BoxTreeRoot { dummy_tree_rank, ); - positioning_context.layout_in_initial_containing_block( + positioning_context.layout_initial_containing_block_children( layout_context, &initial_containing_block, &mut independent_layout.fragments, diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 3747b4661b5..a0f0aac1c94 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -25,7 +25,12 @@ pub(crate) struct AbsolutelyPositionedBox { pub(crate) struct PositioningContext<'box_tree> { for_nearest_positioned_ancestor: Option<Vec<HoistedAbsolutelyPositionedBox<'box_tree>>>, - for_initial_containing_block: Vec<HoistedAbsolutelyPositionedBox<'box_tree>>, + + // For nearest `containing block for all descendants` as defined by the CSS transforms + // spec. + // https://www.w3.org/TR/css-transforms-1/#containing-block-for-all-descendants + for_nearest_containing_block_for_all_descendants: + Vec<HoistedAbsolutelyPositionedBox<'box_tree>>, } #[derive(Debug)] @@ -127,62 +132,158 @@ impl AbsolutelyPositionedBox { } impl<'box_tree> PositioningContext<'box_tree> { - pub(crate) fn new_for_initial_containing_block() -> Self { + pub(crate) fn new_for_containing_block_for_all_descendants() -> Self { Self { for_nearest_positioned_ancestor: None, - for_initial_containing_block: Vec::new(), + for_nearest_containing_block_for_all_descendants: Vec::new(), } } - pub(crate) fn new_for_rayon(has_positioned_ancestor: bool) -> Self { + pub(crate) fn new_for_rayon(collects_for_nearest_positioned_ancestor: bool) -> Self { Self { - for_nearest_positioned_ancestor: if has_positioned_ancestor { + for_nearest_positioned_ancestor: if collects_for_nearest_positioned_ancestor { Some(Vec::new()) } else { None }, - for_initial_containing_block: Vec::new(), + for_nearest_containing_block_for_all_descendants: Vec::new(), } } - pub(crate) fn has_positioned_ancestor(&self) -> bool { + pub(crate) fn collects_for_nearest_positioned_ancestor(&self) -> bool { self.for_nearest_positioned_ancestor.is_some() } - pub(crate) fn for_maybe_position_relative( + /// Given `fragment_layout_fn`, a closure which lays out a fragment in a provided + /// `PositioningContext`, create a new positioning context if necessary for the fragment and + /// lay out the fragment and all its children. Returns the newly created `BoxFragment`. + pub(crate) fn layout_maybe_position_relative_fragment( &mut self, layout_context: &LayoutContext, containing_block: &ContainingBlock, style: &ComputedValues, - f: impl FnOnce(&mut Self) -> BoxFragment, + fragment_layout_fn: impl FnOnce(&mut Self) -> BoxFragment, ) -> BoxFragment { - if style.clone_position() == Position::Relative { - let mut fragment = - // Establing a containing block for absolutely positioned descendants - Self::for_positioned(layout_context, &mut self.for_initial_containing_block, f); + debug_assert!(style.clone_position() != Position::Fixed); + debug_assert!(style.clone_position() != Position::Absolute); + + if style.establishes_containing_block_for_all_descendants() { + let mut fragment = Self::layout_containing_block_for_all_descendants( + layout_context, + fragment_layout_fn, + ); + if style.clone_position() == Position::Relative { + fragment.content_rect.start_corner += + &relative_adjustement(style, containing_block); + } + return fragment; + } + if style.clone_position() == Position::Relative { + let mut fragment = Self::create_and_layout_positioned( + layout_context, + style, + &mut self.for_nearest_containing_block_for_all_descendants, + fragment_layout_fn, + ); fragment.content_rect.start_corner += &relative_adjustement(style, containing_block); - fragment - } else { - f(self) + return fragment; } + + // We don't need to create a new PositioningContext for this Fragment, so + // we pass in the current one to the fragment layout closure. + fragment_layout_fn(self) } - fn for_positioned( + /// Given `fragment_layout_fn`, a closure which lays out a fragment in a provided + /// `PositioningContext`, create a positioning context a positioned fragment and lay out the + /// fragment and all its children. Returns the resulting `BoxFragment`. + fn create_and_layout_positioned( layout_context: &LayoutContext, - for_initial_containing_block: &mut Vec<HoistedAbsolutelyPositionedBox<'box_tree>>, - f: impl FnOnce(&mut Self) -> BoxFragment, + style: &ComputedValues, + for_nearest_containing_block_for_all_descendants: &mut Vec< + HoistedAbsolutelyPositionedBox<'box_tree>, + >, + fragment_layout_fn: impl FnOnce(&mut Self) -> BoxFragment, ) -> BoxFragment { + if style.establishes_containing_block_for_all_descendants() { + return Self::layout_containing_block_for_all_descendants( + layout_context, + fragment_layout_fn, + ); + } + let mut new = Self { for_nearest_positioned_ancestor: Some(Vec::new()), - for_initial_containing_block: std::mem::take(for_initial_containing_block), + for_nearest_containing_block_for_all_descendants: std::mem::take( + for_nearest_containing_block_for_all_descendants, + ), }; - let mut positioned_box_fragment = f(&mut new); - new.layout_in_positioned_ancestor(layout_context, &mut positioned_box_fragment); - *for_initial_containing_block = new.for_initial_containing_block; + let mut positioned_box_fragment = fragment_layout_fn(&mut new); + new.layout_positioned_fragment_children(layout_context, &mut positioned_box_fragment); + *for_nearest_containing_block_for_all_descendants = + new.for_nearest_containing_block_for_all_descendants; positioned_box_fragment } + /// Given `fragment_layout_fn`, a closure which lays out a fragment in a provided + /// `PositioningContext`, create a positioning context for a fragment that establishes a + /// containing block for all descendants and lay out the fragment and all its children using + /// the new positioning context. Returns the resulting `BoxFragment`. + fn layout_containing_block_for_all_descendants( + layout_context: &LayoutContext, + fragment_layout_fn: impl FnOnce(&mut Self) -> BoxFragment, + ) -> BoxFragment { + let mut containing_block_for_all_descendants = + Self::new_for_containing_block_for_all_descendants(); + debug_assert!(containing_block_for_all_descendants + .for_nearest_positioned_ancestor + .is_none()); + + let mut new_fragment = fragment_layout_fn(&mut containing_block_for_all_descendants); + + let padding_rect = Rect { + size: new_fragment.content_rect.size.clone(), + // Ignore the content rect’s position in its own containing block: + start_corner: Vec2::zero(), + } + .inflate(&new_fragment.padding); + let containing_block = DefiniteContainingBlock { + size: padding_rect.size.clone(), + style: &new_fragment.style, + }; + + // Loop because it’s possible that we discover (the static position of) + // more absolutely-positioned boxes while doing layout for others. + let mut new_child_fragments = Vec::new(); + while !containing_block_for_all_descendants + .for_nearest_containing_block_for_all_descendants + .is_empty() + { + HoistedAbsolutelyPositionedBox::layout_many( + layout_context, + &std::mem::take( + &mut containing_block_for_all_descendants + .for_nearest_containing_block_for_all_descendants, + ), + &mut new_child_fragments, + &mut containing_block_for_all_descendants + .for_nearest_containing_block_for_all_descendants, + &containing_block, + ) + } + + new_fragment + .children + .push(Fragment::Anonymous(AnonymousFragment::new( + padding_rect, + new_child_fragments, + new_fragment.style.writing_mode, + ))); + + new_fragment + } + pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox<'box_tree>) { if let Some(nearest) = &mut self.for_nearest_positioned_ancestor { match box_ @@ -196,13 +297,14 @@ impl<'box_tree> PositioningContext<'box_tree> { Position::Static | Position::Relative => unreachable!(), } } - self.for_initial_containing_block.push(box_) + self.for_nearest_containing_block_for_all_descendants + .push(box_) } pub(crate) fn append(&mut self, other: Self) { vec_append_owned( - &mut self.for_initial_containing_block, - other.for_initial_containing_block, + &mut self.for_nearest_containing_block_for_all_descendants, + other.for_nearest_containing_block_for_all_descendants, ); match ( self.for_nearest_positioned_ancestor.as_mut(), @@ -219,7 +321,8 @@ impl<'box_tree> PositioningContext<'box_tree> { tree_rank_in_parent: usize, f: impl FnOnce(&mut Self) -> Vec<Fragment>, ) -> Vec<Fragment> { - let for_icb_so_far = self.for_initial_containing_block.len(); + let for_containing_block_for_all_descendants = + self.for_nearest_containing_block_for_all_descendants.len(); let for_nearest_so_far = self .for_nearest_positioned_ancestor .as_ref() @@ -228,7 +331,8 @@ impl<'box_tree> PositioningContext<'box_tree> { let fragments = f(self); adjust_static_positions( - &mut self.for_initial_containing_block[for_icb_so_far..], + &mut self.for_nearest_containing_block_for_all_descendants + [for_containing_block_for_all_descendants..], &fragments, tree_rank_in_parent, ); @@ -242,7 +346,7 @@ impl<'box_tree> PositioningContext<'box_tree> { fragments } - pub(crate) fn layout_in_initial_containing_block( + pub(crate) fn layout_initial_containing_block_children( &mut self, layout_context: &LayoutContext, initial_containing_block: &DefiniteContainingBlock, @@ -252,18 +356,21 @@ impl<'box_tree> PositioningContext<'box_tree> { // Loop because it’s possible that we discover (the static position of) // more absolutely-positioned boxes while doing layout for others. - while !self.for_initial_containing_block.is_empty() { + while !self + .for_nearest_containing_block_for_all_descendants + .is_empty() + { HoistedAbsolutelyPositionedBox::layout_many( layout_context, - &std::mem::take(&mut self.for_initial_containing_block), + &std::mem::take(&mut self.for_nearest_containing_block_for_all_descendants), fragments, - &mut self.for_initial_containing_block, + &mut self.for_nearest_containing_block_for_all_descendants, initial_containing_block, ) } } - fn layout_in_positioned_ancestor( + fn layout_positioned_fragment_children( &mut self, layout_context: &LayoutContext, positioned_box_fragment: &mut BoxFragment, @@ -285,7 +392,7 @@ impl<'box_tree> PositioningContext<'box_tree> { layout_context, &for_here, &mut children, - &mut self.for_initial_containing_block, + &mut self.for_nearest_containing_block_for_all_descendants, &containing_block, ); positioned_box_fragment @@ -304,16 +411,18 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> { layout_context: &LayoutContext, boxes: &[Self], fragments: &mut Vec<Fragment>, - for_initial_containing_block: &mut Vec<HoistedAbsolutelyPositionedBox<'box_tree>>, + for_nearest_containing_block_for_all_descendants: &mut Vec< + HoistedAbsolutelyPositionedBox<'box_tree>, + >, containing_block: &DefiniteContainingBlock, ) { if layout_context.use_rayon { fragments.par_extend(boxes.par_iter().mapfold_reduce_into( - for_initial_containing_block, - |for_initial_containing_block, box_| { + for_nearest_containing_block_for_all_descendants, + |for_nearest_containing_block_for_all_descendants, box_| { Fragment::Box(box_.layout( layout_context, - for_initial_containing_block, + for_nearest_containing_block_for_all_descendants, containing_block, )) }, @@ -324,7 +433,7 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> { fragments.extend(boxes.iter().map(|box_| { Fragment::Box(box_.layout( layout_context, - for_initial_containing_block, + for_nearest_containing_block_for_all_descendants, containing_block, )) })) @@ -334,7 +443,9 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> { pub(crate) fn layout( &self, layout_context: &LayoutContext, - for_initial_containing_block: &mut Vec<HoistedAbsolutelyPositionedBox<'box_tree>>, + for_nearest_containing_block_for_all_descendants: &mut Vec< + HoistedAbsolutelyPositionedBox<'box_tree>, + >, containing_block: &DefiniteContainingBlock, ) -> BoxFragment { let style = &self.absolutely_positioned_box.contents.style; @@ -396,91 +507,101 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> { block_end: block_axis.margin_end, }; - let for_icb = for_initial_containing_block; - PositioningContext::for_positioned(layout_context, for_icb, |positioning_context| { - let size; - let fragments; - match self.absolutely_positioned_box.contents.as_replaced() { - Ok(replaced) => { - // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width - // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height - let style = &self.absolutely_positioned_box.contents.style; - size = replaced_used_size.unwrap(); - fragments = replaced.make_fragments(style, size.clone()); - }, - Err(non_replaced) => { - // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width - // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height - let inline_size = inline_axis.size.auto_is(|| { - let available_size = match inline_axis.anchor { - Anchor::Start(start) => { - cbis - start - pb.inline_sum() - margin.inline_sum() - }, - Anchor::End(end) => cbis - end - pb.inline_sum() - margin.inline_sum(), + let for_containing_block_for_all_descendants = + for_nearest_containing_block_for_all_descendants; + PositioningContext::create_and_layout_positioned( + layout_context, + style, + for_containing_block_for_all_descendants, + |positioning_context| { + let size; + let fragments; + match self.absolutely_positioned_box.contents.as_replaced() { + Ok(replaced) => { + // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width + // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height + let style = &self.absolutely_positioned_box.contents.style; + size = replaced_used_size.unwrap(); + fragments = replaced.make_fragments(style, size.clone()); + }, + Err(non_replaced) => { + // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width + // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height + let inline_size = inline_axis.size.auto_is(|| { + let available_size = match inline_axis.anchor { + Anchor::Start(start) => { + cbis - start - pb.inline_sum() - margin.inline_sum() + }, + Anchor::End(end) => { + cbis - end - pb.inline_sum() - margin.inline_sum() + }, + }; + self.absolutely_positioned_box + .contents + .content_sizes + .shrink_to_fit(available_size) + }); + + let containing_block_for_children = ContainingBlock { + inline_size, + block_size: block_axis.size, + style, }; - self.absolutely_positioned_box - .contents - .content_sizes - .shrink_to_fit(available_size) - }); - - let containing_block_for_children = ContainingBlock { - inline_size, - block_size: block_axis.size, - style, - }; - // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows - assert_eq!( - containing_block.style.writing_mode, - containing_block_for_children.style.writing_mode, - "Mixed writing modes are not supported yet" - ); - let dummy_tree_rank = 0; - let independent_layout = non_replaced.layout( - layout_context, - positioning_context, - &containing_block_for_children, - dummy_tree_rank, - ); - - size = Vec2 { - inline: inline_size, - block: block_axis - .size - .auto_is(|| independent_layout.content_block_size), - }; - fragments = independent_layout.fragments - }, - }; + // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows + assert_eq!( + containing_block.style.writing_mode, + containing_block_for_children.style.writing_mode, + "Mixed writing modes are not supported yet" + ); + let dummy_tree_rank = 0; + let independent_layout = non_replaced.layout( + layout_context, + positioning_context, + &containing_block_for_children, + dummy_tree_rank, + ); + + size = Vec2 { + inline: inline_size, + block: block_axis + .size + .auto_is(|| independent_layout.content_block_size), + }; + fragments = independent_layout.fragments + }, + }; - let inline_start = match inline_axis.anchor { - Anchor::Start(start) => start + pb.inline_start + margin.inline_start, - Anchor::End(end) => cbis - end - pb.inline_end - margin.inline_end - size.inline, - }; - let block_start = match block_axis.anchor { - Anchor::Start(start) => start + pb.block_start + margin.block_start, - Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - size.block, - }; + let inline_start = match inline_axis.anchor { + Anchor::Start(start) => start + pb.inline_start + margin.inline_start, + Anchor::End(end) => { + cbis - end - pb.inline_end - margin.inline_end - size.inline + }, + }; + let block_start = match block_axis.anchor { + Anchor::Start(start) => start + pb.block_start + margin.block_start, + Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - size.block, + }; - let content_rect = Rect { - start_corner: Vec2 { - inline: inline_start, - block: block_start, - }, - size, - }; + let content_rect = Rect { + start_corner: Vec2 { + inline: inline_start, + block: block_start, + }, + size, + }; - BoxFragment::new( - self.absolutely_positioned_box.contents.tag, - style.clone(), - fragments, - content_rect, - padding, - border, - margin, - CollapsedBlockMargins::zero(), - ) - }) + BoxFragment::new( + self.absolutely_positioned_box.contents.tag, + style.clone(), + fragments, + content_rect, + padding, + border, + margin, + CollapsedBlockMargins::zero(), + ) + }, + ) } } diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index 30b384f3884..44245e2c89d 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -3,9 +3,13 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::geom::{flow_relative, PhysicalSides, PhysicalSize}; +use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode; +use style::computed_values::position::T as ComputedPosition; +use style::computed_values::transform_style::T as ComputedTransformStyle; use style::properties::ComputedValues; use style::values::computed::{Length, LengthPercentage, LengthPercentageOrAuto}; use style::values::computed::{NonNegativeLengthPercentage, Size}; +use style::values::generics::box_::Perspective; use style::values::generics::length::MaxSize; use style::values::specified::box_ as stylo; @@ -49,6 +53,10 @@ pub(crate) trait ComputedValuesExt { fn padding(&self) -> flow_relative::Sides<LengthPercentage>; fn border_width(&self) -> flow_relative::Sides<Length>; fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto>; + fn has_transform_or_perspective(&self) -> bool; + fn effective_z_index(&self) -> i32; + fn establishes_stacking_context(&self) -> bool; + fn establishes_containing_block_for_all_descendants(&self) -> bool; } impl ComputedValuesExt for ComputedValues { @@ -165,6 +173,80 @@ impl ComputedValuesExt for ComputedValues { self.writing_mode, ) } + + /// Returns true if this style has a transform, or perspective property set. + fn has_transform_or_perspective(&self) -> bool { + !self.get_box().transform.0.is_empty() || self.get_box().perspective != Perspective::None + } + + /// Get the effective z-index of this fragment. Z-indices only apply to positioned elements + /// per CSS 2 9.9.1 (http://www.w3.org/TR/CSS2/visuren.html#z-index), so this value may differ + /// from the value specified in the style. + fn effective_z_index(&self) -> i32 { + match self.get_box().position { + ComputedPosition::Static => 0, + _ => self.get_position().z_index.integer_or(0), + } + } + + /// Returns true if this fragment establishes a new stacking context and false otherwise. + fn establishes_stacking_context(&self) -> bool { + let effects = self.get_effects(); + if effects.opacity != 1.0 { + return true; + } + + if effects.mix_blend_mode != ComputedMixBlendMode::Normal { + return true; + } + + if self.has_transform_or_perspective() { + return true; + } + + if !self.get_effects().filter.0.is_empty() { + return true; + } + + if self.get_box().transform_style == ComputedTransformStyle::Preserve3d || + self.overrides_transform_style() + { + return true; + } + + // Fixed position and sticky position always create stacking contexts. + // TODO(mrobinson): We need to handle sticky positioning here when we support it. + if self.get_box().position == ComputedPosition::Fixed { + return true; + } + + // Statically positioned fragments don't establish stacking contexts if the previous + // conditions are not fulfilled. Furthermore, z-index doesn't apply to statically + // positioned fragments. + if self.get_box().position == ComputedPosition::Static { + return false; + } + + // For absolutely and relatively positioned fragments we only establish a stacking + // context if there is a z-index set. + // See https://www.w3.org/TR/CSS2/visuren.html#z-index + !self.get_position().z_index.is_auto() + } + + /// Returns true if this style establishes a containing block for all descendants + /// including fixed and absolutely positioned ones. + fn establishes_containing_block_for_all_descendants(&self) -> bool { + if self.has_transform_or_perspective() { + return true; + } + + if !self.get_effects().filter.0.is_empty() { + return true; + } + + // TODO: We need to handle CSS Contain here. + false + } } impl From<stylo::Display> for Display { diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index ce1487d5fa6..7f56c3b2f15 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -2632,35 +2632,6 @@ class CGConstructorEnabled(CGAbstractMethod): return CGList((CGGeneric(cond) for cond in conditions), " &&\n") -def CreateBindingJSObject(descriptor): - assert not descriptor.isGlobal() - create = "let raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n" - if descriptor.proxy: - create += """ -let handler = RegisterBindings::PROXY_HANDLERS[PrototypeList::Proxies::%s as usize]; -rooted!(in(*cx) let private = PrivateValue(raw as *const libc::c_void)); -let obj = NewProxyObject(*cx, handler, - Handle::from_raw(UndefinedHandleValue), - proto.get()); -assert!(!obj.is_null()); -SetProxyReservedSlot(obj, 0, &private.get()); -rooted!(in(*cx) let obj = obj);\ -""" % (descriptor.name) - else: - create += ("rooted!(in(*cx) let obj = JS_NewObjectWithGivenProto(\n" - " *cx, &Class.base as *const JSClass, proto.handle()));\n" - "assert!(!obj.is_null());\n" - "\n" - "let val = PrivateValue(raw as *const libc::c_void);\n" - "\n" - "JS_SetReservedSlot(obj.get(), DOM_OBJECT_SLOT, &val);") - if descriptor.weakReferenceable: - create += """ -let val = PrivateValue(ptr::null()); -JS_SetReservedSlot(obj.get(), DOM_WEAK_SLOT, &val);""" - return create - - def InitUnforgeablePropertiesOnHolder(descriptor, properties): """ Define the unforgeable properties on the unforgeable holder for @@ -2738,23 +2709,62 @@ class CGWrapMethod(CGAbstractMethod): def definition_body(self): unforgeable = CopyUnforgeablePropertiesToInstance(self.descriptor) - create = CreateBindingJSObject(self.descriptor) + if self.descriptor.proxy: + create = """ +let handler = RegisterBindings::PROXY_HANDLERS[PrototypeList::Proxies::%(concreteType)s as usize]; +rooted!(in(*cx) let obj = NewProxyObject( + *cx, + handler, + Handle::from_raw(UndefinedHandleValue), + proto.get(), +)); +assert!(!obj.is_null()); +SetProxyReservedSlot( + obj.get(), + 0, + &PrivateValue(&*raw as *const %(concreteType)s as *const libc::c_void), +); +""" + else: + create = """ +rooted!(in(*cx) let obj = JS_NewObjectWithGivenProto( + *cx, + &Class.base, + proto.handle(), +)); +assert!(!obj.is_null()); +JS_SetReservedSlot( + obj.get(), + DOM_OBJECT_SLOT, + &PrivateValue(&*raw as *const %(concreteType)s as *const libc::c_void), +); +""" + create = create % {"concreteType": self.descriptor.concreteType} + if self.descriptor.weakReferenceable: + create += """ +let val = PrivateValue(ptr::null()); +JS_SetReservedSlot(obj.get(), DOM_WEAK_SLOT, &val); +""" + return CGGeneric("""\ +let raw = Root::new(MaybeUnreflectedDom::from_box(object)); + let scope = scope.reflector().get_jsobject(); assert!(!scope.get().is_null()); assert!(((*get_object_class(scope.get())).flags & JSCLASS_IS_GLOBAL) != 0); +let _ac = JSAutoRealm::new(*cx, scope.get()); rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>()); -let _ac = JSAutoRealm::new(*cx, scope.get()); GetProtoObject(cx, scope, proto.handle_mut()); assert!(!proto.is_null()); %(createObject)s +raw.init_reflector(obj.get()); %(copyUnforgeable)s -(*raw).init_reflector(obj.get()); -DomRoot::from_ref(&*raw)""" % {'copyUnforgeable': unforgeable, 'createObject': create}) +DomRoot::from_ref(&*raw)\ +""" % {'copyUnforgeable': unforgeable, 'createObject': create}) class CGWrapGlobalMethod(CGAbstractMethod): @@ -2773,6 +2783,7 @@ class CGWrapGlobalMethod(CGAbstractMethod): def definition_body(self): values = { + "concreteType": self.descriptor.concreteType, "unforgeable": CopyUnforgeablePropertiesToInstance(self.descriptor) } @@ -2786,19 +2797,18 @@ class CGWrapGlobalMethod(CGAbstractMethod): values["members"] = "\n".join(members) return CGGeneric("""\ -let raw = Box::into_raw(object); -let _rt = RootedTraceable::new(&*raw); +let raw = Root::new(MaybeUnreflectedDom::from_box(object)); rooted!(in(*cx) let mut obj = ptr::null_mut::<JSObject>()); create_global_object( cx, &Class.base, - raw as *const libc::c_void, + &*raw as *const %(concreteType)s as *const libc::c_void, _trace, obj.handle_mut()); assert!(!obj.is_null()); -(*raw).init_reflector(obj.get()); +raw.init_reflector(obj.get()); let _ac = JSAutoRealm::new(*cx, obj.get()); rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>()); @@ -6060,8 +6070,10 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries 'crate::dom::bindings::reflector::DomObject', 'crate::dom::bindings::root::Dom', 'crate::dom::bindings::root::DomRoot', - 'crate::dom::bindings::root::OptionalHeapSetter', 'crate::dom::bindings::root::DomSlice', + 'crate::dom::bindings::root::MaybeUnreflectedDom', + 'crate::dom::bindings::root::OptionalHeapSetter', + 'crate::dom::bindings::root::Root', 'crate::dom::bindings::utils::AsVoidPtr', 'crate::dom::bindings::utils::DOMClass', 'crate::dom::bindings::utils::DOMJSClass', @@ -6086,7 +6098,6 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries 'crate::dom::bindings::utils::set_dictionary_property', 'crate::dom::bindings::utils::trace_global', 'crate::dom::bindings::trace::JSTraceable', - 'crate::dom::bindings::trace::RootedTraceable', 'crate::dom::bindings::trace::RootedTraceableBox', 'crate::dom::bindings::callback::CallSetup', 'crate::dom::bindings::callback::CallbackContainer', diff --git a/components/script/dom/bindings/reflector.rs b/components/script/dom/bindings/reflector.rs index 2b5a4987eb5..78635b2be31 100644 --- a/components/script/dom/bindings/reflector.rs +++ b/components/script/dom/bindings/reflector.rs @@ -6,6 +6,7 @@ use crate::dom::bindings::conversions::DerivedFrom; use crate::dom::bindings::root::DomRoot; +use crate::dom::bindings::trace::JSTraceable; use crate::dom::globalscope::GlobalScope; use crate::script_runtime::JSContext; use js::jsapi::{Heap, JSObject}; @@ -53,7 +54,7 @@ impl Reflector { } /// Initialize the reflector. (May be called only once.) - pub fn set_jsobject(&mut self, object: *mut JSObject) { + pub unsafe fn set_jsobject(&self, object: *mut JSObject) { assert!(self.object.get().is_null()); assert!(!object.is_null()); self.object.set(object); @@ -75,7 +76,7 @@ impl Reflector { } /// A trait to provide access to the `Reflector` for a DOM object. -pub trait DomObject: 'static { +pub trait DomObject: JSTraceable + 'static { /// Returns the receiver's reflector. fn reflector(&self) -> &Reflector; @@ -97,11 +98,11 @@ impl DomObject for Reflector { /// A trait to initialize the `Reflector` for a DOM object. pub trait MutDomObject: DomObject { /// Initializes the Reflector - fn init_reflector(&mut self, obj: *mut JSObject); + unsafe fn init_reflector(&self, obj: *mut JSObject); } impl MutDomObject for Reflector { - fn init_reflector(&mut self, obj: *mut JSObject) { + unsafe fn init_reflector(&self, obj: *mut JSObject) { self.set_jsobject(obj) } } diff --git a/components/script/dom/bindings/root.rs b/components/script/dom/bindings/root.rs index 19df89df53f..1fea453e35a 100644 --- a/components/script/dom/bindings/root.rs +++ b/components/script/dom/bindings/root.rs @@ -62,7 +62,7 @@ where /// It cannot outlive its associated `RootCollection`, and it gives /// out references which cannot outlive this new `Root`. #[allow(unrooted_must_root)] - unsafe fn new(value: T) -> Self { + pub unsafe fn new(value: T) -> Self { debug_assert!(thread_state::get().is_script()); STACK_ROOTS.with(|ref root_list| { let root_list = &*root_list.get().unwrap(); @@ -99,6 +99,32 @@ where } } +unsafe impl<T> StableTraceObject for MaybeUnreflectedDom<T> +where + T: DomObject, +{ + fn stable_trace_object<'a>(&'a self) -> *const dyn JSTraceable { + // The JSTraceable impl for Reflector doesn't actually do anything, + // so we need this shenanigan to actually trace the reflector of the + // T pointer in Dom<T>. + #[allow(unrooted_must_root)] + struct MaybeUnreflectedStackRoot<T>(T); + unsafe impl<T> JSTraceable for MaybeUnreflectedStackRoot<T> + where + T: DomObject, + { + unsafe fn trace(&self, tracer: *mut JSTracer) { + if self.0.reflector().get_jsobject().is_null() { + self.0.trace(tracer); + } else { + trace_reflector(tracer, "on stack", &self.0.reflector()); + } + } + } + unsafe { &*(self.ptr.as_ptr() as *const T as *const MaybeUnreflectedStackRoot<T>) } + } +} + impl<T> Deref for Root<T> where T: Deref + StableTraceObject, @@ -341,6 +367,36 @@ unsafe impl<T: DomObject> JSTraceable for Dom<T> { } } +/// A traced reference to a DOM object that may not be reflected yet. +#[unrooted_must_root_lint::must_root] +pub struct MaybeUnreflectedDom<T> { + ptr: ptr::NonNull<T>, +} + +impl<T> MaybeUnreflectedDom<T> +where + T: DomObject, +{ + #[allow(unrooted_must_root)] + pub unsafe fn from_box(value: Box<T>) -> Self { + Self { + ptr: Box::into_raw_non_null(value), + } + } +} + +impl<T> Deref for MaybeUnreflectedDom<T> +where + T: DomObject, +{ + type Target = T; + + fn deref(&self) -> &T { + debug_assert!(thread_state::get().is_script()); + unsafe { &*self.ptr.as_ptr() } + } +} + /// An unrooted reference to a DOM object for use in layout. `Layout*Helpers` /// traits must be implemented on this. #[unrooted_must_root_lint::allow_unrooted_interior] diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 5e99e78d03d..631731e39a6 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -918,35 +918,6 @@ impl RootedTraceableSet { /// If you have GC things like *mut JSObject or JSVal, use rooted!. /// If you have an arbitrary number of DomObjects to root, use rooted_vec!. /// If you know what you're doing, use this. -#[derive(JSTraceable)] -pub struct RootedTraceable<'a, T: 'static + JSTraceable> { - ptr: &'a T, -} - -impl<'a, T: JSTraceable + 'static> RootedTraceable<'a, T> { - /// DomRoot a JSTraceable thing for the life of this RootedTraceable - pub fn new(traceable: &'a T) -> RootedTraceable<'a, T> { - unsafe { - RootedTraceableSet::add(traceable); - } - RootedTraceable { ptr: traceable } - } -} - -impl<'a, T: JSTraceable + 'static> Drop for RootedTraceable<'a, T> { - fn drop(&mut self) { - unsafe { - RootedTraceableSet::remove(self.ptr); - } - } -} - -/// Roots any JSTraceable thing -/// -/// If you have a valid DomObject, use DomRoot. -/// If you have GC things like *mut JSObject or JSVal, use rooted!. -/// If you have an arbitrary number of DomObjects to root, use rooted_vec!. -/// If you know what you're doing, use this. #[unrooted_must_root_lint::allow_unrooted_interior] pub struct RootedTraceableBox<T: 'static + JSTraceable> { ptr: *mut T, @@ -959,12 +930,12 @@ unsafe impl<T: JSTraceable + 'static> JSTraceable for RootedTraceableBox<T> { } impl<T: JSTraceable + 'static> RootedTraceableBox<T> { - /// DomRoot a JSTraceable thing for the life of this RootedTraceable + /// DomRoot a JSTraceable thing for the life of this RootedTraceableBox pub fn new(traceable: T) -> RootedTraceableBox<T> { Self::from_box(Box::new(traceable)) } - /// Consumes a boxed JSTraceable and roots it for the life of this RootedTraceable. + /// Consumes a boxed JSTraceable and roots it for the life of this RootedTraceableBox. pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> { let traceable = Box::into_raw(boxed_traceable); unsafe { diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index f3671a5057f..37baedcc663 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -109,8 +109,8 @@ impl Promise { reflector: Reflector::new(), permanent_js_root: Heap::default(), }; - let mut promise = Rc::new(promise); - Rc::get_mut(&mut promise).unwrap().init_reflector(obj.get()); + let promise = Rc::new(promise); + promise.init_reflector(obj.get()); promise.initialize(cx); promise } diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs index 8abbbb480d6..4155d3626a2 100644 --- a/components/script/dom/windowproxy.rs +++ b/components/script/dom/windowproxy.rs @@ -166,7 +166,7 @@ impl WindowProxy { // Create a new browsing context. let current = Some(window.global().pipeline_id()); - let mut window_proxy = Box::new(WindowProxy::new_inherited( + let window_proxy = Box::new(WindowProxy::new_inherited( browsing_context_id, top_level_browsing_context_id, current, @@ -212,7 +212,7 @@ impl WindowProxy { let cx = global_to_clone_from.get_cx(); // Create a new browsing context. - let mut window_proxy = Box::new(WindowProxy::new_inherited( + let window_proxy = Box::new(WindowProxy::new_inherited( browsing_context_id, top_level_browsing_context_id, None, diff --git a/components/script/lib.rs b/components/script/lib.rs index c01fd6dbd60..1a3ba6a2557 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#![feature(box_into_raw_non_null)] #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(drain_filter)] diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/preserve3d-button.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/preserve3d-button.html.ini deleted file mode 100644 index 0c6784a80ed..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/preserve3d-button.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[preserve3d-button.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-001.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-001.html.ini deleted file mode 100644 index a99bde1ab74..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-abspos-001.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-002.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-002.html.ini deleted file mode 100644 index 55e530b062c..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-abspos-002.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-003.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-003.html.ini deleted file mode 100644 index 80712e40569..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-003.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-abspos-003.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-004.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-004.html.ini deleted file mode 100644 index 3196c91458d..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-004.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-abspos-004.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-006.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-006.html.ini deleted file mode 100644 index 45970f93d38..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-006.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-abspos-006.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-007.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-007.html.ini deleted file mode 100644 index 8bccac28610..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-007.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform-abspos-007.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/filter-effects/filtered-inline-is-container.html.ini b/tests/wpt/metadata-layout-2020/css/filter-effects/filtered-inline-is-container.html.ini new file mode 100644 index 00000000000..b41a8df9ac0 --- /dev/null +++ b/tests/wpt/metadata-layout-2020/css/filter-effects/filtered-inline-is-container.html.ini @@ -0,0 +1,2 @@ +[filtered-inline-is-container.html] + expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/transform_stacking_context_a.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/transform_stacking_context_a.html.ini deleted file mode 100644 index 18d0ddfbd1f..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/transform_stacking_context_a.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform_stacking_context_a.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/translate_clip_nested.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/translate_clip_nested.html.ini deleted file mode 100644 index 2c1f8cb35d9..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/translate_clip_nested.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[translate_clip_nested.html] - expected: FAIL |