aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/formdata.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/formdata.rs')
-rw-r--r--components/script/dom/formdata.rs239
1 files changed, 139 insertions, 100 deletions
diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs
index af4c692e7d9..3a8f3ce4b5b 100644
--- a/components/script/dom/formdata.rs
+++ b/components/script/dom/formdata.rs
@@ -1,60 +1,64 @@
/* 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 http://mozilla.org/MPL/2.0/. */
-
-use dom::bindings::cell::DOMRefCell;
-use dom::bindings::codegen::Bindings::FormDataBinding::FormDataMethods;
-use dom::bindings::codegen::Bindings::FormDataBinding::FormDataWrap;
-use dom::bindings::codegen::UnionTypes::FileOrUSVString;
-use dom::bindings::error::Fallible;
-use dom::bindings::inheritance::Castable;
-use dom::bindings::iterable::Iterable;
-use dom::bindings::js::Root;
-use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
-use dom::bindings::str::{DOMString, USVString};
-use dom::blob::{Blob, BlobImpl};
-use dom::file::File;
-use dom::globalscope::GlobalScope;
-use dom::htmlformelement::{HTMLFormElement, FormDatumValue, FormDatum};
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::bindings::cell::DomRefCell;
+use crate::dom::bindings::codegen::Bindings::FormDataBinding::FormDataMethods;
+use crate::dom::bindings::codegen::UnionTypes::FileOrUSVString;
+use crate::dom::bindings::error::{Error, Fallible};
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::iterable::Iterable;
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::bindings::str::{DOMString, USVString};
+use crate::dom::blob::Blob;
+use crate::dom::file::File;
+use crate::dom::globalscope::GlobalScope;
+use crate::dom::htmlformelement::{FormDatum, FormDatumValue, HTMLFormElement};
use dom_struct::dom_struct;
-use html5ever_atoms::LocalName;
-use std::collections::HashMap;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::iter;
+use html5ever::LocalName;
+use script_traits::serializable::BlobImpl;
#[dom_struct]
pub struct FormData {
reflector_: Reflector,
- data: DOMRefCell<HashMap<LocalName, Vec<FormDatum>>>,
+ data: DomRefCell<Vec<(LocalName, FormDatum)>>,
}
impl FormData {
- fn new_inherited(opt_form: Option<&HTMLFormElement>) -> FormData {
- let mut hashmap: HashMap<LocalName, Vec<FormDatum>> = HashMap::new();
-
- if let Some(form) = opt_form {
- for datum in form.get_form_dataset(None) {
- match hashmap.entry(LocalName::from(datum.name.as_ref())) {
- Occupied(entry) => entry.into_mut().push(datum),
- Vacant(entry) => { entry.insert(vec!(datum)); }
- }
- }
- }
+ fn new_inherited(form_datums: Option<Vec<FormDatum>>) -> FormData {
+ let data = match form_datums {
+ Some(data) => data
+ .iter()
+ .map(|datum| (LocalName::from(datum.name.as_ref()), datum.clone()))
+ .collect::<Vec<(LocalName, FormDatum)>>(),
+ None => Vec::new(),
+ };
FormData {
reflector_: Reflector::new(),
- data: DOMRefCell::new(hashmap),
+ data: DomRefCell::new(data),
}
}
- pub fn new(form: Option<&HTMLFormElement>, global: &GlobalScope) -> Root<FormData> {
- reflect_dom_object(box FormData::new_inherited(form),
- global, FormDataWrap)
+ pub fn new(form_datums: Option<Vec<FormDatum>>, global: &GlobalScope) -> DomRoot<FormData> {
+ reflect_dom_object(Box::new(FormData::new_inherited(form_datums)), global)
}
- pub fn Constructor(global: &GlobalScope, form: Option<&HTMLFormElement>) -> Fallible<Root<FormData>> {
- // TODO: Construct form data set for form if it is supplied
- Ok(FormData::new(form, global))
+ // https://xhr.spec.whatwg.org/#dom-formdata
+ #[allow(non_snake_case)]
+ pub fn Constructor(
+ global: &GlobalScope,
+ form: Option<&HTMLFormElement>,
+ ) -> Fallible<DomRoot<FormData>> {
+ if let Some(opt_form) = form {
+ return match opt_form.get_form_dataset(None, None) {
+ Some(form_datums) => Ok(FormData::new(Some(form_datums), global)),
+ None => Err(Error::InvalidState),
+ };
+ }
+
+ Ok(FormData::new(None, global))
}
}
@@ -67,11 +71,9 @@ impl FormDataMethods for FormData {
value: FormDatumValue::String(DOMString::from(str_value.0)),
};
- let mut data = self.data.borrow_mut();
- match data.entry(LocalName::from(name.0)) {
- Occupied(entry) => entry.into_mut().push(datum),
- Vacant(entry) => { entry.insert(vec!(datum)); }
- }
+ self.data
+ .borrow_mut()
+ .push((LocalName::from(name.0), datum));
}
#[allow(unrooted_must_root)]
@@ -80,90 +82,134 @@ impl FormDataMethods for FormData {
let datum = FormDatum {
ty: DOMString::from("file"),
name: DOMString::from(name.0.clone()),
- value: FormDatumValue::File(Root::from_ref(&*self.create_an_entry(blob, filename))),
+ value: FormDatumValue::File(DomRoot::from_ref(&*self.create_an_entry(blob, filename))),
};
- let mut data = self.data.borrow_mut();
-
- match data.entry(LocalName::from(name.0)) {
- Occupied(entry) => entry.into_mut().push(datum),
- Vacant(entry) => { entry.insert(vec!(datum)); },
- }
+ self.data
+ .borrow_mut()
+ .push((LocalName::from(name.0), datum));
}
// https://xhr.spec.whatwg.org/#dom-formdata-delete
fn Delete(&self, name: USVString) {
- self.data.borrow_mut().remove(&LocalName::from(name.0));
+ self.data
+ .borrow_mut()
+ .retain(|(datum_name, _)| datum_name != &LocalName::from(name.0.clone()));
}
// https://xhr.spec.whatwg.org/#dom-formdata-get
fn Get(&self, name: USVString) -> Option<FileOrUSVString> {
- self.data.borrow()
- .get(&LocalName::from(name.0))
- .map(|entry| match entry[0].value {
- FormDatumValue::String(ref s) => FileOrUSVString::USVString(USVString(s.to_string())),
- FormDatumValue::File(ref b) => FileOrUSVString::File(Root::from_ref(&*b)),
- })
+ self.data
+ .borrow()
+ .iter()
+ .filter(|(datum_name, _)| datum_name == &LocalName::from(name.0.clone()))
+ .next()
+ .map(|(_, datum)| match &datum.value {
+ FormDatumValue::String(ref s) => {
+ FileOrUSVString::USVString(USVString(s.to_string()))
+ },
+ FormDatumValue::File(ref b) => FileOrUSVString::File(DomRoot::from_ref(&*b)),
+ })
}
// https://xhr.spec.whatwg.org/#dom-formdata-getall
fn GetAll(&self, name: USVString) -> Vec<FileOrUSVString> {
- self.data.borrow()
- .get(&LocalName::from(name.0))
- .map_or(vec![], |data|
- data.iter().map(|item| match item.value {
- FormDatumValue::String(ref s) => FileOrUSVString::USVString(USVString(s.to_string())),
- FormDatumValue::File(ref b) => FileOrUSVString::File(Root::from_ref(&*b)),
- }).collect()
- )
+ self.data
+ .borrow()
+ .iter()
+ .filter_map(|datum| {
+ if datum.0 != LocalName::from(name.0.clone()) {
+ return None;
+ }
+
+ Some(match &datum.1.value {
+ FormDatumValue::String(ref s) => {
+ FileOrUSVString::USVString(USVString(s.to_string()))
+ },
+ FormDatumValue::File(ref b) => FileOrUSVString::File(DomRoot::from_ref(&*b)),
+ })
+ })
+ .collect()
}
// https://xhr.spec.whatwg.org/#dom-formdata-has
fn Has(&self, name: USVString) -> bool {
- self.data.borrow().contains_key(&LocalName::from(name.0))
+ self.data
+ .borrow()
+ .iter()
+ .any(|(datum_name, _0)| datum_name == &LocalName::from(name.0.clone()))
}
// https://xhr.spec.whatwg.org/#dom-formdata-set
fn Set(&self, name: USVString, str_value: USVString) {
- self.data.borrow_mut().insert(LocalName::from(name.0.clone()), vec![FormDatum {
- ty: DOMString::from("string"),
- name: DOMString::from(name.0),
- value: FormDatumValue::String(DOMString::from(str_value.0)),
- }]);
+ let mut data = self.data.borrow_mut();
+ let local_name = LocalName::from(name.0.clone());
+
+ data.retain(|(datum_name, _)| datum_name != &local_name);
+
+ data.push((
+ local_name,
+ FormDatum {
+ ty: DOMString::from("string"),
+ name: DOMString::from(name.0),
+ value: FormDatumValue::String(DOMString::from(str_value.0)),
+ },
+ ));
}
#[allow(unrooted_must_root)]
// https://xhr.spec.whatwg.org/#dom-formdata-set
fn Set_(&self, name: USVString, blob: &Blob, filename: Option<USVString>) {
- self.data.borrow_mut().insert(LocalName::from(name.0.clone()), vec![FormDatum {
- ty: DOMString::from("file"),
- name: DOMString::from(name.0),
- value: FormDatumValue::File(Root::from_ref(&*self.create_an_entry(blob, filename))),
- }]);
- }
+ let mut data = self.data.borrow_mut();
+ let local_name = LocalName::from(name.0.clone());
-}
+ data.retain(|(datum_name, _)| datum_name != &local_name);
+ data.push((
+ LocalName::from(name.0.clone()),
+ FormDatum {
+ ty: DOMString::from("file"),
+ name: DOMString::from(name.0),
+ value: FormDatumValue::File(DomRoot::from_ref(
+ &*self.create_an_entry(blob, filename),
+ )),
+ },
+ ));
+ }
+}
impl FormData {
// https://xhr.spec.whatwg.org/#create-an-entry
- // Steps 3-4.
- fn create_an_entry(&self, blob: &Blob, opt_filename: Option<USVString>) -> Root<File> {
+ fn create_an_entry(&self, blob: &Blob, opt_filename: Option<USVString>) -> DomRoot<File> {
+ // Steps 3-4
let name = match opt_filename {
Some(filename) => DOMString::from(filename.0),
- None if blob.downcast::<File>().is_none() => DOMString::from("blob"),
- None => DOMString::from(""),
+ None => match blob.downcast::<File>() {
+ None => DOMString::from("blob"),
+ // If it is already a file and no filename was given,
+ // then neither step 3 nor step 4 happens, so instead of
+ // creating a new File object we use the existing one.
+ Some(file) => {
+ return DomRoot::from_ref(file);
+ },
+ },
};
let bytes = blob.get_bytes().unwrap_or(vec![]);
- File::new(&self.global(), BlobImpl::new_from_bytes(bytes), name, None, &blob.type_string())
+ File::new(
+ &self.global(),
+ BlobImpl::new_from_bytes(bytes, blob.type_string()),
+ name,
+ None,
+ )
}
pub fn datums(&self) -> Vec<FormDatum> {
- self.data.borrow().values()
- .flat_map(|value| value.iter())
- .map(|value| value.clone())
+ self.data
+ .borrow()
+ .iter()
+ .map(|(_, datum)| datum.clone())
.collect()
}
}
@@ -173,28 +219,21 @@ impl Iterable for FormData {
type Value = FileOrUSVString;
fn get_iterable_length(&self) -> u32 {
- self.data.borrow().values().map(|value| value.len()).sum::<usize>() as u32
+ self.data.borrow().len() as u32
}
fn get_value_at_index(&self, n: u32) -> FileOrUSVString {
let data = self.data.borrow();
- let value = &data.values()
- .flat_map(|value| value.iter())
- .nth(n as usize)
- .unwrap()
- .value;
- match *value {
+ let datum = &data.get(n as usize).unwrap().1;
+ match &datum.value {
FormDatumValue::String(ref s) => FileOrUSVString::USVString(USVString(s.to_string())),
- FormDatumValue::File(ref b) => FileOrUSVString::File(Root::from_ref(&*b)),
+ FormDatumValue::File(ref b) => FileOrUSVString::File(DomRoot::from_ref(b)),
}
}
fn get_key_at_index(&self, n: u32) -> USVString {
let data = self.data.borrow();
- let value = &data.iter()
- .flat_map(|(key, value)| iter::repeat(key).take(value.len()))
- .nth(n as usize)
- .unwrap();
- USVString(value.to_string())
+ let key = &data.get(n as usize).unwrap().0;
+ USVString(key.to_string())
}
}