aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bindings/js.rs33
-rw-r--r--components/script/dom/document.rs2
-rw-r--r--components/script/dom/htmlcanvaselement.rs63
-rw-r--r--components/script/dom/htmlelement.rs20
-rw-r--r--components/script/dom/htmllabelelement.rs55
-rw-r--r--components/script/dom/virtualmethods.rs4
-rw-r--r--components/script/dom/webidls/HTMLLabelElement.webidl4
7 files changed, 142 insertions, 39 deletions
diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs
index 7abebcac971..a2ec90033ba 100644
--- a/components/script/dom/bindings/js.rs
+++ b/components/script/dom/bindings/js.rs
@@ -273,6 +273,22 @@ impl<T: HeapGCValue> HeapSizeOf for MutHeap<T> {
}
}
+impl<T: Reflectable> PartialEq for MutHeap<JS<T>> {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe {
+ *self.val.get() == *other.val.get()
+ }
+ }
+}
+
+impl<T: Reflectable + PartialEq> PartialEq<T> for MutHeap<JS<T>> {
+ fn eq(&self, other: &T) -> bool {
+ unsafe {
+ **self.val.get() == *other
+ }
+ }
+}
+
/// A holder that provides interior mutability for GC-managed values such as
/// `JS<T>`, with nullability represented by an enclosing Option wrapper.
/// Essentially a `Cell<Option<JS<T>>>`, but safer.
@@ -334,6 +350,23 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> {
*self.ptr.get() = val.map(|p| JS::from_ref(p));
}
}
+
+}
+
+impl<T: Reflectable> PartialEq for MutNullableHeap<JS<T>> {
+ fn eq(&self, other: &Self) -> bool {
+ unsafe {
+ *self.ptr.get() == *other.ptr.get()
+ }
+ }
+}
+
+impl<'a, T: Reflectable> PartialEq<Option<&'a T>> for MutNullableHeap<JS<T>> {
+ fn eq(&self, other: &Option<&T>) -> bool {
+ unsafe {
+ *self.ptr.get() == other.map(JS::from_ref)
+ }
+ }
}
impl<T: HeapGCValue> Default for MutNullableHeap<T> {
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 23d455a1903..771342d0f36 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -1147,7 +1147,7 @@ impl Document {
})
}
- fn get_element_by_id(&self, id: &Atom) -> Option<Root<Element>> {
+ pub fn get_element_by_id(&self, id: &Atom) -> Option<Root<Element>> {
self.idmap.borrow().get(&id).map(|ref elements| (*elements)[0].root())
}
}
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs
index d6e484a2f9d..2fdb8a129e6 100644
--- a/components/script/dom/htmlcanvaselement.rs
+++ b/components/script/dom/htmlcanvaselement.rs
@@ -89,48 +89,41 @@ impl HTMLCanvasElement {
}
}
+pub struct HTMLCanvasData {
+ pub renderer_id: Option<usize>,
+ pub ipc_renderer: Option<IpcSender<CanvasMsg>>,
+ pub width: u32,
+ pub height: u32,
+}
+
pub trait LayoutHTMLCanvasElementHelpers {
- #[allow(unsafe_code)]
- unsafe fn get_renderer_id(&self) -> Option<usize>;
- #[allow(unsafe_code)]
- unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>>;
- #[allow(unsafe_code)]
- unsafe fn get_canvas_width(&self) -> u32;
- #[allow(unsafe_code)]
- unsafe fn get_canvas_height(&self) -> u32;
+ fn data(&self) -> HTMLCanvasData;
}
impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
#[allow(unsafe_code)]
- unsafe fn get_renderer_id(&self) -> Option<usize> {
- let ref canvas = *self.unsafe_get();
- canvas.context.borrow_for_layout().as_ref().map(|context| {
- match *context {
- CanvasContext::Context2d(ref context) => context.to_layout().get_renderer_id(),
- CanvasContext::WebGL(ref context) => context.to_layout().get_renderer_id(),
- }
- })
- }
+ fn data(&self) -> HTMLCanvasData {
+ unsafe {
+ let canvas = &*self.unsafe_get();
+ let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() {
+ Some(&CanvasContext::Context2d(ref context)) => {
+ let context = context.to_layout();
+ (Some(context.get_renderer_id()), Some(context.get_ipc_renderer()))
+ },
+ Some(&CanvasContext::WebGL(ref context)) => {
+ let context = context.to_layout();
+ (Some(context.get_renderer_id()), Some(context.get_ipc_renderer()))
+ },
+ None => (None, None),
+ };
- #[allow(unsafe_code)]
- unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> {
- let ref canvas = *self.unsafe_get();
- canvas.context.borrow_for_layout().as_ref().map(|context| {
- match *context {
- CanvasContext::Context2d(ref context) => context.to_layout().get_ipc_renderer(),
- CanvasContext::WebGL(ref context) => context.to_layout().get_ipc_renderer(),
+ HTMLCanvasData {
+ renderer_id: renderer_id,
+ ipc_renderer: ipc_renderer,
+ width: canvas.width.get(),
+ height: canvas.height.get(),
}
- })
- }
-
- #[allow(unsafe_code)]
- unsafe fn get_canvas_width(&self) -> u32 {
- (*self.unsafe_get()).width.get()
- }
-
- #[allow(unsafe_code)]
- unsafe fn get_canvas_height(&self) -> u32 {
- (*self.unsafe_get()).height.get()
+ }
}
}
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index 34a7847187a..b04082eae4d 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -296,6 +296,26 @@ impl HTMLElement {
let local_name = Atom::from_slice(&to_snake_case(local_name));
self.upcast::<Element>().remove_attribute(&ns!(""), &local_name);
}
+
+ // https://html.spec.whatwg.org/multipage/#category-label
+ pub fn is_labelable_element(&self) -> bool {
+ // Note: HTMLKeygenElement is omitted because Servo doesn't currently implement it
+ match self.upcast::<Node>().type_id() {
+ NodeTypeId::Element(ElementTypeId::HTMLElement(type_id)) =>
+ match type_id {
+ HTMLElementTypeId::HTMLInputElement =>
+ self.downcast::<HTMLInputElement>().unwrap().Type() != "hidden",
+ HTMLElementTypeId::HTMLButtonElement |
+ HTMLElementTypeId::HTMLMeterElement |
+ HTMLElementTypeId::HTMLOutputElement |
+ HTMLElementTypeId::HTMLProgressElement |
+ HTMLElementTypeId::HTMLSelectElement |
+ HTMLElementTypeId::HTMLTextAreaElement => true,
+ _ => false,
+ },
+ _ => false,
+ }
+ }
}
impl VirtualMethods for HTMLElement {
diff --git a/components/script/dom/htmllabelelement.rs b/components/script/dom/htmllabelelement.rs
index 3beefc3db9a..bcda8df24cc 100644
--- a/components/script/dom/htmllabelelement.rs
+++ b/components/script/dom/htmllabelelement.rs
@@ -2,13 +2,18 @@
* 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::attr::AttrValue;
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
+use dom::bindings::conversions::Castable;
use dom::bindings::js::Root;
use dom::document::Document;
+use dom::element::Element;
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
-use dom::node::Node;
+use dom::node::{document_from_node, Node};
+use dom::virtualmethods::VirtualMethods;
+use string_cache::Atom;
use util::str::DOMString;
#[dom_struct]
@@ -40,6 +45,54 @@ impl HTMLLabelElementMethods for HTMLLabelElement {
fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner()
}
+
+ // https://html.spec.whatwg.org/multipage/#dom-label-htmlfor
+ make_getter!(HtmlFor, "for");
+
+ // https://html.spec.whatwg.org/multipage/#dom-label-htmlfor
+ make_atomic_setter!(SetHtmlFor, "for");
+
+ // https://html.spec.whatwg.org/multipage/#dom-label-control
+ fn GetControl(&self) -> Option<Root<HTMLElement>> {
+ if !self.upcast::<Node>().is_in_doc() {
+ return None;
+ }
+
+ let for_attr = match self.upcast::<Element>().get_attribute(&ns!(""), &atom!("for")) {
+ Some(for_attr) => for_attr,
+ None => return self.first_labelable_descendant(),
+ };
+
+ let for_value = for_attr.value();
+ document_from_node(self).get_element_by_id(for_value.as_atom())
+ .and_then(Root::downcast::<HTMLElement>)
+ .into_iter()
+ .filter(|e| e.is_labelable_element())
+ .next()
+ }
+}
+
+impl VirtualMethods for HTMLLabelElement {
+ fn super_type(&self) -> Option<&VirtualMethods> {
+ Some(self.upcast::<HTMLElement>() as &VirtualMethods)
+ }
+
+ fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
+ match name {
+ &atom!("for") => AttrValue::from_atomic(value),
+ _ => self.super_type().unwrap().parse_plain_attribute(name, value),
+ }
+ }
+}
+
+impl HTMLLabelElement {
+ fn first_labelable_descendant(&self) -> Option<Root<HTMLElement>> {
+ self.upcast::<Node>()
+ .traverse_preorder()
+ .filter_map(Root::downcast::<HTMLElement>)
+ .filter(|elem| elem.is_labelable_element())
+ .next()
+ }
}
impl FormControl for HTMLLabelElement {}
diff --git a/components/script/dom/virtualmethods.rs b/components/script/dom/virtualmethods.rs
index da80f414da4..32406205e5d 100644
--- a/components/script/dom/virtualmethods.rs
+++ b/components/script/dom/virtualmethods.rs
@@ -25,6 +25,7 @@ use dom::htmlheadelement::HTMLHeadElement;
use dom::htmliframeelement::HTMLIFrameElement;
use dom::htmlimageelement::HTMLImageElement;
use dom::htmlinputelement::HTMLInputElement;
+use dom::htmllabelelement::HTMLLabelElement;
use dom::htmllinkelement::HTMLLinkElement;
use dom::htmlmetaelement::HTMLMetaElement;
use dom::htmlobjectelement::HTMLObjectElement;
@@ -164,6 +165,9 @@ pub fn vtable_for(node: &Node) -> &VirtualMethods {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
node.downcast::<HTMLInputElement>().unwrap() as &VirtualMethods
}
+ NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLabelElement)) => {
+ node.downcast::<HTMLLabelElement>().unwrap() as &VirtualMethods
+ }
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLinkElement)) => {
node.downcast::<HTMLLinkElement>().unwrap() as &VirtualMethods
}
diff --git a/components/script/dom/webidls/HTMLLabelElement.webidl b/components/script/dom/webidls/HTMLLabelElement.webidl
index 00900df77fc..22659c26e76 100644
--- a/components/script/dom/webidls/HTMLLabelElement.webidl
+++ b/components/script/dom/webidls/HTMLLabelElement.webidl
@@ -6,6 +6,6 @@
// https://html.spec.whatwg.org/multipage/#htmllabelelement
interface HTMLLabelElement : HTMLElement {
readonly attribute HTMLFormElement? form;
- // attribute DOMString htmlFor;
- //readonly attribute HTMLElement? control;
+ attribute DOMString htmlFor;
+ readonly attribute HTMLElement? control;
};