/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cmp::Ordering; use std::iter::Iterator; use dom_struct::dom_struct; use style::custom_properties; use stylo_atoms::Atom; use super::bindings::trace::HashMapTracedValues; use crate::dom::bindings::codegen::Bindings::StylePropertyMapReadOnlyBinding::StylePropertyMapReadOnlyMethods; use crate::dom::bindings::reflector::{Reflector, reflect_dom_object}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::cssstylevalue::CSSStyleValue; use crate::dom::globalscope::GlobalScope; use crate::script_runtime::CanGc; #[dom_struct] pub(crate) struct StylePropertyMapReadOnly { reflector: Reflector, entries: HashMapTracedValues>, } impl StylePropertyMapReadOnly { fn new_inherited(entries: Entries) -> StylePropertyMapReadOnly where Entries: IntoIterator)>, { StylePropertyMapReadOnly { reflector: Reflector::new(), entries: HashMapTracedValues(entries.into_iter().collect()), } } pub(crate) fn from_iter( global: &GlobalScope, entries: Entries, can_gc: CanGc, ) -> DomRoot where Entries: IntoIterator, { let mut keys = Vec::new(); rooted_vec!(let mut values); let iter = entries.into_iter(); let (lo, _) = iter.size_hint(); keys.reserve(lo); values.reserve(lo); for (key, value) in iter { let value = CSSStyleValue::new(global, value, can_gc); keys.push(key); values.push(Dom::from_ref(&*value)); } let iter = keys.drain(..).zip(values.iter().cloned()); reflect_dom_object( Box::new(StylePropertyMapReadOnly::new_inherited(iter)), global, can_gc, ) } } impl StylePropertyMapReadOnlyMethods for StylePropertyMapReadOnly { /// fn Get(&self, property: DOMString) -> Option> { // TODO: avoid constructing an Atom self.entries .get(&Atom::from(property)) .map(|value| DomRoot::from_ref(&**value)) } /// fn Has(&self, property: DOMString) -> bool { // TODO: avoid constructing an Atom self.entries.contains_key(&Atom::from(property)) } /// fn GetProperties(&self) -> Vec { let mut result: Vec = self .entries .0 .keys() .map(|key| DOMString::from(&**key)) .collect(); // https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-getproperties // requires this sort order result.sort_by(|key1, key2| { if let Ok(key1) = custom_properties::parse_name(key1) { if let Ok(key2) = custom_properties::parse_name(key2) { key1.cmp(key2) } else { Ordering::Greater } } else if custom_properties::parse_name(key2).is_ok() { Ordering::Less } else { key1.cmp(key2) } }); result } }