From 31980a7a34fb18ddd637dfacec0d0226e9ac0bd1 Mon Sep 17 00:00:00 2001 From: Anthony Urena Date: Tue, 6 Oct 2015 11:53:00 -0400 Subject: [PATCH] Refactor html form dataset collection Factor out FormDatum collection for Improve early return logic for getting the FormDatum from an Condense element type patterns --- components/script/dom/htmlformelement.rs | 123 +++++++--------------- components/script/dom/htmlinputelement.rs | 40 ++++++- 2 files changed, 79 insertions(+), 84 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 632b084c293..2b4edbbdfcb 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -229,7 +229,43 @@ impl HTMLFormElement { win.r().pipeline(), load_data)).unwrap(); } - pub fn get_form_dataset<'b>(&self, submitter: Option>) -> Vec { + fn get_unclean_dataset<'a>(&self, submitter: Option>) -> Vec { + let node = NodeCast::from_ref(self); + // TODO: This is an incorrect way of getting controls owned + // by the form, but good enough until html5ever lands + node.traverse_preorder().filter_map(|child| { + if child.r().get_disabled_state() { + return None; + } + if child.r().ancestors() + .any(|a| HTMLDataListElementCast::to_root(a).is_some()) { + return None; + } + match child.r().type_id() { + NodeTypeId::Element(ElementTypeId::HTMLElement(element)) => { + match element { + HTMLElementTypeId::HTMLInputElement => { + let input = HTMLInputElementCast::to_ref(child.r()).unwrap(); + input.get_form_datum(submitter) + } + HTMLElementTypeId::HTMLButtonElement | + HTMLElementTypeId::HTMLSelectElement | + HTMLElementTypeId::HTMLObjectElement | + HTMLElementTypeId::HTMLTextAreaElement => { + // Unimplemented + None + } + _ => None + } + } + _ => None + } + }).collect() + // TODO: Handle `dirnames` (needs directionality support) + // https://html.spec.whatwg.org/multipage/#the-directionality + } + + pub fn get_form_dataset<'a>(&self, submitter: Option>) -> Vec { fn clean_crlf(s: &str) -> DOMString { // https://html.spec.whatwg.org/multipage/#constructing-the-form-data-set // Step 4 @@ -262,88 +298,9 @@ impl HTMLFormElement { buf } - let node = NodeCast::from_ref(self); - // TODO: This is an incorrect way of getting controls owned - // by the form, but good enough until html5ever lands - let data_set = node.traverse_preorder().filter_map(|child| { - if child.r().get_disabled_state() { - return None; - } - if child.r().ancestors() - .any(|a| HTMLDataListElementCast::to_root(a).is_some()) { - return None; - } - // XXXManishearth don't include it if it is a button but not the submitter - match child.r().type_id() { - NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => { - let input = HTMLInputElementCast::to_ref(child.r()).unwrap(); - let ty = input.Type(); - let name = input.Name(); - match &*ty { - "radio" | "checkbox" => { - if !input.Checked() || name.is_empty() { - return None; - } - }, - "image" => (), - _ => { - if name.is_empty() { - return None; - } - } - } - - let mut value = input.Value(); - let is_submitter = match submitter { - Some(FormSubmitter::InputElement(s)) => { - input == s - }, - _ => false - }; - match &*ty { - "image" => None, // Unimplemented - "radio" | "checkbox" => { - if value.is_empty() { - value = "on".to_owned(); - } - Some(FormDatum { - ty: ty, - name: name, - value: value - }) - }, - // Discard buttons which are not the submitter - "submit" | "button" | "reset" if !is_submitter => None, - "file" => None, // Unimplemented - _ => Some(FormDatum { - ty: ty, - name: name, - value: value - }) - } - } - NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) => { - // Unimplemented - None - } - NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) => { - // Unimplemented - None - } - NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement)) => { - // Unimplemented - None - } - NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => { - // Unimplemented - None - } - _ => None - } - }); - // TODO: Handle `dirnames` (needs directionality support) - // https://html.spec.whatwg.org/multipage/#the-directionality - let mut ret: Vec = data_set.collect(); + let mut ret = self.get_unclean_dataset(submitter); + // https://html.spec.whatwg.org/multipage/#constructing-the-form-data-set + // Step 4 for datum in &mut ret { match &*datum.ty { "file" | "textarea" => (), diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 3d9f7ce66ba..d8e5e843c19 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -21,7 +21,7 @@ use dom::element::{AttributeMutation, Element, ElementTypeId, RawLayoutElementHe use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; -use dom::htmlformelement::{FormControl, FormSubmitter, HTMLFormElement}; +use dom::htmlformelement::{FormControl, FormSubmitter, HTMLFormElement, FormDatum}; use dom::htmlformelement::{ResetFrom, SubmittedFrom}; use dom::keyboardevent::KeyboardEvent; use dom::node::{Node, NodeDamage, NodeTypeId}; @@ -408,6 +408,44 @@ impl HTMLInputElement { } } + pub fn get_form_datum<'a>(&self, submitter: Option>) -> Option { + let ty = self.Type(); + let name = self.Name(); + let is_submitter = match submitter { + Some(FormSubmitter::InputElement(s)) => { + self == s + }, + _ => false + }; + + match &*ty { + "submit" | "button" | "reset" if !is_submitter => return None, + "radio" | "checkbox" => { + if !self.Checked() || name.is_empty() { + return None; + } + }, + "image" | "file" => return None, // Unimplemented + _ => { + if name.is_empty() { + return None; + } + } + } + + let mut value = self.Value(); + if ty == "radio" || ty == "checkbox" { + if value.is_empty() { + value = "on".to_owned(); + } + } + Some(FormDatum { + ty: ty, + name: name, + value: value + }) + } + // https://html.spec.whatwg.org/multipage/#radio-button-group pub fn get_radio_group_name(&self) -> Option { //TODO: determine form owner