Make LayoutNodeHelpers::composed_parent_node_ref be safe

For clarity, I introduce <LayoutDom<Element>>::parent_node_ref to contain
the remaining unsafety bits out of composed_parent_node_ref which is more
complex than just a field access.
This commit is contained in:
Anthony Ramine 2020-03-31 22:32:35 +02:00
parent f712b0bcf8
commit fc07a5147c
4 changed files with 44 additions and 50 deletions

View file

@ -203,12 +203,10 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
type ConcreteShadowRoot = ServoShadowRoot<'ln>; type ConcreteShadowRoot = ServoShadowRoot<'ln>;
fn parent_node(&self) -> Option<Self> { fn parent_node(&self) -> Option<Self> {
unsafe {
self.node self.node
.composed_parent_node_ref() .composed_parent_node_ref()
.map(Self::from_layout_js) .map(Self::from_layout_js)
} }
}
fn first_child(&self) -> Option<Self> { fn first_child(&self) -> Option<Self> {
self.node.first_child_ref().map(Self::from_layout_js) self.node.first_child_ref().map(Self::from_layout_js)
@ -745,13 +743,11 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
} }
fn parent_element(&self) -> Option<ServoLayoutElement<'le>> { fn parent_element(&self) -> Option<ServoLayoutElement<'le>> {
unsafe {
self.element self.element
.upcast() .upcast()
.composed_parent_node_ref() .composed_parent_node_ref()
.and_then(as_element) .and_then(as_element)
} }
}
fn parent_node_is_shadow_root(&self) -> bool { fn parent_node_is_shadow_root(&self) -> bool {
match self.as_node().parent_node() { match self.as_node().parent_node() {

View file

@ -210,12 +210,10 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
type ConcreteShadowRoot = ServoShadowRoot<'ln>; type ConcreteShadowRoot = ServoShadowRoot<'ln>;
fn parent_node(&self) -> Option<Self> { fn parent_node(&self) -> Option<Self> {
unsafe {
self.node self.node
.composed_parent_node_ref() .composed_parent_node_ref()
.map(Self::from_layout_js) .map(Self::from_layout_js)
} }
}
fn first_child(&self) -> Option<Self> { fn first_child(&self) -> Option<Self> {
self.node.first_child_ref().map(Self::from_layout_js) self.node.first_child_ref().map(Self::from_layout_js)
@ -752,13 +750,11 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
} }
fn parent_element(&self) -> Option<ServoLayoutElement<'le>> { fn parent_element(&self) -> Option<ServoLayoutElement<'le>> {
unsafe {
self.element self.element
.upcast() .upcast()
.composed_parent_node_ref() .composed_parent_node_ref()
.and_then(as_element) .and_then(as_element)
} }
}
fn parent_node_is_shadow_root(&self) -> bool { fn parent_node_is_shadow_root(&self) -> bool {
match self.as_node().parent_node() { match self.as_node().parent_node() {

View file

@ -985,9 +985,7 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
unsafe { &(*self.unsafe_get()).namespace } unsafe { &(*self.unsafe_get()).namespace }
} }
#[allow(unsafe_code)]
fn get_lang_for_layout(self) -> String { fn get_lang_for_layout(self) -> String {
unsafe {
let mut current_node = Some(self.upcast::<Node>()); let mut current_node = Some(self.upcast::<Node>());
while let Some(node) = current_node { while let Some(node) = current_node {
current_node = node.composed_parent_node_ref(); current_node = node.composed_parent_node_ref();
@ -998,9 +996,7 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
{ {
return attr.to_owned(); return attr.to_owned();
} }
if let Some(attr) = if let Some(attr) = elem.get_attr_val_for_layout(&ns!(), &local_name!("lang")) {
elem.get_attr_val_for_layout(&ns!(), &local_name!("lang"))
{
return attr.to_owned(); return attr.to_owned();
} }
}, },
@ -1011,7 +1007,6 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
// TODO: Check HTTP Content-Language header // TODO: Check HTTP Content-Language header
String::new() String::new()
} }
}
#[inline] #[inline]
#[allow(unsafe_code)] #[allow(unsafe_code)]

View file

@ -1307,7 +1307,7 @@ pub unsafe fn from_untrusted_node_address(
pub trait LayoutNodeHelpers<'dom> { pub trait LayoutNodeHelpers<'dom> {
fn type_id_for_layout(self) -> NodeTypeId; fn type_id_for_layout(self) -> NodeTypeId;
unsafe fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>; fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>; fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>; fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>; fn prev_sibling_ref(self) -> Option<LayoutDom<'dom, Node>>;
@ -1339,6 +1339,14 @@ pub trait LayoutNodeHelpers<'dom> {
fn opaque(self) -> OpaqueNode; fn opaque(self) -> OpaqueNode;
} }
impl<'dom> LayoutDom<'dom, Node> {
#[inline]
#[allow(unsafe_code)]
fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
}
}
impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> { impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
#[inline] #[inline]
#[allow(unsafe_code)] #[allow(unsafe_code)]
@ -1352,10 +1360,9 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
} }
#[inline] #[inline]
#[allow(unsafe_code)] fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
unsafe fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> { let parent = self.parent_node_ref();
let parent = (*self.unsafe_get()).parent_node.get_inner_as_layout(); if let Some(parent) = parent {
if let Some(ref parent) = parent {
if let Some(shadow_root) = parent.downcast::<ShadowRoot>() { if let Some(shadow_root) = parent.downcast::<ShadowRoot>() {
return Some(shadow_root.get_host_for_layout().upcast()); return Some(shadow_root.get_host_for_layout().upcast());
} }