From f73e1453caf583839901b1edd4bb6349ee9f5e87 Mon Sep 17 00:00:00 2001 From: Chintan Gandhi Date: Wed, 27 Nov 2019 10:37:32 -0500 Subject: [PATCH 01/13] uncomment the named getter from HTMLFormElement.webidl --- components/script/dom/webidls/HTMLFormElement.webidl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/script/dom/webidls/HTMLFormElement.webidl b/components/script/dom/webidls/HTMLFormElement.webidl index f48726c343a..13ffbf4dfe8 100644 --- a/components/script/dom/webidls/HTMLFormElement.webidl +++ b/components/script/dom/webidls/HTMLFormElement.webidl @@ -29,7 +29,7 @@ interface HTMLFormElement : HTMLElement { [SameObject] readonly attribute HTMLFormControlsCollection elements; readonly attribute unsigned long length; getter Element? (unsigned long index); - //getter (RadioNodeList or Element) (DOMString name); + getter (RadioNodeList or Element) (DOMString name); void submit(); [CEReactions] From 2108a85764c4a7f4b9cdc6f2d2b1afaeb7ba4371 Mon Sep 17 00:00:00 2001 From: Chintan Gandhi Date: Tue, 3 Dec 2019 16:12:51 -0500 Subject: [PATCH 02/13] created sourced names w/o past names map part --- components/script/dom/htmlformelement.rs | 75 ++++++++++++++++++++++++ 1 file changed, 75 insertions(+) mode change 100755 => 100644 components/script/dom/htmlformelement.rs diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs old mode 100755 new mode 100644 index b09804e397c..fc96145e25e --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -64,6 +64,8 @@ use std::cell::Cell; use style::attr::AttrValue; use style::str::split_html_space_chars; +use crate::dom::bindings::codegen::UnionTypes::RadioNodeListOrElement; + #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] pub struct GenerationId(u32); @@ -253,6 +255,79 @@ impl HTMLFormElementMethods for HTMLFormElement { let elements = self.Elements(); elements.IndexedGetter(index) } + + fn NamedGetter(&self, name: DOMString) -> Option { + // return Option::Some::; + unimplemented!(); + } + + // https://html.spec.whatwg.org/multipage/forms.html#the-form-element:supported-property-names + fn SupportedPropertyNames(&self) -> Vec { + + enum SourcedNameSource { + Id, + Name, + Past(std::time::Duration) + } + + struct SourcedName { + name: DOMString, + element: DomRoot, + source: SourcedNameSource, + } + + // vector to store sourced names tuple information + let mut sourcedNamesVec: Vec = Vec::new(); + + // let controls = self.controls.borrow_mut(); - line 849 → unsure of which "borrow" to use + let controls = self.controls.borrow(); // line 807 in this file + + // controls - list of form elements + // check all listed elements first, push to sourcedNamesVec as per spec + for child in controls.iter() { + + if child.is_html_element() { // if child.is_listed() + + if child.has_attribute(&local_name!("id")) { + // https://learning-rust.github.io/docs/b2.structs.html + let entry = SourcedName {name: child.get_string_attribute(&local_name!("id")), element: child.root_element(), source: SourcedNameSource::Id}; + sourcedNamesVec.push(entry); + } + else if child.has_attribute(&local_name!("name")) { + let entry = SourcedName {name: child.get_string_attribute(&local_name!("name")), element: child.root_element(), source: SourcedNameSource::Name}; + sourcedNamesVec.push(entry); + } + } + } + + // check img elements now, push to sourcedNamesVec as per spec + for child in controls.iter() { + // https://doc.servo.org/src/script/dom/htmlelement.rs.html#645-665 + // if child.get_string_attribute(&local_name!("type")) == "image" { + + // https://users.rust-lang.org/t/how-check-type-of-variable/33845/7 + if child.is::() { + + if child.has_attribute(&local_name!("id")) { + // https://learning-rust.github.io/docs/b2.structs.html + let entry = SourcedName {name: child.get_string_attribute(&local_name!("id")), element: child.root_element(), source: SourcedNameSource::Id}; + sourcedNamesVec.push(entry); + } + else if child.has_attribute(&local_name!("name")) { + let entry = SourcedName {name: child.get_string_attribute(&local_name!("name")), element: child.root_element(), source: SourcedNameSource::Name}; + sourcedNamesVec.push(entry); + } + } + } + + // return list of names + let mut namesVec: Vec = Vec::new(); + for elem in sourcedNamesVec.iter() { + namesVec.push(elem.name.clone()); + } + + return namesVec; + } } #[derive(Clone, Copy, MallocSizeOf, PartialEq)] From 2ee6150990d2bb58ccf3bd634db640e155164eff Mon Sep 17 00:00:00 2001 From: jaymodi98 Date: Tue, 3 Dec 2019 18:31:16 -0500 Subject: [PATCH 03/13] Removed tidy-test errors --- components/script/dom/htmlformelement.rs | 41 ++++++++++++++++-------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index fc96145e25e..09e055001ab 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -256,18 +256,18 @@ impl HTMLFormElementMethods for HTMLFormElement { elements.IndexedGetter(index) } + // https://html.spec.whatwg.org/multipage/#the-form-element%3Adetermine-the-value-of-a-named-property fn NamedGetter(&self, name: DOMString) -> Option { // return Option::Some::; unimplemented!(); } - // https://html.spec.whatwg.org/multipage/forms.html#the-form-element:supported-property-names + // https://html.spec.whatwg.org/multipage/#the-form-element:supported-property-names fn SupportedPropertyNames(&self) -> Vec { - enum SourcedNameSource { Id, Name, - Past(std::time::Duration) + Past(std::time::Duration), } struct SourcedName { @@ -285,16 +285,23 @@ impl HTMLFormElementMethods for HTMLFormElement { // controls - list of form elements // check all listed elements first, push to sourcedNamesVec as per spec for child in controls.iter() { - - if child.is_html_element() { // if child.is_listed() + if child.is_html_element() { + // if child.is_listed() if child.has_attribute(&local_name!("id")) { // https://learning-rust.github.io/docs/b2.structs.html - let entry = SourcedName {name: child.get_string_attribute(&local_name!("id")), element: child.root_element(), source: SourcedNameSource::Id}; + let entry = SourcedName { + name: child.get_string_attribute(&local_name!("id")), + element: child.root_element(), + source: SourcedNameSource::Id, + }; sourcedNamesVec.push(entry); - } - else if child.has_attribute(&local_name!("name")) { - let entry = SourcedName {name: child.get_string_attribute(&local_name!("name")), element: child.root_element(), source: SourcedNameSource::Name}; + } else if child.has_attribute(&local_name!("name")) { + let entry = SourcedName { + name: child.get_string_attribute(&local_name!("name")), + element: child.root_element(), + source: SourcedNameSource::Name, + }; sourcedNamesVec.push(entry); } } @@ -307,14 +314,20 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://users.rust-lang.org/t/how-check-type-of-variable/33845/7 if child.is::() { - if child.has_attribute(&local_name!("id")) { // https://learning-rust.github.io/docs/b2.structs.html - let entry = SourcedName {name: child.get_string_attribute(&local_name!("id")), element: child.root_element(), source: SourcedNameSource::Id}; + let entry = SourcedName { + name: child.get_string_attribute(&local_name!("id")), + element: child.root_element(), + source: SourcedNameSource::Id, + }; sourcedNamesVec.push(entry); - } - else if child.has_attribute(&local_name!("name")) { - let entry = SourcedName {name: child.get_string_attribute(&local_name!("name")), element: child.root_element(), source: SourcedNameSource::Name}; + } else if child.has_attribute(&local_name!("name")) { + let entry = SourcedName { + name: child.get_string_attribute(&local_name!("name")), + element: child.root_element(), + source: SourcedNameSource::Name, + }; sourcedNamesVec.push(entry); } } From 5e67dbda540338f2cd8b45fb28039763eb165e5b Mon Sep 17 00:00:00 2001 From: hkshah6 Date: Wed, 4 Dec 2019 18:44:57 -0500 Subject: [PATCH 04/13] Fixed is_listed_element() call and DomRoot child reference --- components/script/dom/htmlformelement.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 09e055001ab..43986c49387 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -285,21 +285,21 @@ impl HTMLFormElementMethods for HTMLFormElement { // controls - list of form elements // check all listed elements first, push to sourcedNamesVec as per spec for child in controls.iter() { - if child.is_html_element() { + if child.downcast::().map_or(false, |c| c.is_listed_element()) { // if child.is_listed() if child.has_attribute(&local_name!("id")) { // https://learning-rust.github.io/docs/b2.structs.html let entry = SourcedName { name: child.get_string_attribute(&local_name!("id")), - element: child.root_element(), + element: DomRoot::from_ref(&*child), source: SourcedNameSource::Id, }; sourcedNamesVec.push(entry); } else if child.has_attribute(&local_name!("name")) { let entry = SourcedName { name: child.get_string_attribute(&local_name!("name")), - element: child.root_element(), + element: DomRoot::from_ref(&*child), source: SourcedNameSource::Name, }; sourcedNamesVec.push(entry); @@ -318,14 +318,14 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://learning-rust.github.io/docs/b2.structs.html let entry = SourcedName { name: child.get_string_attribute(&local_name!("id")), - element: child.root_element(), + element: DomRoot::from_ref(&*child), source: SourcedNameSource::Id, }; sourcedNamesVec.push(entry); } else if child.has_attribute(&local_name!("name")) { let entry = SourcedName { name: child.get_string_attribute(&local_name!("name")), - element: child.root_element(), + element: DomRoot::from_ref(&*child), source: SourcedNameSource::Name, }; sourcedNamesVec.push(entry); From 50fdae7a8c4f3f513d88b358e87dc8361e3df179 Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Thu, 5 Dec 2019 14:43:29 -0500 Subject: [PATCH 05/13] implemented NamedGetter and other suggestions --- components/script/dom/htmlformelement.rs | 88 +++++++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 43986c49387..8fec745e870 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -65,6 +65,8 @@ use style::attr::AttrValue; use style::str::split_html_space_chars; use crate::dom::bindings::codegen::UnionTypes::RadioNodeListOrElement; +use crate::dom::radionodelist::RadioNodeList; +use std::collections::HashMap; #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] pub struct GenerationId(u32); @@ -78,6 +80,7 @@ pub struct HTMLFormElement { elements: DomOnceCell, generation_id: Cell, controls: DomRefCell>>, + past_names_map: DomRefCell>>, } impl HTMLFormElement { @@ -93,6 +96,7 @@ impl HTMLFormElement { elements: Default::default(), generation_id: Cell::new(GenerationId(0)), controls: DomRefCell::new(Vec::new()), + past_names_map: DomRefCell::new(HashMap::new()), } } @@ -258,8 +262,83 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://html.spec.whatwg.org/multipage/#the-form-element%3Adetermine-the-value-of-a-named-property fn NamedGetter(&self, name: DOMString) -> Option { - // return Option::Some::; - unimplemented!(); + // unimplemented!(); + let window = window_from_node(self); + + // Q2. ERROR in the following declaration - check the attached screenshot (image2) + let mut candidates: Vec> = Vec::new(); + + // let mut candidates: RadioNodeList = RadioNodeList::new(&window, Dom); + + let controls = self.controls.borrow(); + + for child in controls.iter() { + if child + .downcast::() + .map_or(false, |c| c.is_listed_element()) + { + if child.has_attribute(&local_name!("id")) || + (child.has_attribute(&local_name!("name")) && + child.get_string_attribute(&local_name!("name")) == name) + { + // println!("{:?}", child.what_is_this()); + candidates.push(Dom::from_ref(&*child.downcast::().unwrap())); + } + } + } + + if candidates.len() == 0 { + for child in controls.iter() { + if child.is::() { + if child.has_attribute(&local_name!("id")) || + (child.has_attribute(&local_name!("name")) && + child.get_string_attribute(&local_name!("name")) == name) + { + candidates.push(Dom::from_ref(&*child.downcast::().unwrap())); + } + } + } + } + + let mut past_names_map = self.past_names_map.borrow_mut(); + + if candidates.len() == 0 { + for (key, val) in past_names_map.iter() { + if *key == name { + // println!("{:?}", val.what_is_this()); + return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( + &*val.upcast::(), + ))); + } + } + } + + if candidates.len() > 1 { + let mut candidatesDomRoot: Vec> = Vec::new(); + for cand in candidates.iter() { + // println!("{:?}", cand.what_is_this()); + candidatesDomRoot.push(DomRoot::from_ref(&*cand.upcast::())); + } + + // Q1. ERROR in the following line - check the attached screenshot (image1) + // Related link for potential fix: https://stackoverflow.com/a/26953620/11978763 + // we are unsure of how to incorporate this + return Some(RadioNodeListOrElement::RadioNodeList( + RadioNodeList::new_simple_list(&window, candidatesDomRoot.iter()), + )); + } + + let element_node = &candidates[0]; + if past_names_map.contains_key(&name) { + let stat = past_names_map.entry(name).or_insert(element_node.clone()); + *stat = element_node.clone(); + } else { + past_names_map.insert(name, element_node.clone()); + } + + return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( + &*element_node.upcast::(), + ))); } // https://html.spec.whatwg.org/multipage/#the-form-element:supported-property-names @@ -285,7 +364,10 @@ impl HTMLFormElementMethods for HTMLFormElement { // controls - list of form elements // check all listed elements first, push to sourcedNamesVec as per spec for child in controls.iter() { - if child.downcast::().map_or(false, |c| c.is_listed_element()) { + if child + .downcast::() + .map_or(false, |c| c.is_listed_element()) + { // if child.is_listed() if child.has_attribute(&local_name!("id")) { From 7b968a3ca8b4aac4dae594682dd33999a3cbc298 Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Thu, 5 Dec 2019 19:50:10 -0500 Subject: [PATCH 06/13] NamedGetter completed and fixed issues --- components/script/dom/htmlformelement.rs | 48 ++++++++---------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 8fec745e870..52fc70c5bb3 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -80,7 +80,7 @@ pub struct HTMLFormElement { elements: DomOnceCell, generation_id: Cell, controls: DomRefCell>>, - past_names_map: DomRefCell>>, + past_names_map: DomRefCell>>, } impl HTMLFormElement { @@ -262,13 +262,9 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://html.spec.whatwg.org/multipage/#the-form-element%3Adetermine-the-value-of-a-named-property fn NamedGetter(&self, name: DOMString) -> Option { - // unimplemented!(); let window = window_from_node(self); - // Q2. ERROR in the following declaration - check the attached screenshot (image2) - let mut candidates: Vec> = Vec::new(); - - // let mut candidates: RadioNodeList = RadioNodeList::new(&window, Dom); + let mut candidates: Vec> = Vec::new(); let controls = self.controls.borrow(); @@ -281,8 +277,7 @@ impl HTMLFormElementMethods for HTMLFormElement { (child.has_attribute(&local_name!("name")) && child.get_string_attribute(&local_name!("name")) == name) { - // println!("{:?}", child.what_is_this()); - candidates.push(Dom::from_ref(&*child.downcast::().unwrap())); + candidates.push(DomRoot::from_ref(&*child.upcast::())); } } } @@ -294,7 +289,7 @@ impl HTMLFormElementMethods for HTMLFormElement { (child.has_attribute(&local_name!("name")) && child.get_string_attribute(&local_name!("name")) == name) { - candidates.push(Dom::from_ref(&*child.downcast::().unwrap())); + candidates.push(DomRoot::from_ref(&*child.upcast::())); } } } @@ -303,41 +298,28 @@ impl HTMLFormElementMethods for HTMLFormElement { let mut past_names_map = self.past_names_map.borrow_mut(); if candidates.len() == 0 { - for (key, val) in past_names_map.iter() { - if *key == name { - // println!("{:?}", val.what_is_this()); - return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( - &*val.upcast::(), - ))); - } + if past_names_map.contains_key(&name) { + return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( + &*past_names_map.get(&name).unwrap(), + ))); } + return None; } if candidates.len() > 1 { - let mut candidatesDomRoot: Vec> = Vec::new(); - for cand in candidates.iter() { - // println!("{:?}", cand.what_is_this()); - candidatesDomRoot.push(DomRoot::from_ref(&*cand.upcast::())); - } - - // Q1. ERROR in the following line - check the attached screenshot (image1) - // Related link for potential fix: https://stackoverflow.com/a/26953620/11978763 - // we are unsure of how to incorporate this return Some(RadioNodeListOrElement::RadioNodeList( - RadioNodeList::new_simple_list(&window, candidatesDomRoot.iter()), + RadioNodeList::new_simple_list(&window, candidates.into_iter()), )); } let element_node = &candidates[0]; - if past_names_map.contains_key(&name) { - let stat = past_names_map.entry(name).or_insert(element_node.clone()); - *stat = element_node.clone(); - } else { - past_names_map.insert(name, element_node.clone()); - } + past_names_map.insert( + name, + Dom::from_ref(&*element_node.downcast::().unwrap()), + ); return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( - &*element_node.upcast::(), + &*element_node.downcast::().unwrap(), ))); } From 16b9efc406399b3d03c7044a9dd99205c9870966 Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Fri, 6 Dec 2019 00:40:43 -0500 Subject: [PATCH 07/13] updated past_names_map to save time info --- components/script/dom/bindings/trace.rs | 4 +++- components/script/dom/htmlformelement.rs | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index fbd4da02d5b..7170200e4cd 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -143,13 +143,15 @@ use style::values::specified::Length; use tendril::fmt::UTF8; use tendril::stream::LossyDecoder; use tendril::{StrTendril, TendrilSink}; -use time::{Duration, Timespec}; +use time::{Duration, Timespec, Tm}; use uuid::Uuid; use webgpu::{WebGPU, WebGPUAdapter}; use webrender_api::{DocumentId, ImageKey, RenderApiSender}; use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; use webxr_api::SwapChainId as WebXRSwapChainId; +unsafe_no_jsmanaged_fields!(Tm); + /// A trait to allow tracing (only) DOM objects. pub unsafe trait JSTraceable { /// Trace `self`. diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 52fc70c5bb3..ba352511bf8 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -67,6 +67,8 @@ use style::str::split_html_space_chars; use crate::dom::bindings::codegen::UnionTypes::RadioNodeListOrElement; use crate::dom::radionodelist::RadioNodeList; use std::collections::HashMap; +use time::{now, Tm, Duration}; + #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] pub struct GenerationId(u32); @@ -80,7 +82,7 @@ pub struct HTMLFormElement { elements: DomOnceCell, generation_id: Cell, controls: DomRefCell>>, - past_names_map: DomRefCell>>, + past_names_map: DomRefCell, Tm)>>, } impl HTMLFormElement { @@ -300,7 +302,7 @@ impl HTMLFormElementMethods for HTMLFormElement { if candidates.len() == 0 { if past_names_map.contains_key(&name) { return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( - &*past_names_map.get(&name).unwrap(), + &*past_names_map.get(&name).unwrap().0, ))); } return None; @@ -315,7 +317,7 @@ impl HTMLFormElementMethods for HTMLFormElement { let element_node = &candidates[0]; past_names_map.insert( name, - Dom::from_ref(&*element_node.downcast::().unwrap()), + (Dom::from_ref(&*element_node.downcast::().unwrap()), now()), ); return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( @@ -328,7 +330,7 @@ impl HTMLFormElementMethods for HTMLFormElement { enum SourcedNameSource { Id, Name, - Past(std::time::Duration), + Past(Duration), } struct SourcedName { From 159194b0f900c4ef126a2db9897e052cf7582186 Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Fri, 6 Dec 2019 01:24:52 -0500 Subject: [PATCH 08/13] run tidy check and added comments --- components/script/dom/htmlformelement.rs | 40 +++++++++++------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index ba352511bf8..b39bc1cf58a 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -67,8 +67,7 @@ use style::str::split_html_space_chars; use crate::dom::bindings::codegen::UnionTypes::RadioNodeListOrElement; use crate::dom::radionodelist::RadioNodeList; use std::collections::HashMap; -use time::{now, Tm, Duration}; - +use time::{now, Duration, Tm}; #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] pub struct GenerationId(u32); @@ -264,12 +263,10 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://html.spec.whatwg.org/multipage/#the-form-element%3Adetermine-the-value-of-a-named-property fn NamedGetter(&self, name: DOMString) -> Option { - let window = window_from_node(self); - let mut candidates: Vec> = Vec::new(); let controls = self.controls.borrow(); - + // Step 1 for child in controls.iter() { if child .downcast::() @@ -283,7 +280,7 @@ impl HTMLFormElementMethods for HTMLFormElement { } } } - + // Step 2 if candidates.len() == 0 { for child in controls.iter() { if child.is::() { @@ -299,6 +296,7 @@ impl HTMLFormElementMethods for HTMLFormElement { let mut past_names_map = self.past_names_map.borrow_mut(); + // Step 3 if candidates.len() == 0 { if past_names_map.contains_key(&name) { return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( @@ -308,18 +306,26 @@ impl HTMLFormElementMethods for HTMLFormElement { return None; } + // Step 4 if candidates.len() > 1 { + let window = window_from_node(self); + return Some(RadioNodeListOrElement::RadioNodeList( RadioNodeList::new_simple_list(&window, candidates.into_iter()), )); } + // Step 5 let element_node = &candidates[0]; past_names_map.insert( name, - (Dom::from_ref(&*element_node.downcast::().unwrap()), now()), + ( + Dom::from_ref(&*element_node.downcast::().unwrap()), + now(), + ), ); + // Step 6 return Some(RadioNodeListOrElement::Element(DomRoot::from_ref( &*element_node.downcast::().unwrap(), ))); @@ -327,6 +333,7 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://html.spec.whatwg.org/multipage/#the-form-element:supported-property-names fn SupportedPropertyNames(&self) -> Vec { + // Step 1 enum SourcedNameSource { Id, Name, @@ -339,23 +346,17 @@ impl HTMLFormElementMethods for HTMLFormElement { source: SourcedNameSource, } - // vector to store sourced names tuple information let mut sourcedNamesVec: Vec = Vec::new(); - // let controls = self.controls.borrow_mut(); - line 849 → unsure of which "borrow" to use - let controls = self.controls.borrow(); // line 807 in this file + let controls = self.controls.borrow(); - // controls - list of form elements - // check all listed elements first, push to sourcedNamesVec as per spec + // Step 2 for child in controls.iter() { if child .downcast::() .map_or(false, |c| c.is_listed_element()) { - // if child.is_listed() - if child.has_attribute(&local_name!("id")) { - // https://learning-rust.github.io/docs/b2.structs.html let entry = SourcedName { name: child.get_string_attribute(&local_name!("id")), element: DomRoot::from_ref(&*child), @@ -373,15 +374,10 @@ impl HTMLFormElementMethods for HTMLFormElement { } } - // check img elements now, push to sourcedNamesVec as per spec + // Step 3 for child in controls.iter() { - // https://doc.servo.org/src/script/dom/htmlelement.rs.html#645-665 - // if child.get_string_attribute(&local_name!("type")) == "image" { - - // https://users.rust-lang.org/t/how-check-type-of-variable/33845/7 if child.is::() { if child.has_attribute(&local_name!("id")) { - // https://learning-rust.github.io/docs/b2.structs.html let entry = SourcedName { name: child.get_string_attribute(&local_name!("id")), element: DomRoot::from_ref(&*child), @@ -399,7 +395,7 @@ impl HTMLFormElementMethods for HTMLFormElement { } } - // return list of names + // Step 8 let mut namesVec: Vec = Vec::new(); for elem in sourcedNamesVec.iter() { namesVec.push(elem.name.clone()); From 575f7f5670371da7113fd545a494b3c219bebb29 Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Fri, 6 Dec 2019 19:52:10 -0500 Subject: [PATCH 09/13] partially implemented SupportedPropertyNames --- components/script/dom/htmlformelement.rs | 28 ++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index b39bc1cf58a..0fafed06f40 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -363,7 +363,8 @@ impl HTMLFormElementMethods for HTMLFormElement { source: SourcedNameSource::Id, }; sourcedNamesVec.push(entry); - } else if child.has_attribute(&local_name!("name")) { + } + if child.has_attribute(&local_name!("name")) { let entry = SourcedName { name: child.get_string_attribute(&local_name!("name")), element: DomRoot::from_ref(&*child), @@ -384,7 +385,8 @@ impl HTMLFormElementMethods for HTMLFormElement { source: SourcedNameSource::Id, }; sourcedNamesVec.push(entry); - } else if child.has_attribute(&local_name!("name")) { + } + if child.has_attribute(&local_name!("name")) { let entry = SourcedName { name: child.get_string_attribute(&local_name!("name")), element: DomRoot::from_ref(&*child), @@ -395,6 +397,28 @@ impl HTMLFormElementMethods for HTMLFormElement { } } + // Step 4 + let past_names_map = self.past_names_map.borrow(); + for (key, val) in past_names_map.iter() { + let entry = SourcedName { + name: key.clone(), + element: DomRoot::from_ref(&*val.0), + source: SourcedNameSource::Past(now()-val.1), // calculate difference now()-val.1 to find age + }; + sourcedNamesVec.push(entry); + } + + // Step 5 + // TODO need to sort as per spec. This is a partially implemented function. + // Kindly guide us on how to refine this function further. + sourcedNamesVec.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); + + // Step 6 + sourcedNamesVec.retain(|sn| !sn.name.to_string().is_empty()); + + // Step 7 + // Q1. Unable to clearly understand. It seems to contradict with step 4. + // Step 8 let mut namesVec: Vec = Vec::new(); for elem in sourcedNamesVec.iter() { From a935e00e21c595322cdcabed1f9379a9537966fa Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Fri, 6 Dec 2019 23:41:49 -0500 Subject: [PATCH 10/13] sorting partially done for Step 6 of SupportedPropertyNames --- components/script/dom/htmlformelement.rs | 35 +++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 0fafed06f40..43e09fb6061 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -69,6 +69,8 @@ use crate::dom::radionodelist::RadioNodeList; use std::collections::HashMap; use time::{now, Duration, Tm}; +// use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods; + #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] pub struct GenerationId(u32); @@ -334,12 +336,22 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://html.spec.whatwg.org/multipage/#the-form-element:supported-property-names fn SupportedPropertyNames(&self) -> Vec { // Step 1 + #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] enum SourcedNameSource { Id, Name, Past(Duration), } + impl SourcedNameSource { + fn is_past(&self) -> bool { + match self { + SourcedNameSource::Past(..) => true, + _ => false, + } + } + } + struct SourcedName { name: DOMString, element: DomRoot, @@ -403,15 +415,30 @@ impl HTMLFormElementMethods for HTMLFormElement { let entry = SourcedName { name: key.clone(), element: DomRoot::from_ref(&*val.0), - source: SourcedNameSource::Past(now()-val.1), // calculate difference now()-val.1 to find age + source: SourcedNameSource::Past(now() - val.1), // calculate difference now()-val.1 to find age }; sourcedNamesVec.push(entry); } // Step 5 - // TODO need to sort as per spec. This is a partially implemented function. - // Kindly guide us on how to refine this function further. - sourcedNamesVec.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); + // TODO need to sort as per spec. Kindly guide us how to sort by tree order of the element entry of each tuple. + // Following gives error as CompareDocumentPosition return u16 and not Ordering. + // sourcedNamesVec.sort_by(|a, b| + // a.element.upcast::().CompareDocumentPosition(b.element.upcast::()) + // ); + + // The remaining part where sorting is to be done by putting entries whose source is id first, + // then entries whose source is name, and finally entries whose source is past, + // and sorting entries with the same element and source by their age, oldest first. + // can be done as follows: + + sourcedNamesVec.sort_by(|a, b| { + if a.source.is_past() && b.source.is_past() { + b.source.cmp(&a.source) + } else { + a.source.cmp(&b.source) + } + }); // Step 6 sourcedNamesVec.retain(|sn| !sn.name.to_string().is_empty()); From 4682d9231d9cb96b2febdd38b83dde14f824849e Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Sat, 7 Dec 2019 21:03:28 -0500 Subject: [PATCH 11/13] sorting done for Step 6 of SupportedPropertyNames --- components/script/dom/htmlformelement.rs | 40 +++++++++++++++++------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 43e09fb6061..57dd48ba065 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -69,7 +69,7 @@ use crate::dom::radionodelist::RadioNodeList; use std::collections::HashMap; use time::{now, Duration, Tm}; -// use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods; +use crate::dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods}; #[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] pub struct GenerationId(u32); @@ -421,22 +421,38 @@ impl HTMLFormElementMethods for HTMLFormElement { } // Step 5 - // TODO need to sort as per spec. Kindly guide us how to sort by tree order of the element entry of each tuple. - // Following gives error as CompareDocumentPosition return u16 and not Ordering. - // sourcedNamesVec.sort_by(|a, b| - // a.element.upcast::().CompareDocumentPosition(b.element.upcast::()) - // ); - - // The remaining part where sorting is to be done by putting entries whose source is id first, + // TODO need to sort as per spec. + // if a.CompareDocumentPosition(b) returns 0 that means a=b in which case + // the remaining part where sorting is to be done by putting entries whose source is id first, // then entries whose source is name, and finally entries whose source is past, // and sorting entries with the same element and source by their age, oldest first. - // can be done as follows: + + // if a.CompareDocumentPosition(b) has set NodeConstants::DOCUMENT_POSITION_FOLLOWING + // (this can be checked by bitwise operations) then b would follow a in tree order and + // Ordering::Less should be returned in the closure else Ordering::Greater sourcedNamesVec.sort_by(|a, b| { - if a.source.is_past() && b.source.is_past() { - b.source.cmp(&a.source) + if a.element + .upcast::() + .CompareDocumentPosition(b.element.upcast::()) == + 0 + { + if a.source.is_past() && b.source.is_past() { + b.source.cmp(&a.source) + } else { + a.source.cmp(&b.source) + } } else { - a.source.cmp(&b.source) + if a.element + .upcast::() + .CompareDocumentPosition(b.element.upcast::()) & + NodeConstants::DOCUMENT_POSITION_FOLLOWING == + NodeConstants::DOCUMENT_POSITION_FOLLOWING + { + std::cmp::Ordering::Less + } else { + std::cmp::Ordering::Greater + } } }); From 254bbc3b8c028ab49bc9b109ca3c683c9fceb907 Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Mon, 16 Dec 2019 01:41:59 -0500 Subject: [PATCH 12/13] removed duplicate entries from sourcedNamesVec for step 7 of SupportedPropertyNames --- components/script/dom/htmlformelement.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 57dd48ba065..879d0a7c275 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -274,7 +274,8 @@ impl HTMLFormElementMethods for HTMLFormElement { .downcast::() .map_or(false, |c| c.is_listed_element()) { - if child.has_attribute(&local_name!("id")) || + if (child.has_attribute(&local_name!("id")) && + child.get_string_attribute(&local_name!("id")) == name) || (child.has_attribute(&local_name!("name")) && child.get_string_attribute(&local_name!("name")) == name) { @@ -286,7 +287,8 @@ impl HTMLFormElementMethods for HTMLFormElement { if candidates.len() == 0 { for child in controls.iter() { if child.is::() { - if child.has_attribute(&local_name!("id")) || + if (child.has_attribute(&local_name!("id")) && + child.get_string_attribute(&local_name!("id")) == name) || (child.has_attribute(&local_name!("name")) && child.get_string_attribute(&local_name!("name")) == name) { @@ -459,13 +461,16 @@ impl HTMLFormElementMethods for HTMLFormElement { // Step 6 sourcedNamesVec.retain(|sn| !sn.name.to_string().is_empty()); - // Step 7 - // Q1. Unable to clearly understand. It seems to contradict with step 4. - - // Step 8 + // Step 7-8 let mut namesVec: Vec = Vec::new(); for elem in sourcedNamesVec.iter() { - namesVec.push(elem.name.clone()); + if namesVec + .iter() + .find(|name| name.to_string() == elem.name.to_string()) + .is_none() + { + namesVec.push(elem.name.clone()); + } } return namesVec; From ef8496c7bcceda19b72baa8cd856e26e2fc8a3ff Mon Sep 17 00:00:00 2001 From: Anshul Jethvani Date: Mon, 16 Dec 2019 12:05:06 -0500 Subject: [PATCH 13/13] updated expected test results in log --- .../form-double-submit-2.html.ini | 2 +- .../form-submission-0/form-double-submit.html.ini | 2 +- .../form-submission-algorithm.html.ini | 3 +++ .../HTMLFieldSetElement.html.ini | 3 --- .../the-form-element/form-nameditem.html.ini | 15 --------------- 5 files changed, 5 insertions(+), 20 deletions(-) diff --git a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit-2.html.ini b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit-2.html.ini index f6eecd82b49..638ddaa3a7f 100644 --- a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit-2.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit-2.html.ini @@ -1,5 +1,5 @@ [form-double-submit-2.html] - expected: ERROR + expected: TIMEOUT [preventDefault should allow onclick submit() to succeed] expected: TIMEOUT diff --git a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit.html.ini b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit.html.ini index dce74c6dd71..a951013eb1e 100644 --- a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-double-submit.html.ini @@ -1,5 +1,5 @@ [form-double-submit.html] - expected: ERROR + expected: TIMEOUT [default submit action should supersede onclick submit()] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini index b024b42f41f..fed3bca14a2 100644 --- a/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini @@ -17,3 +17,6 @@ [firing an event named submit; form.requestSubmit()] expected: FAIL + [Cannot navigate (after constructing the entry list)] + expected: FAIL + diff --git a/tests/wpt/metadata/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html.ini b/tests/wpt/metadata/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html.ini index 57d01129025..9bdcfee9aeb 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html.ini @@ -6,6 +6,3 @@ [The elements must return an HTMLFormControlsCollection object] expected: FAIL - [The controls must root at the fieldset element] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/the-form-element/form-nameditem.html.ini b/tests/wpt/metadata/html/semantics/forms/the-form-element/form-nameditem.html.ini index 3ebc134b386..2a540f30348 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-form-element/form-nameditem.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-form-element/form-nameditem.html.ini @@ -3,33 +3,18 @@ [Name for a single element should work] expected: FAIL - [Calling item() on the NodeList returned from the named getter should work] - expected: FAIL - - [Indexed getter on the NodeList returned from the named getter should work] - expected: FAIL - [All listed elements except input type=image should be present in the form] expected: FAIL [Named elements should override builtins] expected: FAIL - [The form attribute should be taken into account for named getters (single element)] - expected: FAIL - [The form attribute should be taken into account for named getters (multiple elements)] expected: FAIL - [Input should only be a named property on the innermost form that contains it] - expected: FAIL - [Trying to set an expando that would shadow an already-existing named property] expected: FAIL - [Trying to set an expando that shadows a named property that gets added later] - expected: FAIL - [Past names map should work correctly] expected: FAIL