aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Kolupaev <dmitry.klpv@gmail.com>2020-01-28 10:34:10 +0300
committerDmitry Kolupaev <dmitry.klpv@gmail.com>2020-02-25 01:18:20 +0300
commitef49f2e0eb28f3eb6445eff3aa095edc4b8a64d8 (patch)
tree530e0ab4dd56c0512639a2cefc32786c47edd7ff
parent6bc4a7df24df6c7ed41f2ee4c2d38a282760c2b6 (diff)
downloadservo-ef49f2e0eb28f3eb6445eff3aa095edc4b8a64d8.tar.gz
servo-ef49f2e0eb28f3eb6445eff3aa095edc4b8a64d8.zip
Implement dirname for form submit and directionality for element
-rw-r--r--Cargo.lock6
-rw-r--r--components/constellation/constellation.rs2
-rw-r--r--components/embedder_traits/lib.rs2
-rw-r--r--components/script/Cargo.toml1
-rw-r--r--components/script/dom/element.rs64
-rw-r--r--components/script/dom/htmlelement.rs5
-rw-r--r--components/script/dom/htmlformelement.rs18
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs36
-rwxr-xr-xcomponents/script/dom/htmltextareaelement.rs9
-rw-r--r--components/script/dom/webidls/HTMLElement.webidl4
-rw-r--r--components/script/dom/window.rs1
-rw-r--r--tests/wpt/metadata/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html.ini5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl.html32
14 files changed, 178 insertions, 19 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0aebb0c0e24..07524b670c2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4783,6 +4783,7 @@ dependencies = [
"tendril",
"time",
"tinyfiledialogs",
+ "unicode-bidi",
"unicode-segmentation",
"url",
"utf-8",
@@ -6291,13 +6292,12 @@ dependencies = [
[[package]]
name = "unicode-bidi"
-version = "0.3.3"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
+checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
dependencies = [
"matches",
"serde",
- "serde_derive",
]
[[package]]
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 0df1a28c15c..629921035f0 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -1614,7 +1614,7 @@ where
Some(ctx) => ctx.pipeline_id,
None => {
return warn!(
- "LoadUrl for unknow browsing context: {:?}",
+ "LoadUrl for unknown browsing context: {:?}",
top_level_browsing_context_id
);
},
diff --git a/components/embedder_traits/lib.rs b/components/embedder_traits/lib.rs
index 246ef63f250..c13ad617920 100644
--- a/components/embedder_traits/lib.rs
+++ b/components/embedder_traits/lib.rs
@@ -149,7 +149,7 @@ pub enum EmbedderMsg {
ResizeTo(DeviceIntSize),
/// Show dialog to user
Prompt(PromptDefinition, PromptOrigin),
- /// Wether or not to allow a pipeline to load a url.
+ /// Whether or not to allow a pipeline to load a url.
AllowNavigationRequest(PipelineId, ServoUrl),
/// Whether or not to allow script to open a new tab/browser
AllowOpeningBrowser(IpcSender<bool>),
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..bb51ee432fd 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -12,6 +12,7 @@ use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use crate::dom::bindings::codegen::Bindings::ElementBinding;
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
+use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementBinding::HTMLElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods;
@@ -540,6 +541,69 @@ impl Element {
}
true // whatwg/html#5239
}
+
+ /// https://html.spec.whatwg.org/#the-directionality
+ pub fn directionality(&self) -> String {
+ if self.is::<HTMLElement>() {
+ let htmlElement = self.downcast::<HTMLElement>().unwrap();
+ self.html_element_directionality(&htmlElement.Dir())
+ } else {
+ let node = self.upcast::<Node>();
+ self.parent_directionality(node)
+ }
+ }
+
+ fn html_element_directionality(&self, element_direction: &str) -> String {
+ if element_direction == "ltr" {
+ return "ltr".to_owned();
+ }
+
+ if element_direction == "rtl" {
+ return "rtl".to_owned();
+ }
+
+ if self.is::<HTMLInputElement>() {
+ let input = self.downcast::<HTMLInputElement>().unwrap();
+ return input.directionality(element_direction);
+ }
+
+ if self.is::<HTMLTextAreaElement>() {
+ let area = self.downcast::<HTMLTextAreaElement>().unwrap();
+ return area.directionality(element_direction);
+ }
+
+ // TODO(dmitry.klpv): 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/#the-bdi-element)
+
+ let node = self.upcast::<Node>();
+ self.parent_directionality(node)
+ }
+
+ fn parent_directionality(&self, node: &Node) -> String {
+ if !node.has_parent() {
+ return "ltr".to_owned();
+ }
+
+ let parent = node.GetParentNode();
+ match parent {
+ Some(parent) => {
+ if parent.is::<Document>() {
+ return "ltr".to_owned();
+ }
+
+ return if parent.is::<Element>() {
+ let parentHtml = parent.downcast::<Element>().unwrap();
+ parentHtml.directionality()
+ } else {
+ self.parent_directionality(&*parent)
+ };
+ },
+ None => "ltr".to_owned(),
+ }
+ }
}
#[allow(unsafe_code)]
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index ac0f99416c2..48401acc3fd 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -170,6 +170,11 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#dom-hidden
make_bool_setter!(SetHidden, "hidden");
+ // https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute
+ make_getter!(Dir, "dir");
+ // https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute
+ make_setter!(SetDir, "dir");
+
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
global_event_handlers!(NoOnload);
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index adbb790a181..ffd0d111cad 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -745,6 +745,8 @@ impl HTMLFormElement {
.map(|field| (&*field.name, field.replace_value(charset))),
);
+ println!("New URL: {url}", url = &load_data.url);
+
self.plan_to_navigate(load_data, target);
}
@@ -952,6 +954,20 @@ impl HTMLFormElement {
let input = child.downcast::<HTMLInputElement>().unwrap();
data_set.append(&mut input.form_datums(submitter, encoding));
+
+ // TODO: probably move to input.form_datums(...) function
+ // 4.10.18.2 https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submitting-element-directionality:-the-dirname-attribute
+ let dirname: DOMString = input.DirName();
+ let dirname_str: &str = &*dirname;
+ if !dirname_str.is_empty() {
+ data_set.push(FormDatum {
+ ty: input.Type(),
+ name: DOMString::from_string(dirname_str.to_owned()),
+ value: FormDatumValue::String(DOMString::from(
+ input.directionality("auto"),
+ )),
+ });
+ }
},
HTMLElementTypeId::HTMLButtonElement => {
let button = child.downcast::<HTMLButtonElement>().unwrap();
@@ -983,8 +999,6 @@ impl HTMLFormElement {
}
}
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..298af937a32 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,41 @@ impl HTMLInputElement {
)
}
+ pub fn directionality(&self, element_direction: &str) -> String {
+ match self.input_type() {
+ InputType::Tel => return "ltr".to_owned(),
+ InputType::Text | InputType::Search | InputType::Url | InputType::Email => {
+ if element_direction == "auto" {
+ let value: String = self.Value().to_string();
+ return HTMLInputElement::auto_directionality(&value);
+ }
+ },
+ _ => {},
+ }
+
+ return "ltr".to_owned();
+ }
+
+ pub fn auto_directionality(value: &str) -> String {
+ if HTMLInputElement::first_strong_character_is_rtl(value) {
+ "rtl".to_owned()
+ } else {
+ "ltr".to_owned()
+ }
+ }
+
+ fn first_strong_character_is_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..0cc174cc3c1 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,14 @@ impl HTMLTextAreaElement {
)
}
+ pub fn directionality(&self, element_direction: &str) -> String {
+ if element_direction == "auto" {
+ let value: String = self.Value().to_string();
+ return HTMLInputElement::auto_directionality(&value);
+ }
+ return "ltr".to_owned();
+ }
+
fn update_placeholder_shown_state(&self) {
let has_placeholder = !self.placeholder.borrow().is_empty();
let has_value = !self.textinput.borrow().is_empty();
diff --git a/components/script/dom/webidls/HTMLElement.webidl b/components/script/dom/webidls/HTMLElement.webidl
index ef529dc80af..5300ca8b2a0 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/window.rs b/components/script/dom/window.rs
index ce290caabf7..724a44e9869 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -2017,6 +2017,7 @@ impl Window {
}
// TODO: step 11, navigationType.
// Step 12, 13
+ println!("ScriptThread::navigate");
ScriptThread::navigate(pipeline_id, load_data, replace);
};
}
diff --git a/tests/wpt/metadata/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html.ini b/tests/wpt/metadata/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html.ini
deleted file mode 100644
index 13a9c4d0918..00000000000
--- a/tests/wpt/metadata/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[dirname-ltr.html]
- type: testharness
- [submit element directionality]
- expected: FAIL
-
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html
index 28d1c150b37..6420b5b0c76 100644
--- a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html
@@ -20,10 +20,12 @@
}
var t = async_test("submit element directionality");
- document.querySelector("input").value="foobar";
- document.querySelector("button").click();
+ setTimeout(function() {
+ document.querySelector("input").value="foobar";
+ document.querySelector("button").click();
- document.querySelector("iframe").onload = t.step_func_done(function() {
- assert_equals(getParameterByName("comment.dir"), "ltr");
- });
+ document.querySelector("iframe").onload = t.step_func_done(function() {
+ assert_equals(getParameterByName("comment.dir"), "ltr");
+ });
+ }, 3000);
</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl.html
new file mode 100644
index 00000000000..69eb45c992c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Submitting element directionality: the dirname attribute</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#submitting-element-directionality:-the-dirname-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form action="dirname-ltr-iframe.html" method=get target="iframe">
+ <p><label>Comment: <input type=text id="comment-input" name="comment" dirname="comment.dir" required/></label></p>
+ <p><button type=submit>Post Comment</button></p>
+</form>
+<iframe name="iframe"></iframe>
+<script>
+ function getParameterByName(name) {
+ name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+ var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
+ results = regex.exec(document.querySelector("iframe").contentWindow.location.search);
+ return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
+ }
+
+ var t = async_test("submit element directionality");
+ setTimeout(3000, function() {
+ var rtlValue = "مرحبا";
+ document.querySelector("input").value = rtlValue;
+ document.querySelector("button").click();
+
+ document.querySelector("iframe").onload = t.step_func_done(function() {
+ assert_equals(getParameterByName("comment.dir"), "rtl");
+ });
+ }, 3000);
+</script>