script/dom/
stylepropertymapreadonly.rs1use std::cmp::Ordering;
6use std::iter::Iterator;
7
8use dom_struct::dom_struct;
9use rustc_hash::FxBuildHasher;
10use style::custom_properties;
11use stylo_atoms::Atom;
12
13use super::bindings::trace::HashMapTracedValues;
14use crate::dom::bindings::codegen::Bindings::StylePropertyMapReadOnlyBinding::StylePropertyMapReadOnlyMethods;
15use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
16use crate::dom::bindings::root::{Dom, DomRoot};
17use crate::dom::bindings::str::DOMString;
18use crate::dom::cssstylevalue::CSSStyleValue;
19use crate::dom::globalscope::GlobalScope;
20use crate::script_runtime::CanGc;
21
22#[dom_struct]
23pub(crate) struct StylePropertyMapReadOnly {
24 reflector: Reflector,
25 entries: HashMapTracedValues<Atom, Dom<CSSStyleValue>, FxBuildHasher>,
26}
27
28impl StylePropertyMapReadOnly {
29 fn new_inherited<Entries>(entries: Entries) -> StylePropertyMapReadOnly
30 where
31 Entries: IntoIterator<Item = (Atom, Dom<CSSStyleValue>)>,
32 {
33 StylePropertyMapReadOnly {
34 reflector: Reflector::new(),
35 entries: HashMapTracedValues(entries.into_iter().collect()),
36 }
37 }
38
39 pub(crate) fn from_iter<Entries>(
40 global: &GlobalScope,
41 entries: Entries,
42 can_gc: CanGc,
43 ) -> DomRoot<StylePropertyMapReadOnly>
44 where
45 Entries: IntoIterator<Item = (Atom, String)>,
46 {
47 let mut keys = Vec::new();
48 rooted_vec!(let mut values);
49 let iter = entries.into_iter();
50 let (lo, _) = iter.size_hint();
51 keys.reserve(lo);
52 values.reserve(lo);
53 for (key, value) in iter {
54 let value = CSSStyleValue::new(global, value, can_gc);
55 keys.push(key);
56 values.push(Dom::from_ref(&*value));
57 }
58 let iter = keys.drain(..).zip(values.iter().cloned());
59 reflect_dom_object(
60 Box::new(StylePropertyMapReadOnly::new_inherited(iter)),
61 global,
62 can_gc,
63 )
64 }
65}
66
67impl StylePropertyMapReadOnlyMethods<crate::DomTypeHolder> for StylePropertyMapReadOnly {
68 fn Get(&self, property: DOMString) -> Option<DomRoot<CSSStyleValue>> {
70 self.entries
72 .get(&Atom::from(property))
73 .map(|value| DomRoot::from_ref(&**value))
74 }
75
76 fn Has(&self, property: DOMString) -> bool {
78 self.entries.contains_key(&Atom::from(property))
80 }
81
82 fn GetProperties(&self) -> Vec<DOMString> {
84 let mut result: Vec<DOMString> = self
85 .entries
86 .0
87 .keys()
88 .map(|key| DOMString::from(&**key))
89 .collect();
90 result.sort_by(|key1, key2| {
93 if let Ok(key1) = custom_properties::parse_name(&key1.str()) {
94 if let Ok(key2) = custom_properties::parse_name(&key2.str()) {
95 key1.cmp(key2)
96 } else {
97 Ordering::Greater
98 }
99 } else if custom_properties::parse_name(&key2.str()).is_ok() {
100 Ordering::Less
101 } else {
102 key1.cmp(key2)
103 }
104 });
105 result
106 }
107}