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 js::context::JSContext;
7use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
8use servo_arc::Arc;
9use style::stylesheets::Stylesheet;
10
11use super::cssstylesheet::CSSStyleSheet;
12use super::stylesheet::StyleSheet;
13use crate::dom::bindings::codegen::Bindings::StyleSheetListBinding::StyleSheetListMethods;
14use crate::dom::bindings::root::{Dom, DomRoot};
15use crate::dom::document::Document;
16use crate::dom::documentorshadowroot::StylesheetSource;
17use crate::dom::element::Element;
18use crate::dom::shadowroot::ShadowRoot;
19use crate::dom::window::Window;
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(
37        &self,
38        cx: &mut JSContext,
39        index: usize,
40    ) -> Option<DomRoot<CSSStyleSheet>> {
41        match *self {
42            StyleSheetListOwner::Document(ref doc) => doc.stylesheet_at(cx, index),
43            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
44                shadow_root.stylesheet_at(cx, index)
45            },
46        }
47    }
48
49    pub(crate) fn add_owned_stylesheet(&self, owner_node: &Element, sheet: Arc<Stylesheet>) {
50        match *self {
51            StyleSheetListOwner::Document(ref doc) => doc.add_owned_stylesheet(owner_node, sheet),
52            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
53                shadow_root.add_owned_stylesheet(owner_node, sheet)
54            },
55        }
56    }
57
58    pub(crate) fn append_constructed_stylesheet(&self, cssom_stylesheet: &CSSStyleSheet) {
59        match *self {
60            StyleSheetListOwner::Document(ref doc) => {
61                doc.append_constructed_stylesheet(cssom_stylesheet)
62            },
63            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
64                shadow_root.append_constructed_stylesheet(cssom_stylesheet)
65            },
66        }
67    }
68
69    #[cfg_attr(crown, expect(crown::unrooted_must_root))] // Owner needs to be rooted already necessarily.
70    pub(crate) fn remove_stylesheet(&self, owner: StylesheetSource, s: &Arc<Stylesheet>) {
71        match *self {
72            StyleSheetListOwner::Document(ref doc) => doc.remove_stylesheet(owner, s),
73            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
74                shadow_root.remove_stylesheet(owner, s)
75            },
76        }
77    }
78
79    pub(crate) fn invalidate_stylesheets(&self) {
80        match *self {
81            StyleSheetListOwner::Document(ref doc) => doc.invalidate_stylesheets(),
82            StyleSheetListOwner::ShadowRoot(ref shadow_root) => {
83                shadow_root.invalidate_stylesheets()
84            },
85        }
86    }
87}
88
89#[dom_struct]
90pub(crate) struct StyleSheetList {
91    reflector_: Reflector,
92    document_or_shadow_root: StyleSheetListOwner,
93}
94
95impl StyleSheetList {
96    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
97    fn new_inherited(doc_or_sr: StyleSheetListOwner) -> StyleSheetList {
98        StyleSheetList {
99            reflector_: Reflector::new(),
100            document_or_shadow_root: doc_or_sr,
101        }
102    }
103
104    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
105    pub(crate) fn new(
106        cx: &mut js::context::JSContext,
107        window: &Window,
108        doc_or_sr: StyleSheetListOwner,
109    ) -> DomRoot<StyleSheetList> {
110        reflect_dom_object_with_cx(
111            Box::new(StyleSheetList::new_inherited(doc_or_sr)),
112            window,
113            cx,
114        )
115    }
116}
117
118impl StyleSheetListMethods<crate::DomTypeHolder> for StyleSheetList {
119    /// <https://drafts.csswg.org/cssom/#dom-stylesheetlist-length>
120    fn Length(&self) -> u32 {
121        self.document_or_shadow_root.stylesheet_count() as u32
122    }
123
124    /// <https://drafts.csswg.org/cssom/#dom-stylesheetlist-item>
125    fn Item(&self, cx: &mut JSContext, index: u32) -> Option<DomRoot<StyleSheet>> {
126        // XXXManishearth this  doesn't handle the origin clean flag and is a
127        // cors vulnerability
128        self.document_or_shadow_root
129            .stylesheet_at(cx, index as usize)
130            .map(DomRoot::upcast)
131    }
132
133    // check-tidy: no specs after this line
134    fn IndexedGetter(&self, cx: &mut JSContext, index: u32) -> Option<DomRoot<StyleSheet>> {
135        self.Item(cx, index)
136    }
137}