aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2020-02-24 21:18:10 -0500
committerGitHub <noreply@github.com>2020-02-24 21:18:10 -0500
commit145c89a2d49b7a0c2842e99dff65da4d8164bf7d (patch)
tree77953fcbca71db4cec36c60594796df871d93239 /components/script
parente3a5f36fb21d8a93c248016bdd59b8878713a8a3 (diff)
parent50b495684ed37042fbc0b895f1e6d0a732b9d378 (diff)
downloadservo-145c89a2d49b7a0c2842e99dff65da4d8164bf7d.tar.gz
servo-145c89a2d49b7a0c2842e99dff65da4d8164bf7d.zip
Auto merge of #25499 - NeverHappened:implement-form-dirname, r=jdm
Implement dirname support for form element Added support for dirname in input on form submit Added Dir getter / setter for HTMLElement NOT YET Added get directionality according to https://html.spec.whatwg.org/multipage/dom.html#the-directionality - [X] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #25379 (GitHub issue number if applicable)
Diffstat (limited to 'components/script')
-rw-r--r--components/script/Cargo.toml1
-rw-r--r--components/script/dom/element.rs10
-rw-r--r--components/script/dom/htmlelement.rs48
-rw-r--r--components/script/dom/htmlformelement.rs25
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs31
-rwxr-xr-xcomponents/script/dom/htmltextareaelement.rs12
-rw-r--r--components/script/dom/node.rs20
-rw-r--r--components/script/dom/webidls/HTMLElement.webidl4
-rw-r--r--components/script/dom/webidls/HTMLTextAreaElement.webidl4
9 files changed, 148 insertions, 7 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index 93813953aac..03eac6cae65 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -110,6 +110,7 @@ style_traits = {path = "../style_traits"}
swapper = "0.1"
tendril = {version = "0.4.1", features = ["encoding_rs"]}
time = "0.1.12"
+unicode-bidi = "0.3.4"
unicode-segmentation = "1.1.0"
url = "2.0"
utf-8 = "0.7"
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index eecff289cdb..268b263fc41 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -540,6 +540,16 @@ impl Element {
}
true // whatwg/html#5239
}
+
+ // https://html.spec.whatwg.org/multipage/#the-directionality
+ pub fn directionality(&self) -> String {
+ self.downcast::<HTMLElement>()
+ .and_then(|html_element| html_element.directionality())
+ .unwrap_or_else(|| {
+ let node = self.upcast::<Node>();
+ node.parent_directionality()
+ })
+ }
}
#[allow(unsafe_code)]
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index ac0f99416c2..00d7a64ed32 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -27,6 +27,7 @@ use crate::dom::htmlframesetelement::HTMLFrameSetElement;
use crate::dom::htmlhtmlelement::HTMLHtmlElement;
use crate::dom::htmlinputelement::{HTMLInputElement, InputType};
use crate::dom::htmllabelelement::HTMLLabelElement;
+use crate::dom::htmltextareaelement::HTMLTextAreaElement;
use crate::dom::node::{document_from_node, window_from_node};
use crate::dom::node::{BindContext, Node, NodeFlags, ShadowIncluding};
use crate::dom::text::Text;
@@ -170,6 +171,11 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#dom-hidden
make_bool_setter!(SetHidden, "hidden");
+ // https://html.spec.whatwg.org/multipage/#the-dir-attribute
+ make_getter!(Dir, "dir");
+ // https://html.spec.whatwg.org/multipage/#the-dir-attribute
+ make_setter!(SetDir, "dir");
+
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
global_event_handlers!(NoOnload);
@@ -767,6 +773,48 @@ impl HTMLElement {
})
.count() as u32
}
+
+ // https://html.spec.whatwg.org/multipage/#the-directionality.
+ // returns Some if can infer direction by itself or from child nodes
+ // returns None if requires to go up to parent
+ pub fn directionality(&self) -> Option<String> {
+ let element_direction: &str = &self.Dir();
+
+ if element_direction == "ltr" {
+ return Some("ltr".to_owned());
+ }
+
+ if element_direction == "rtl" {
+ return Some("rtl".to_owned());
+ }
+
+ if let Some(input) = self.downcast::<HTMLInputElement>() {
+ if input.input_type() == InputType::Tel {
+ return Some("ltr".to_owned());
+ }
+ }
+
+ if element_direction == "auto" {
+ if let Some(directionality) = self
+ .downcast::<HTMLInputElement>()
+ .and_then(|input| input.auto_directionality())
+ {
+ return Some(directionality);
+ }
+
+ if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
+ return Some(area.auto_directionality());
+ }
+ }
+
+ // TODO(NeverHappened): Implement condition
+ // If the element's dir attribute is in the auto state OR
+ // If the element is a bdi element and the dir attribute is not in a defined state
+ // (i.e. it is not present or has an invalid value)
+ // Requires bdi element implementation (https://html.spec.whatwg.org/multipage/#the-bdi-element)
+
+ None
+ }
}
impl VirtualMethods for HTMLElement {
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index adbb790a181..30d1857de9d 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -950,7 +950,6 @@ impl HTMLFormElement {
match element {
HTMLElementTypeId::HTMLInputElement => {
let input = child.downcast::<HTMLInputElement>().unwrap();
-
data_set.append(&mut input.form_datums(submitter, encoding));
},
HTMLElementTypeId::HTMLButtonElement => {
@@ -981,10 +980,30 @@ impl HTMLFormElement {
_ => (),
}
}
+
+ // Step: 5.13. Add an entry if element has dirname attribute
+ // An element can only have a dirname attribute if it is a textarea element
+ // or an input element whose type attribute is in either the Text state or the Search state
+ let child_element = child.downcast::<Element>().unwrap();
+ let input_matches =
+ child_element
+ .downcast::<HTMLInputElement>()
+ .map_or(false, |input| {
+ input.input_type() == InputType::Text ||
+ input.input_type() == InputType::Search
+ });
+ let textarea_matches = child_element.is::<HTMLTextAreaElement>();
+ let dirname = child_element.get_string_attribute(&local_name!("dirname"));
+ if (input_matches || textarea_matches) && !dirname.is_empty() {
+ let dir = DOMString::from(child_element.directionality());
+ data_set.push(FormDatum {
+ ty: DOMString::from("string"),
+ name: dirname,
+ value: FormDatumValue::String(dir),
+ });
+ }
}
data_set
- // TODO: Handle `dirnames` (needs directionality support)
- // https://html.spec.whatwg.org/multipage/#the-directionality
}
/// <https://html.spec.whatwg.org/multipage/#constructing-the-form-data-set>
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index 441206c9dad..a5fefa095ae 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -75,6 +75,7 @@ use std::ptr::NonNull;
use style::attr::AttrValue;
use style::element_state::ElementState;
use style::str::{split_commas, str_join};
+use unicode_bidi::{bidi_class, BidiClass};
const DEFAULT_SUBMIT_VALUE: &'static str = "Submit";
const DEFAULT_RESET_VALUE: &'static str = "Reset";
@@ -327,6 +328,36 @@ impl HTMLInputElement {
)
}
+ pub fn auto_directionality(&self) -> Option<String> {
+ match self.input_type() {
+ InputType::Text | InputType::Search | InputType::Url | InputType::Email => {
+ let value: String = self.Value().to_string();
+ Some(HTMLInputElement::directionality_from_value(&value))
+ },
+ _ => None,
+ }
+ }
+
+ pub fn directionality_from_value(value: &str) -> String {
+ if HTMLInputElement::is_first_strong_character_rtl(value) {
+ "rtl".to_owned()
+ } else {
+ "ltr".to_owned()
+ }
+ }
+
+ fn is_first_strong_character_rtl(value: &str) -> bool {
+ for ch in value.chars() {
+ return match bidi_class(ch) {
+ BidiClass::L => false,
+ BidiClass::AL => true,
+ BidiClass::R => true,
+ _ => continue,
+ };
+ }
+ false
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-input-value
// https://html.spec.whatwg.org/multipage/#concept-input-apply
fn value_mode(&self) -> ValueMode {
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index 9fd316e3a18..d077d9eec8f 100755
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -22,6 +22,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlfieldsetelement::HTMLFieldSetElement;
use crate::dom::htmlformelement::{FormControl, HTMLFormElement};
+use crate::dom::htmlinputelement::HTMLInputElement;
use crate::dom::keyboardevent::KeyboardEvent;
use crate::dom::node::{document_from_node, window_from_node};
use crate::dom::node::{
@@ -173,6 +174,11 @@ impl HTMLTextAreaElement {
)
}
+ pub fn auto_directionality(&self) -> String {
+ let value: String = self.Value().to_string();
+ return HTMLInputElement::directionality_from_value(&value);
+ }
+
fn update_placeholder_shown_state(&self) {
let has_placeholder = !self.placeholder.borrow().is_empty();
let has_value = !self.textinput.borrow().is_empty();
@@ -205,6 +211,12 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
// https://html.spec.whatwg.org/multipage/#dom-textarea-cols
make_limited_uint_setter!(SetCols, "cols", DEFAULT_COLS);
+ // https://html.spec.whatwg.org/multipage/#dom-input-dirName
+ make_getter!(DirName, "dirname");
+
+ // https://html.spec.whatwg.org/multipage/#dom-input-dirName
+ make_setter!(SetDirName, "dirname");
+
// https://html.spec.whatwg.org/multipage/#dom-fe-disabled
make_bool_getter!(Disabled, "disabled");
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index c1da57eae88..05b81a84d5d 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -440,6 +440,26 @@ impl Node {
.upcast::<Event>()
.dispatch(self.upcast::<EventTarget>(), false);
}
+
+ pub fn parent_directionality(&self) -> String {
+ let mut current = self.GetParentNode();
+
+ loop {
+ match current {
+ Some(node) => {
+ if let Some(directionality) = node
+ .downcast::<HTMLElement>()
+ .and_then(|html_element| html_element.directionality())
+ {
+ return directionality;
+ } else {
+ current = node.GetParentNode();
+ }
+ },
+ None => return "ltr".to_owned(),
+ }
+ }
+ }
}
pub struct QuerySelectorIterator {
diff --git a/components/script/dom/webidls/HTMLElement.webidl b/components/script/dom/webidls/HTMLElement.webidl
index ef529dc80af..c743c0a7129 100644
--- a/components/script/dom/webidls/HTMLElement.webidl
+++ b/components/script/dom/webidls/HTMLElement.webidl
@@ -14,8 +14,8 @@ interface HTMLElement : Element {
attribute DOMString lang;
[CEReactions]
attribute boolean translate;
- // [CEReactions]
- // attribute DOMString dir;
+ [CEReactions]
+ attribute DOMString dir;
readonly attribute DOMStringMap dataset;
// microdata
diff --git a/components/script/dom/webidls/HTMLTextAreaElement.webidl b/components/script/dom/webidls/HTMLTextAreaElement.webidl
index 99cf18e0c10..b09200f1dc5 100644
--- a/components/script/dom/webidls/HTMLTextAreaElement.webidl
+++ b/components/script/dom/webidls/HTMLTextAreaElement.webidl
@@ -13,8 +13,8 @@ interface HTMLTextAreaElement : HTMLElement {
// attribute boolean autofocus;
[CEReactions, SetterThrows]
attribute unsigned long cols;
- // [CEReactions]
- // attribute DOMString dirName;
+ [CEReactions]
+ attribute DOMString dirName;
[CEReactions]
attribute boolean disabled;
readonly attribute HTMLFormElement? form;