mirror of
https://github.com/servo/servo.git
synced 2025-07-19 13:23:46 +01:00
css: Refactor StyleSheetInDocument
owner (#38136)
Refactor `documentotshadowroot::StyleSheetInDocument`, renaming it into `ServoStylesheetInDocument` to avoid confusion with Stylo's `StylesheetInDocument` trait. To support constructed stylesheet. The `ServoStylesheetInDocument.owner` would contains enum of: - `Dom<Element>` - for stylesheet parsed from an element. - `Dom<CSSStylesheet>` - for constructed stylesheet. Testing: No WPT regression. Fixes: #38133 --------- Signed-off-by: Jo Steven Novaryo <jo.steven.novaryo@huawei.com>
This commit is contained in:
parent
d671f58078
commit
bbed6cddcd
6 changed files with 112 additions and 57 deletions
|
@ -134,7 +134,9 @@ use crate::dom::customelementregistry::CustomElementDefinition;
|
|||
use crate::dom::customevent::CustomEvent;
|
||||
use crate::dom::datatransfer::DataTransfer;
|
||||
use crate::dom::documentfragment::DocumentFragment;
|
||||
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, StyleSheetInDocument};
|
||||
use crate::dom::documentorshadowroot::{
|
||||
DocumentOrShadowRoot, ServoStylesheetInDocument, StylesheetSource,
|
||||
};
|
||||
use crate::dom::documenttype::DocumentType;
|
||||
use crate::dom::domimplementation::DOMImplementation;
|
||||
use crate::dom::element::{
|
||||
|
@ -332,7 +334,7 @@ pub(crate) struct Document {
|
|||
style_shared_lock: StyleSharedRwLock,
|
||||
/// List of stylesheets associated with nodes in this document. |None| if the list needs to be refreshed.
|
||||
#[custom_trace]
|
||||
stylesheets: DomRefCell<DocumentStylesheetSet<StyleSheetInDocument>>,
|
||||
stylesheets: DomRefCell<DocumentStylesheetSet<ServoStylesheetInDocument>>,
|
||||
stylesheet_list: MutNullableDom<StyleSheetList>,
|
||||
ready_state: Cell<DocumentReadyState>,
|
||||
/// Whether the DOMContentLoaded event has already been dispatched.
|
||||
|
@ -4889,23 +4891,29 @@ impl Document {
|
|||
|
||||
stylesheets
|
||||
.get(Origin::Author, index)
|
||||
.and_then(|s| s.owner.upcast::<Node>().get_cssom_stylesheet())
|
||||
.and_then(|s| s.owner.get_cssom_object())
|
||||
}
|
||||
|
||||
/// Add a stylesheet owned by `owner` to the list of document sheets, in the
|
||||
/// correct tree position.
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn add_stylesheet(&self, owner: &Element, sheet: Arc<Stylesheet>) {
|
||||
pub(crate) fn add_stylesheet(&self, owner: StylesheetSource, sheet: Arc<Stylesheet>) {
|
||||
let stylesheets = &mut *self.stylesheets.borrow_mut();
|
||||
let insertion_point = stylesheets
|
||||
|
||||
// TODO(stevennovayo): support constructed stylesheet for adopted stylesheet and its ordering
|
||||
let insertion_point = match &owner {
|
||||
StylesheetSource::Element(owner_elem) => stylesheets
|
||||
.iter()
|
||||
.map(|(sheet, _origin)| sheet)
|
||||
.find(|sheet_in_doc| {
|
||||
owner
|
||||
.upcast::<Node>()
|
||||
.is_before(sheet_in_doc.owner.upcast())
|
||||
.find(|sheet_in_doc| match sheet_in_doc.owner {
|
||||
StylesheetSource::Element(ref other_elem) => {
|
||||
owner_elem.upcast::<Node>().is_before(other_elem.upcast())
|
||||
},
|
||||
StylesheetSource::Constructed(_) => unreachable!(),
|
||||
})
|
||||
.cloned();
|
||||
.cloned(),
|
||||
StylesheetSource::Constructed(_) => unreachable!(),
|
||||
};
|
||||
|
||||
if self.has_browsing_context() {
|
||||
self.window.layout_mut().add_stylesheet(
|
||||
|
@ -4932,7 +4940,7 @@ impl Document {
|
|||
|
||||
/// Remove a stylesheet owned by `owner` from the list of document sheets.
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn remove_stylesheet(&self, owner: &Element, stylesheet: &Arc<Stylesheet>) {
|
||||
pub(crate) fn remove_stylesheet(&self, owner: StylesheetSource, stylesheet: &Arc<Stylesheet>) {
|
||||
if self.has_browsing_context() {
|
||||
self.window
|
||||
.layout_mut()
|
||||
|
|
|
@ -26,46 +26,77 @@ use crate::dom::element::Element;
|
|||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::node::{self, Node, VecPreOrderInsertionHelper};
|
||||
use crate::dom::shadowroot::ShadowRoot;
|
||||
use crate::dom::types::CSSStyleSheet;
|
||||
use crate::dom::window::Window;
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::stylesheet_set::StylesheetSetRef;
|
||||
|
||||
/// Stylesheet could be constructed by a CSSOM object CSSStylesheet or parsed
|
||||
/// from HTML element such as `<style>` or `<link>`.
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub(crate) struct StyleSheetInDocument {
|
||||
pub(crate) enum StylesheetSource {
|
||||
Element(Dom<Element>),
|
||||
// TODO(stevennovaryo): This type of enum would not be used until we implement adopted stylesheet
|
||||
#[allow(dead_code)]
|
||||
Constructed(Dom<CSSStyleSheet>),
|
||||
}
|
||||
|
||||
impl StylesheetSource {
|
||||
pub(crate) fn get_cssom_object(&self) -> Option<DomRoot<CSSStyleSheet>> {
|
||||
match self {
|
||||
StylesheetSource::Element(el) => el.upcast::<Node>().get_cssom_stylesheet(),
|
||||
StylesheetSource::Constructed(ss) => Some(ss.as_rooted()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_a_valid_owner(&self) -> bool {
|
||||
match self {
|
||||
StylesheetSource::Element(el) => el.as_stylesheet_owner().is_some(),
|
||||
StylesheetSource::Constructed(ss) => ss.is_constructed(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub(crate) struct ServoStylesheetInDocument {
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
#[no_trace]
|
||||
pub(crate) sheet: Arc<Stylesheet>,
|
||||
pub(crate) owner: Dom<Element>,
|
||||
/// The object that owns this stylesheet. For constructed stylesheet, it would be the
|
||||
/// CSSOM object itself, and for stylesheet generated by an element, it would be the
|
||||
/// html element. This is used to get the CSSOM Stylesheet within a DocumentOrShadowDOM.
|
||||
pub(crate) owner: StylesheetSource,
|
||||
}
|
||||
|
||||
// This is necessary because this type is contained within a Stylo type which needs
|
||||
// Stylo's version of MallocSizeOf.
|
||||
impl stylo_malloc_size_of::MallocSizeOf for StyleSheetInDocument {
|
||||
impl stylo_malloc_size_of::MallocSizeOf for ServoStylesheetInDocument {
|
||||
fn size_of(&self, ops: &mut stylo_malloc_size_of::MallocSizeOfOps) -> usize {
|
||||
<StyleSheetInDocument as malloc_size_of::MallocSizeOf>::size_of(self, ops)
|
||||
<ServoStylesheetInDocument as malloc_size_of::MallocSizeOf>::size_of(self, ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for StyleSheetInDocument {
|
||||
impl fmt::Debug for ServoStylesheetInDocument {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.sheet.fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for StyleSheetInDocument {
|
||||
impl PartialEq for ServoStylesheetInDocument {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Arc::ptr_eq(&self.sheet, &other.sheet)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToMediaListKey for StyleSheetInDocument {
|
||||
impl ToMediaListKey for ServoStylesheetInDocument {
|
||||
fn to_media_list_key(&self) -> MediaListKey {
|
||||
self.sheet.contents.to_media_list_key()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
|
||||
impl ::style::stylesheets::StylesheetInDocument for ServoStylesheetInDocument {
|
||||
fn enabled(&self) -> bool {
|
||||
self.sheet.enabled()
|
||||
}
|
||||
|
@ -85,7 +116,7 @@ impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
|
|||
|
||||
// https://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
pub(crate) struct DocumentOrShadowRoot {
|
||||
window: Dom<Window>,
|
||||
}
|
||||
|
@ -225,18 +256,18 @@ impl DocumentOrShadowRoot {
|
|||
/// Remove a stylesheet owned by `owner` from the list of document sheets.
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn remove_stylesheet(
|
||||
owner: &Element,
|
||||
owner: StylesheetSource,
|
||||
s: &Arc<Stylesheet>,
|
||||
mut stylesheets: StylesheetSetRef<StyleSheetInDocument>,
|
||||
mut stylesheets: StylesheetSetRef<ServoStylesheetInDocument>,
|
||||
) {
|
||||
let guard = s.shared_lock.read();
|
||||
|
||||
// FIXME(emilio): Would be nice to remove the clone, etc.
|
||||
stylesheets.remove_stylesheet(
|
||||
None,
|
||||
StyleSheetInDocument {
|
||||
ServoStylesheetInDocument {
|
||||
sheet: s.clone(),
|
||||
owner: Dom::from_ref(owner),
|
||||
owner,
|
||||
},
|
||||
&guard,
|
||||
);
|
||||
|
@ -246,18 +277,15 @@ impl DocumentOrShadowRoot {
|
|||
/// correct tree position.
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn add_stylesheet(
|
||||
owner: &Element,
|
||||
mut stylesheets: StylesheetSetRef<StyleSheetInDocument>,
|
||||
owner: StylesheetSource,
|
||||
mut stylesheets: StylesheetSetRef<ServoStylesheetInDocument>,
|
||||
sheet: Arc<Stylesheet>,
|
||||
insertion_point: Option<StyleSheetInDocument>,
|
||||
insertion_point: Option<ServoStylesheetInDocument>,
|
||||
style_shared_lock: &StyleSharedRwLock,
|
||||
) {
|
||||
debug_assert!(owner.as_stylesheet_owner().is_some(), "Wat");
|
||||
debug_assert!(owner.is_a_valid_owner(), "Wat");
|
||||
|
||||
let sheet = StyleSheetInDocument {
|
||||
sheet,
|
||||
owner: Dom::from_ref(owner),
|
||||
};
|
||||
let sheet = ServoStylesheetInDocument { sheet, owner };
|
||||
|
||||
let guard = style_shared_lock.read();
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ use net_traits::{
|
|||
FetchMetadata, FetchResponseListener, NetworkError, ReferrerPolicy, ResourceFetchTiming,
|
||||
ResourceTimingType,
|
||||
};
|
||||
use script_bindings::root::Dom;
|
||||
use servo_arc::Arc;
|
||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||
use style::attr::AttrValue;
|
||||
|
@ -41,6 +42,7 @@ use crate::dom::bindings::str::{DOMString, USVString};
|
|||
use crate::dom::csp::{GlobalCspReporting, Violation};
|
||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||
use crate::dom::document::Document;
|
||||
use crate::dom::documentorshadowroot::StylesheetSource;
|
||||
use crate::dom::domtokenlist::DOMTokenList;
|
||||
use crate::dom::element::{
|
||||
AttributeMutation, Element, ElementCreator, cors_setting_for_element,
|
||||
|
@ -178,11 +180,13 @@ impl HTMLLinkElement {
|
|||
pub(crate) fn set_stylesheet(&self, s: Arc<Stylesheet>) {
|
||||
let stylesheets_owner = self.stylesheet_list_owner();
|
||||
if let Some(ref s) = *self.stylesheet.borrow() {
|
||||
stylesheets_owner.remove_stylesheet(self.upcast(), s)
|
||||
stylesheets_owner
|
||||
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), s)
|
||||
}
|
||||
*self.stylesheet.borrow_mut() = Some(s.clone());
|
||||
self.clean_stylesheet_ownership();
|
||||
stylesheets_owner.add_stylesheet(self.upcast(), s);
|
||||
stylesheets_owner
|
||||
.add_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), s);
|
||||
}
|
||||
|
||||
pub(crate) fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
|
||||
|
@ -416,7 +420,7 @@ impl VirtualMethods for HTMLLinkElement {
|
|||
if let Some(s) = self.stylesheet.borrow_mut().take() {
|
||||
self.clean_stylesheet_ownership();
|
||||
self.stylesheet_list_owner()
|
||||
.remove_stylesheet(self.upcast(), &s);
|
||||
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), &s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use dom_struct::dom_struct;
|
|||
use html5ever::{LocalName, Prefix};
|
||||
use js::rust::HandleObject;
|
||||
use net_traits::ReferrerPolicy;
|
||||
use script_bindings::root::Dom;
|
||||
use servo_arc::Arc;
|
||||
use style::media_queries::MediaList as StyleMediaList;
|
||||
use style::stylesheets::{AllowImportRules, Origin, Stylesheet, UrlExtraData};
|
||||
|
@ -22,6 +23,7 @@ use crate::dom::bindings::str::DOMString;
|
|||
use crate::dom::csp::{CspReporting, InlineCheckType};
|
||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||
use crate::dom::document::Document;
|
||||
use crate::dom::documentorshadowroot::StylesheetSource;
|
||||
use crate::dom::element::{AttributeMutation, Element, ElementCreator};
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::medialist::MediaList;
|
||||
|
@ -153,11 +155,13 @@ impl HTMLStyleElement {
|
|||
pub(crate) fn set_stylesheet(&self, s: Arc<Stylesheet>) {
|
||||
let stylesheets_owner = self.stylesheet_list_owner();
|
||||
if let Some(ref s) = *self.stylesheet.borrow() {
|
||||
stylesheets_owner.remove_stylesheet(self.upcast(), s)
|
||||
stylesheets_owner
|
||||
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), s)
|
||||
}
|
||||
*self.stylesheet.borrow_mut() = Some(s.clone());
|
||||
self.clean_stylesheet_ownership();
|
||||
stylesheets_owner.add_stylesheet(self.upcast(), s);
|
||||
stylesheets_owner
|
||||
.add_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), s);
|
||||
}
|
||||
|
||||
pub(crate) fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
|
||||
|
@ -192,7 +196,7 @@ impl HTMLStyleElement {
|
|||
if let Some(s) = self.stylesheet.borrow_mut().take() {
|
||||
self.clean_stylesheet_ownership();
|
||||
self.stylesheet_list_owner()
|
||||
.remove_stylesheet(self.upcast(), &s)
|
||||
.remove_stylesheet(StylesheetSource::Element(Dom::from_ref(self.upcast())), &s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,9 @@ use crate::dom::bindings::str::DOMString;
|
|||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||
use crate::dom::document::Document;
|
||||
use crate::dom::documentfragment::DocumentFragment;
|
||||
use crate::dom::documentorshadowroot::{DocumentOrShadowRoot, StyleSheetInDocument};
|
||||
use crate::dom::documentorshadowroot::{
|
||||
DocumentOrShadowRoot, ServoStylesheetInDocument, StylesheetSource,
|
||||
};
|
||||
use crate::dom::element::Element;
|
||||
use crate::dom::htmlslotelement::HTMLSlotElement;
|
||||
use crate::dom::node::{
|
||||
|
@ -62,7 +64,7 @@ pub(crate) struct ShadowRoot {
|
|||
host: MutNullableDom<Element>,
|
||||
/// List of author styles associated with nodes in this shadow tree.
|
||||
#[custom_trace]
|
||||
author_styles: DomRefCell<AuthorStyles<StyleSheetInDocument>>,
|
||||
author_styles: DomRefCell<AuthorStyles<ServoStylesheetInDocument>>,
|
||||
stylesheet_list: MutNullableDom<StyleSheetList>,
|
||||
window: Dom<Window>,
|
||||
|
||||
|
@ -175,22 +177,29 @@ impl ShadowRoot {
|
|||
|
||||
stylesheets
|
||||
.get(index)
|
||||
.and_then(|s| s.owner.upcast::<Node>().get_cssom_stylesheet())
|
||||
.and_then(|s| s.owner.get_cssom_object())
|
||||
}
|
||||
|
||||
/// Add a stylesheet owned by `owner` to the list of shadow root sheets, in the
|
||||
/// correct tree position.
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn add_stylesheet(&self, owner: &Element, sheet: Arc<Stylesheet>) {
|
||||
pub(crate) fn add_stylesheet(&self, owner: StylesheetSource, sheet: Arc<Stylesheet>) {
|
||||
let stylesheets = &mut self.author_styles.borrow_mut().stylesheets;
|
||||
let insertion_point = stylesheets
|
||||
|
||||
// TODO(stevennovayo): support constructed stylesheet for adopted stylesheet and its ordering
|
||||
let insertion_point = match &owner {
|
||||
StylesheetSource::Element(owner_elem) => stylesheets
|
||||
.iter()
|
||||
.find(|sheet_in_shadow| {
|
||||
owner
|
||||
.upcast::<Node>()
|
||||
.is_before(sheet_in_shadow.owner.upcast())
|
||||
.find(|sheet_in_shadow| match sheet_in_shadow.owner {
|
||||
StylesheetSource::Element(ref other_elem) => {
|
||||
owner_elem.upcast::<Node>().is_before(other_elem.upcast())
|
||||
},
|
||||
StylesheetSource::Constructed(_) => unreachable!(),
|
||||
})
|
||||
.cloned();
|
||||
.cloned(),
|
||||
StylesheetSource::Constructed(_) => unreachable!(),
|
||||
};
|
||||
|
||||
DocumentOrShadowRoot::add_stylesheet(
|
||||
owner,
|
||||
StylesheetSetRef::Author(stylesheets),
|
||||
|
@ -202,7 +211,7 @@ impl ShadowRoot {
|
|||
|
||||
/// Remove a stylesheet owned by `owner` from the list of shadow root sheets.
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn remove_stylesheet(&self, owner: &Element, s: &Arc<Stylesheet>) {
|
||||
pub(crate) fn remove_stylesheet(&self, owner: StylesheetSource, s: &Arc<Stylesheet>) {
|
||||
DocumentOrShadowRoot::remove_stylesheet(
|
||||
owner,
|
||||
s,
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
|||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::cssstylesheet::CSSStyleSheet;
|
||||
use crate::dom::document::Document;
|
||||
use crate::dom::element::Element;
|
||||
use crate::dom::documentorshadowroot::StylesheetSource;
|
||||
use crate::dom::shadowroot::ShadowRoot;
|
||||
use crate::dom::stylesheet::StyleSheet;
|
||||
use crate::dom::window::Window;
|
||||
|
@ -39,7 +39,8 @@ impl StyleSheetListOwner {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_stylesheet(&self, owner: &Element, sheet: Arc<Stylesheet>) {
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn add_stylesheet(&self, owner: StylesheetSource, sheet: Arc<Stylesheet>) {
|
||||
match *self {
|
||||
StyleSheetListOwner::Document(ref doc) => doc.add_stylesheet(owner, sheet),
|
||||
StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
|
||||
|
@ -48,7 +49,8 @@ impl StyleSheetListOwner {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn remove_stylesheet(&self, owner: &Element, s: &Arc<Stylesheet>) {
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
|
||||
pub(crate) fn remove_stylesheet(&self, owner: StylesheetSource, s: &Arc<Stylesheet>) {
|
||||
match *self {
|
||||
StyleSheetListOwner::Document(ref doc) => doc.remove_stylesheet(owner, s),
|
||||
StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue