Skip to main content

script/dom/css/
stylesheetlist.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use script_bindings::reflector::{Reflector, reflect_dom_object};
7use servo_arc::Arc;
8use style::stylesheets::Stylesheet;
9
10use super::cssstylesheet::CSSStyleSheet;
11use super::stylesheet::StyleSheet;
12use crate::dom::bindings::codegen::Bindings::StyleSheetListBinding::StyleSheetListMethods;
13use crate::dom::bindings::root::{Dom, DomRoot};
14use crate::dom::document::Document;
15use crate::dom::documentorshadowroot::StylesheetSource;
16use crate::dom::element::Element;
17use crate::dom::shadowroot::ShadowRoot;
18use crate::dom::window::Window;
19use crate::script_runtime::CanGc;
20
21#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
22#[derive(Clone, JSTraceable, MallocSizeOf, PartialEq)]
23pub(crate) enum StyleSheetListOwner {
24    Document(Dom<Document>),
25    ShadowRoot(Dom<ShadowRoot>),
26}
27
28impl StyleSheetListOwner {
29    pub(crate) fn stylesheet_count(&self) -> usize {
30        match *self {
31            StyleSheetListOwner::Document(ref doc) => doc.stylesheet_count(),
32            StyleSheetListOwner::ShadowRoot(ref shadow_root) => shadow_root.stylesheet_count(),
33        }
34    }
35
36    pub(crate) fn stylesheet_at(&self, index: usize) -> Option<DomRoot<CSSStyleSheet>> {
37        match *self {
38            StyleSheetListOwner::Document(ref doc) => doc.stylesheet_at(index),
39            StyleSheetListOwner::ShadowRoot(ref shadow_root) => shadow_root.stylesheet_at(index),
40        }
41    }
42
43    pub(crate) fn add_owned_stylesheet(
44        &self,
45        cx: &mut js::context::JSContext,
46        owner_node: &Element,
47        sheet: Arc<Stylesheet>,
48    ) {
49        match *self {
50            StyleSheetListOwner::Document(ref doc) => {
51                doc.add_owned_stylesheet(cx, owner_node, sheet)
52            },
53            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
54                shadow_root.add_owned_stylesheet(cx, owner_node, sheet)
55            },
56        }
57    }
58
59    pub(crate) fn append_constructed_stylesheet(
60        &self,
61        cx: &mut js::context::JSContext,
62        cssom_stylesheet: &CSSStyleSheet,
63    ) {
64        match *self {
65            StyleSheetListOwner::Document(ref doc) => {
66                doc.append_constructed_stylesheet(cx, cssom_stylesheet)
67            },
68            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
69                shadow_root.append_constructed_stylesheet(cx, cssom_stylesheet)
70            },
71        }
72    }
73
74    #[cfg_attr(crown, expect(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
75    pub(crate) fn remove_stylesheet(&self, owner: StylesheetSource, s: &Arc<Stylesheet>) {
76        match *self {
77            StyleSheetListOwner::Document(ref doc) => doc.remove_stylesheet(owner, s),
78            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
79                shadow_root.remove_stylesheet(owner, s)
80            },
81        }
82    }
83
84    pub(crate) fn invalidate_stylesheets(&self) {
85        match *self {
86            StyleSheetListOwner::Document(ref doc) => doc.invalidate_stylesheets(),
87            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
88                shadow_root.invalidate_stylesheets()
89            },
90        }
91    }
92}
93
94#[dom_struct]
95pub(crate) struct StyleSheetList {
96    reflector_: Reflector,
97    document_or_shadow_root: StyleSheetListOwner,
98}
99
100impl StyleSheetList {
101    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
102    fn new_inherited(doc_or_sr: StyleSheetListOwner) -> StyleSheetList {
103        StyleSheetList {
104            reflector_: Reflector::new(),
105            document_or_shadow_root: doc_or_sr,
106        }
107    }
108
109    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
110    pub(crate) fn new(
111        window: &Window,
112        doc_or_sr: StyleSheetListOwner,
113        can_gc: CanGc,
114    ) -> DomRoot<StyleSheetList> {
115        reflect_dom_object(
116            Box::new(StyleSheetList::new_inherited(doc_or_sr)),
117            window,
118            can_gc,
119        )
120    }
121}
122
123impl StyleSheetListMethods<crate::DomTypeHolder> for StyleSheetList {
124    /// <https://drafts.csswg.org/cssom/#dom-stylesheetlist-length>
125    fn Length(&self) -> u32 {
126        self.document_or_shadow_root.stylesheet_count() as u32
127    }
128
129    /// <https://drafts.csswg.org/cssom/#dom-stylesheetlist-item>
130    fn Item(&self, index: u32) -> Option<DomRoot<StyleSheet>> {
131        // XXXManishearth this  doesn't handle the origin clean flag and is a
132        // cors vulnerability
133        self.document_or_shadow_root
134            .stylesheet_at(index as usize)
135            .map(DomRoot::upcast)
136    }
137
138    // check-tidy: no specs after this line
139    fn IndexedGetter(&self, index: u32) -> Option<DomRoot<StyleSheet>> {
140        self.Item(index)
141    }
142}