diff options
Diffstat (limited to 'components/script/dom/nodelist.rs')
-rw-r--r-- | components/script/dom/nodelist.rs | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index 88fdd4cb70c..1fdcef4b340 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -7,7 +7,9 @@ use crate::dom::bindings::codegen::Bindings::NodeListBinding; use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; +use crate::dom::bindings::str::DOMString; use crate::dom::htmlelement::HTMLElement; +use crate::dom::htmlformelement::HTMLFormElement; use crate::dom::node::{ChildrenMutation, Node}; use crate::dom::window::Window; use dom_struct::dom_struct; @@ -19,6 +21,7 @@ pub enum NodeListType { Simple(Vec<Dom<Node>>), Children(ChildrenList), Labels(LabelsList), + Radio(RadioList), } // https://dom.spec.whatwg.org/#interface-nodelist @@ -83,6 +86,7 @@ impl NodeListMethods for NodeList { NodeListType::Simple(ref elems) => elems.len() as u32, NodeListType::Children(ref list) => list.len(), NodeListType::Labels(ref list) => list.len(), + NodeListType::Radio(ref list) => list.len(), } } @@ -94,6 +98,7 @@ impl NodeListMethods for NodeList { .map(|node| DomRoot::from_ref(&**node)), NodeListType::Children(ref list) => list.item(index), NodeListType::Labels(ref list) => list.item(index), + NodeListType::Radio(ref list) => list.item(index), } } @@ -108,20 +113,22 @@ impl NodeList { if let NodeListType::Children(ref list) = self.list_type { list } else { - panic!("called as_children_list() on a simple node list") + panic!("called as_children_list() on a non-children node list") } } - pub fn as_simple_list(&self) -> &Vec<Dom<Node>> { - if let NodeListType::Simple(ref list) = self.list_type { + pub fn as_radio_list(&self) -> &RadioList { + if let NodeListType::Radio(ref list) = self.list_type { list } else { - panic!("called as_simple_list() on a children node list") + panic!("called as_radio_list() on a non-radio node list") } } pub fn iter<'a>(&'a self) -> impl Iterator<Item = DomRoot<Node>> + 'a { let len = self.Length(); + // There is room for optimization here in non-simple cases, + // as calling Item repeatedly on a live list can involve redundant work. (0..len).flat_map(move |i| self.Item(i)) } } @@ -328,7 +335,7 @@ impl ChildrenList { } } -// Labels lists: There might room for performance optimization +// Labels lists: There might be room for performance optimization // analogous to the ChildrenMutation case of a children list, // in which we can keep information from an older access live // if we know nothing has happened that would change it. @@ -357,3 +364,40 @@ impl LabelsList { self.element.label_at(index) } } + +// Radio node lists: There is room for performance improvement here; +// a form is already aware of changes to its set of controls, +// so a radio list can cache and cache-invalidate its contents +// just by hooking into what the form already knows without a +// separate mutation observer. FIXME #25482 +#[derive(Clone, Copy, JSTraceable, MallocSizeOf)] +pub enum RadioListMode { + ControlsExceptImageInputs, + Images, +} + +#[derive(JSTraceable, MallocSizeOf)] +#[unrooted_must_root_lint::must_root] +pub struct RadioList { + form: Dom<HTMLFormElement>, + mode: RadioListMode, + name: DOMString, +} + +impl RadioList { + pub fn new(form: &HTMLFormElement, mode: RadioListMode, name: DOMString) -> RadioList { + RadioList { + form: Dom::from_ref(form), + mode: mode, + name: name, + } + } + + pub fn len(&self) -> u32 { + self.form.count_for_radio_list(self.mode, &self.name) + } + + pub fn item(&self, index: u32) -> Option<DomRoot<Node>> { + self.form.nth_for_radio_list(index, self.mode, &self.name) + } +} |