mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Detach shadow clean up
This commit is contained in:
parent
f8ae394cad
commit
1f3c879a85
5 changed files with 76 additions and 63 deletions
|
@ -189,7 +189,9 @@ impl<'lr> TShadowRoot for ServoShadowRoot<'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>
|
||||
|
|
|
@ -491,7 +491,7 @@ impl Element {
|
|||
self.ensure_rare_data().shadow_root = Some(Dom::from_ref(&*shadow_root));
|
||||
shadow_root
|
||||
.upcast::<Node>()
|
||||
.set_containing_shadow_root(&shadow_root);
|
||||
.set_containing_shadow_root(Some(&shadow_root));
|
||||
|
||||
if self.is_connected() {
|
||||
self.node.owner_doc().register_shadow_root(&*shadow_root);
|
||||
|
@ -504,6 +504,7 @@ impl Element {
|
|||
|
||||
pub fn detach_shadow(&self) {
|
||||
if let Some(ref shadow_root) = self.shadow_root() {
|
||||
shadow_root.detach();
|
||||
self.node.owner_doc().unregister_shadow_root(shadow_root);
|
||||
self.ensure_rare_data().shadow_root = None;
|
||||
} else {
|
||||
|
|
|
@ -1737,55 +1737,53 @@ impl HTMLMediaElement {
|
|||
// if we are already showing the controls.
|
||||
return;
|
||||
}
|
||||
if let Ok(shadow_root) = element.attach_shadow(IsUserAgentWidget::Yes) {
|
||||
let document = document_from_node(self);
|
||||
let script = HTMLScriptElement::new(
|
||||
local_name!("script"),
|
||||
None,
|
||||
&document,
|
||||
ElementCreator::ScriptCreated,
|
||||
);
|
||||
let mut media_controls_script =
|
||||
resources::read_string(EmbedderResource::MediaControlsJS);
|
||||
// This is our hacky way to temporarily workaround the lack of a privileged
|
||||
// JS context.
|
||||
// The media controls UI accesses the document.servoGetMediaControls(id) API
|
||||
// to get an instance to the media controls ShadowRoot.
|
||||
// `id` needs to match the internally generated UUID assigned to a media element.
|
||||
let id = document.register_media_controls(&shadow_root);
|
||||
let media_controls_script = media_controls_script.as_mut_str().replace("@@@id@@@", &id);
|
||||
*self.media_controls_id.borrow_mut() = Some(id);
|
||||
script
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(DOMString::from(media_controls_script)));
|
||||
if let Err(e) = shadow_root
|
||||
.upcast::<Node>()
|
||||
.AppendChild(&*script.upcast::<Node>())
|
||||
{
|
||||
warn!("Could not render media controls {:?}", e);
|
||||
return;
|
||||
}
|
||||
|
||||
let media_controls_style = resources::read_string(EmbedderResource::MediaControlsCSS);
|
||||
let style = HTMLStyleElement::new(
|
||||
local_name!("script"),
|
||||
None,
|
||||
&document,
|
||||
ElementCreator::ScriptCreated,
|
||||
);
|
||||
style
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(DOMString::from(media_controls_style)));
|
||||
|
||||
if let Err(e) = shadow_root
|
||||
.upcast::<Node>()
|
||||
.AppendChild(&*style.upcast::<Node>())
|
||||
{
|
||||
warn!("Could not render media controls {:?}", e);
|
||||
}
|
||||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
let shadow_root = element.attach_shadow(IsUserAgentWidget::Yes).unwrap();
|
||||
let document = document_from_node(self);
|
||||
let script = HTMLScriptElement::new(
|
||||
local_name!("script"),
|
||||
None,
|
||||
&document,
|
||||
ElementCreator::ScriptCreated,
|
||||
);
|
||||
let mut media_controls_script = resources::read_string(EmbedderResource::MediaControlsJS);
|
||||
// This is our hacky way to temporarily workaround the lack of a privileged
|
||||
// JS context.
|
||||
// The media controls UI accesses the document.servoGetMediaControls(id) API
|
||||
// to get an instance to the media controls ShadowRoot.
|
||||
// `id` needs to match the internally generated UUID assigned to a media element.
|
||||
let id = document.register_media_controls(&shadow_root);
|
||||
let media_controls_script = media_controls_script.as_mut_str().replace("@@@id@@@", &id);
|
||||
*self.media_controls_id.borrow_mut() = Some(id);
|
||||
script
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(DOMString::from(media_controls_script)));
|
||||
if let Err(e) = shadow_root
|
||||
.upcast::<Node>()
|
||||
.AppendChild(&*script.upcast::<Node>())
|
||||
{
|
||||
warn!("Could not render media controls {:?}", e);
|
||||
return;
|
||||
}
|
||||
|
||||
let media_controls_style = resources::read_string(EmbedderResource::MediaControlsCSS);
|
||||
let style = HTMLStyleElement::new(
|
||||
local_name!("script"),
|
||||
None,
|
||||
&document,
|
||||
ElementCreator::ScriptCreated,
|
||||
);
|
||||
style
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(DOMString::from(media_controls_style)));
|
||||
|
||||
if let Err(e) = shadow_root
|
||||
.upcast::<Node>()
|
||||
.AppendChild(&*style.upcast::<Node>())
|
||||
{
|
||||
warn!("Could not render media controls {:?}", e);
|
||||
}
|
||||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
|
||||
fn remove_controls(&self) {
|
||||
|
|
|
@ -283,7 +283,7 @@ impl Node {
|
|||
for node in new_child.traverse_preorder(ShadowIncluding::No) {
|
||||
if parent_in_shadow_tree {
|
||||
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());
|
||||
}
|
||||
|
@ -961,8 +961,8 @@ impl Node {
|
|||
.map(|sr| DomRoot::from_ref(&**sr))
|
||||
}
|
||||
|
||||
pub fn set_containing_shadow_root(&self, shadow_root: &ShadowRoot) {
|
||||
self.ensure_rare_data().containing_shadow_root = Some(Dom::from_ref(shadow_root));
|
||||
pub fn set_containing_shadow_root(&self, shadow_root: Option<&ShadowRoot>) {
|
||||
self.ensure_rare_data().containing_shadow_root = shadow_root.map(|sr| Dom::from_ref(sr));
|
||||
}
|
||||
|
||||
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();
|
||||
if let Some(ref parent) = parent {
|
||||
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
|
||||
|
|
|
@ -41,7 +41,7 @@ pub struct ShadowRoot {
|
|||
document_fragment: DocumentFragment,
|
||||
document_or_shadow_root: DocumentOrShadowRoot,
|
||||
document: Dom<Document>,
|
||||
host: Dom<Element>,
|
||||
host: MutNullableDom<Element>,
|
||||
/// List of author styles associated with nodes in this shadow tree.
|
||||
author_styles: DomRefCell<AuthorStyles<StyleSheetInDocument>>,
|
||||
stylesheet_list: MutNullableDom<StyleSheetList>,
|
||||
|
@ -62,7 +62,7 @@ impl ShadowRoot {
|
|||
document_fragment,
|
||||
document_or_shadow_root: DocumentOrShadowRoot::new(document.window()),
|
||||
document: Dom::from_ref(document),
|
||||
host: Dom::from_ref(host),
|
||||
host: MutNullableDom::new(Some(host)),
|
||||
author_styles: DomRefCell::new(AuthorStyles::new()),
|
||||
stylesheet_list: MutNullableDom::new(None),
|
||||
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>> {
|
||||
//XXX get retargeted focused element
|
||||
None
|
||||
|
@ -130,9 +140,9 @@ impl ShadowRoot {
|
|||
self.document.invalidate_shadow_roots_stylesheets();
|
||||
self.author_styles.borrow_mut().stylesheets.force_dirty();
|
||||
// Mark the host element dirty so a reflow will be performed.
|
||||
self.host
|
||||
.upcast::<Node>()
|
||||
.dirty(NodeDamage::NodeStyleDamaged);
|
||||
if let Some(host) = self.host.get() {
|
||||
host.upcast::<Node>().dirty(NodeDamage::NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
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
|
||||
|
@ -232,7 +244,7 @@ impl ShadowRootMethods for ShadowRoot {
|
|||
|
||||
#[allow(unsafe_code)]
|
||||
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>(
|
||||
&self,
|
||||
) -> &'a AuthorStyles<StyleSheetInDocument>;
|
||||
|
@ -247,8 +259,8 @@ pub trait LayoutShadowRootHelpers {
|
|||
impl LayoutShadowRootHelpers for LayoutDom<ShadowRoot> {
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn get_host_for_layout(&self) -> LayoutDom<Element> {
|
||||
(*self.unsafe_get()).host.to_layout()
|
||||
unsafe fn get_host_for_layout(&self) -> Option<LayoutDom<Element>> {
|
||||
(*self.unsafe_get()).host.get_inner_as_layout()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue