aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/domobject_derive/lib.rs2
-rw-r--r--components/layout_2020/display_list/mod.rs15
-rw-r--r--components/layout_2020/display_list/stacking_context.rs74
-rw-r--r--components/layout_2020/flow/mod.rs12
-rw-r--r--components/layout_2020/flow/root.rs5
-rw-r--r--components/layout_2020/positioned.rs363
-rw-r--r--components/layout_2020/style_ext.rs82
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py89
-rw-r--r--components/script/dom/bindings/reflector.rs9
-rw-r--r--components/script/dom/bindings/root.rs58
-rw-r--r--components/script/dom/bindings/trace.rs33
-rw-r--r--components/script/dom/promise.rs4
-rw-r--r--components/script/dom/windowproxy.rs4
-rw-r--r--components/script/lib.rs1
-rw-r--r--tests/wpt/metadata-layout-2020/css/css-transforms/preserve3d-button.html.ini2
-rw-r--r--tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-001.html.ini2
-rw-r--r--tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-002.html.ini2
-rw-r--r--tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-003.html.ini2
-rw-r--r--tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-004.html.ini2
-rw-r--r--tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-006.html.ini2
-rw-r--r--tests/wpt/metadata-layout-2020/css/css-transforms/transform-abspos-007.html.ini2
-rw-r--r--tests/wpt/metadata-layout-2020/css/filter-effects/filtered-inline-is-container.html.ini2
-rw-r--r--tests/wpt/mozilla/meta-layout-2020/css/transform_stacking_context_a.html.ini2
-rw-r--r--tests/wpt/mozilla/meta-layout-2020/css/translate_clip_nested.html.ini2
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