Detach shadow clean up

This commit is contained in:
Fernando Jiménez Moreno 2019-06-11 15:48:36 +02:00
parent f8ae394cad
commit 1f3c879a85
5 changed files with 76 additions and 63 deletions

View file

@ -189,7 +189,9 @@ impl<'lr> TShadowRoot for ServoShadowRoot<'lr> {
} }
fn host(&self) -> ServoLayoutElement<'lr> { fn host(&self) -> ServoLayoutElement<'lr> {
ServoLayoutElement::from_layout_js(unsafe { self.shadow_root.get_host_for_layout() }) ServoLayoutElement::from_layout_js(unsafe {
self.shadow_root.get_host_for_layout().unwrap()
})
} }
fn style_data<'a>(&self) -> Option<&'a CascadeData> fn style_data<'a>(&self) -> Option<&'a CascadeData>

View file

@ -491,7 +491,7 @@ impl Element {
self.ensure_rare_data().shadow_root = Some(Dom::from_ref(&*shadow_root)); self.ensure_rare_data().shadow_root = Some(Dom::from_ref(&*shadow_root));
shadow_root shadow_root
.upcast::<Node>() .upcast::<Node>()
.set_containing_shadow_root(&shadow_root); .set_containing_shadow_root(Some(&shadow_root));
if self.is_connected() { if self.is_connected() {
self.node.owner_doc().register_shadow_root(&*shadow_root); self.node.owner_doc().register_shadow_root(&*shadow_root);
@ -504,6 +504,7 @@ impl Element {
pub fn detach_shadow(&self) { pub fn detach_shadow(&self) {
if let Some(ref shadow_root) = self.shadow_root() { if let Some(ref shadow_root) = self.shadow_root() {
shadow_root.detach();
self.node.owner_doc().unregister_shadow_root(shadow_root); self.node.owner_doc().unregister_shadow_root(shadow_root);
self.ensure_rare_data().shadow_root = None; self.ensure_rare_data().shadow_root = None;
} else { } else {

View file

@ -1737,7 +1737,7 @@ impl HTMLMediaElement {
// if we are already showing the controls. // if we are already showing the controls.
return; return;
} }
if let Ok(shadow_root) = element.attach_shadow(IsUserAgentWidget::Yes) { let shadow_root = element.attach_shadow(IsUserAgentWidget::Yes).unwrap();
let document = document_from_node(self); let document = document_from_node(self);
let script = HTMLScriptElement::new( let script = HTMLScriptElement::new(
local_name!("script"), local_name!("script"),
@ -1745,8 +1745,7 @@ impl HTMLMediaElement {
&document, &document,
ElementCreator::ScriptCreated, ElementCreator::ScriptCreated,
); );
let mut media_controls_script = let mut media_controls_script = resources::read_string(EmbedderResource::MediaControlsJS);
resources::read_string(EmbedderResource::MediaControlsJS);
// This is our hacky way to temporarily workaround the lack of a privileged // This is our hacky way to temporarily workaround the lack of a privileged
// JS context. // JS context.
// The media controls UI accesses the document.servoGetMediaControls(id) API // The media controls UI accesses the document.servoGetMediaControls(id) API
@ -1786,7 +1785,6 @@ impl HTMLMediaElement {
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
} }
}
fn remove_controls(&self) { fn remove_controls(&self) {
if let Some(ref id) = *self.media_controls_id.borrow() { if let Some(ref id) = *self.media_controls_id.borrow() {

View file

@ -283,7 +283,7 @@ impl Node {
for node in new_child.traverse_preorder(ShadowIncluding::No) { for node in new_child.traverse_preorder(ShadowIncluding::No) {
if parent_in_shadow_tree { if parent_in_shadow_tree {
if let Some(shadow_root) = self.containing_shadow_root() { if let Some(shadow_root) = self.containing_shadow_root() {
node.set_containing_shadow_root(&*shadow_root); node.set_containing_shadow_root(Some(&*shadow_root));
} }
debug_assert!(node.containing_shadow_root().is_some()); debug_assert!(node.containing_shadow_root().is_some());
} }
@ -961,8 +961,8 @@ impl Node {
.map(|sr| DomRoot::from_ref(&**sr)) .map(|sr| DomRoot::from_ref(&**sr))
} }
pub fn set_containing_shadow_root(&self, shadow_root: &ShadowRoot) { pub fn set_containing_shadow_root(&self, shadow_root: Option<&ShadowRoot>) {
self.ensure_rare_data().containing_shadow_root = Some(Dom::from_ref(shadow_root)); self.ensure_rare_data().containing_shadow_root = shadow_root.map(|sr| Dom::from_ref(sr));
} }
pub fn is_in_html_doc(&self) -> bool { pub fn is_in_html_doc(&self) -> bool {
@ -1241,7 +1241,7 @@ impl LayoutNodeHelpers for LayoutDom<Node> {
let parent = (*self.unsafe_get()).parent_node.get_inner_as_layout(); let parent = (*self.unsafe_get()).parent_node.get_inner_as_layout();
if let Some(ref 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 shadow_root.get_host_for_layout().map(|h| h.upcast());
} }
} }
parent parent

View file

@ -41,7 +41,7 @@ pub struct ShadowRoot {
document_fragment: DocumentFragment, document_fragment: DocumentFragment,
document_or_shadow_root: DocumentOrShadowRoot, document_or_shadow_root: DocumentOrShadowRoot,
document: Dom<Document>, document: Dom<Document>,
host: Dom<Element>, host: MutNullableDom<Element>,
/// List of author styles associated with nodes in this shadow tree. /// List of author styles associated with nodes in this shadow tree.
author_styles: DomRefCell<AuthorStyles<StyleSheetInDocument>>, author_styles: DomRefCell<AuthorStyles<StyleSheetInDocument>>,
stylesheet_list: MutNullableDom<StyleSheetList>, stylesheet_list: MutNullableDom<StyleSheetList>,
@ -62,7 +62,7 @@ impl ShadowRoot {
document_fragment, document_fragment,
document_or_shadow_root: DocumentOrShadowRoot::new(document.window()), document_or_shadow_root: DocumentOrShadowRoot::new(document.window()),
document: Dom::from_ref(document), document: Dom::from_ref(document),
host: Dom::from_ref(host), host: MutNullableDom::new(Some(host)),
author_styles: DomRefCell::new(AuthorStyles::new()), author_styles: DomRefCell::new(AuthorStyles::new()),
stylesheet_list: MutNullableDom::new(None), stylesheet_list: MutNullableDom::new(None),
window: Dom::from_ref(document.window()), window: Dom::from_ref(document.window()),
@ -77,6 +77,16 @@ impl ShadowRoot {
) )
} }
pub fn detach(&self) {
self.host.set(None);
let node = self.upcast::<Node>();
node.set_containing_shadow_root(None);
node.set_flag(NodeFlags::IS_CONNECTED, false);
for child in node.traverse_preorder(ShadowIncluding::No) {
child.set_flag(NodeFlags::IS_CONNECTED, false);
}
}
pub fn get_focused_element(&self) -> Option<DomRoot<Element>> { pub fn get_focused_element(&self) -> Option<DomRoot<Element>> {
//XXX get retargeted focused element //XXX get retargeted focused element
None None
@ -130,9 +140,9 @@ impl ShadowRoot {
self.document.invalidate_shadow_roots_stylesheets(); self.document.invalidate_shadow_roots_stylesheets();
self.author_styles.borrow_mut().stylesheets.force_dirty(); self.author_styles.borrow_mut().stylesheets.force_dirty();
// Mark the host element dirty so a reflow will be performed. // Mark the host element dirty so a reflow will be performed.
self.host if let Some(host) = self.host.get() {
.upcast::<Node>() host.upcast::<Node>().dirty(NodeDamage::NodeStyleDamaged);
.dirty(NodeDamage::NodeStyleDamaged); }
} }
/// Remove any existing association between the provided id and any elements /// Remove any existing association between the provided id and any elements
@ -216,7 +226,9 @@ impl ShadowRootMethods for ShadowRoot {
/// https://dom.spec.whatwg.org/#dom-shadowroot-host /// https://dom.spec.whatwg.org/#dom-shadowroot-host
fn Host(&self) -> DomRoot<Element> { fn Host(&self) -> DomRoot<Element> {
DomRoot::from_ref(&self.host) let host = self.host.get();
debug_assert!(host.is_some());
host.unwrap()
} }
// https://drafts.csswg.org/cssom/#dom-document-stylesheets // https://drafts.csswg.org/cssom/#dom-document-stylesheets
@ -232,7 +244,7 @@ impl ShadowRootMethods for ShadowRoot {
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub trait LayoutShadowRootHelpers { pub trait LayoutShadowRootHelpers {
unsafe fn get_host_for_layout(&self) -> LayoutDom<Element>; unsafe fn get_host_for_layout(&self) -> Option<LayoutDom<Element>>;
unsafe fn get_style_data_for_layout<'a, E: TElement>( unsafe fn get_style_data_for_layout<'a, E: TElement>(
&self, &self,
) -> &'a AuthorStyles<StyleSheetInDocument>; ) -> &'a AuthorStyles<StyleSheetInDocument>;
@ -247,8 +259,8 @@ pub trait LayoutShadowRootHelpers {
impl LayoutShadowRootHelpers for LayoutDom<ShadowRoot> { impl LayoutShadowRootHelpers for LayoutDom<ShadowRoot> {
#[inline] #[inline]
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn get_host_for_layout(&self) -> LayoutDom<Element> { unsafe fn get_host_for_layout(&self) -> Option<LayoutDom<Element>> {
(*self.unsafe_get()).host.to_layout() (*self.unsafe_get()).host.get_inner_as_layout()
} }
#[inline] #[inline]