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