servo: Merge #3605 - Improve macro getters, add macro setters, implement attributes for <form> (from Manishearth:form-stuff); r=jdm

Source-Repo: https://github.com/servo/servo
Source-Revision: 94731270df688f2df49fdec36ccf7eefd9ed021f
This commit is contained in:
Manish Goregaokar 2014-10-08 03:42:34 -06:00
parent 17eeb55b66
commit 2dfaa0ee12
12 changed files with 227 additions and 127 deletions

View File

@ -41,6 +41,7 @@ use std::cell::RefCell;
use std::default::Default;
use std::mem;
use string_cache::{Atom, Namespace};
use url::UrlParser;
#[jstraceable]
#[must_root]
@ -486,8 +487,18 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
fn get_url_attribute(self, name: &str) -> DOMString {
assert!(name == name.to_ascii_lower().as_slice());
// XXX Resolve URL.
self.get_string_attribute(name)
if !self.has_attribute(name) {
return "".to_string();
}
let url = self.get_string_attribute(name);
let doc = document_from_node(self).root();
let base = doc.url();
// https://html.spec.whatwg.org/multipage/infrastructure.html#reflect
// XXXManishearth this doesn't handle `javascript:` urls properly
match UrlParser::new().base_url(base).parse(url.as_slice()) {
Ok(parsed) => parsed.serialize(),
Err(_) => "".to_string()
}
}
fn set_url_attribute(self, name: &str, value: DOMString) {
self.set_string_attribute(name, value);

View File

@ -4,12 +4,12 @@
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLButtonElementDerived, HTMLFieldSetElementDerived};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{AttributeHandlers, Element, HTMLButtonElementTypeId};
use dom::element::{AttributeHandlers, HTMLButtonElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, window_from_node};
@ -55,10 +55,7 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
make_bool_getter!(Disabled)
// http://www.whatwg.org/html/#dom-fe-disabled
fn SetDisabled(self, disabled: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_bool_attribute("disabled", disabled)
}
make_bool_setter!(SetDisabled, "disabled")
}
impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {

View File

@ -75,10 +75,7 @@ impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> {
make_bool_getter!(Disabled)
// http://www.whatwg.org/html/#dom-fieldset-disabled
fn SetDisabled(self, disabled: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_bool_attribute("disabled", disabled)
}
make_bool_setter!(SetDisabled, "disabled")
}
impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {

View File

@ -3,20 +3,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::Bindings::HTMLFormElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived;
use dom::bindings::codegen::Bindings::HTMLFormElementBinding::HTMLFormElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFormElementDerived};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::HTMLFormElementTypeId;
use dom::element::{Element, AttributeHandlers, HTMLFormElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use dom::node::{Node, ElementNodeTypeId, window_from_node};
use servo_util::str::DOMString;
use std::ascii::OwnedStrAsciiExt;
#[jstraceable]
#[must_root]
pub struct HTMLFormElement {
pub htmlelement: HTMLElement
pub htmlelement: HTMLElement,
}
impl HTMLFormElementDerived for EventTarget {
@ -39,6 +42,101 @@ impl HTMLFormElement {
}
}
impl<'a> HTMLFormElementMethods for JSRef<'a, HTMLFormElement> {
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-acceptcharset
make_getter!(AcceptCharset, "accept-charset")
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-acceptcharset
make_setter!(SetAcceptCharset, "accept-charset")
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-action
fn Action(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self);
let url = element.get_url_attribute("src");
match url.as_slice() {
"" => {
let window = window_from_node(self).root();
window.get_url().serialize()
},
_ => url
}
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-action
make_setter!(SetAction, "action")
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-autocomplete
fn Autocomplete(self) -> DOMString {
let elem: JSRef<Element> = ElementCast::from_ref(self);
let ac = elem.get_string_attribute("autocomplete").into_ascii_lower();
// https://html.spec.whatwg.org/multipage/forms.html#attr-form-autocomplete
match ac.as_slice() {
"off" => ac,
_ => "on".to_string()
}
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-autocomplete
make_setter!(SetAutocomplete, "autocomplete")
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-enctype
fn Enctype(self) -> DOMString {
let elem: JSRef<Element> = ElementCast::from_ref(self);
let enctype = elem.get_string_attribute("enctype").into_ascii_lower();
// https://html.spec.whatwg.org/multipage/forms.html#attr-fs-enctype
match enctype.as_slice() {
"text/plain" | "multipart/form-data" => enctype,
_ => "application/x-www-form-urlencoded".to_string()
}
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-enctype
make_setter!(SetEnctype, "enctype")
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-encoding
fn Encoding(self) -> DOMString {
self.Enctype()
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-encoding
fn SetEncoding(self, value: DOMString) {
self.SetEnctype(value)
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-method
fn Method(self) -> DOMString {
let elem: JSRef<Element> = ElementCast::from_ref(self);
let method = elem.get_string_attribute("method").into_ascii_lower();
// https://html.spec.whatwg.org/multipage/forms.html#attr-fs-method
match method.as_slice() {
"post" | "dialog" => method,
_ => "get".to_string()
}
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-method
make_setter!(SetMethod, "method")
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-name
make_getter!(Name)
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-name
make_setter!(SetName, "name")
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-novalidate
make_bool_getter!(NoValidate)
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-novalidate
make_bool_setter!(SetNoValidate, "novalidate")
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-target
make_getter!(Target)
// https://html.spec.whatwg.org/multipage/forms.html#dom-fs-target
make_setter!(SetTarget, "target")
}
impl Reflectable for HTMLFormElement {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.htmlelement.reflector()

View File

@ -98,24 +98,15 @@ impl LayoutHTMLImageElementHelpers for JS<HTMLImageElement> {
impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
make_getter!(Alt)
fn SetAlt(self, alt: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_string_attribute("alt", alt)
}
make_setter!(SetAlt, "alt")
make_getter!(Src)
make_url_getter!(Src)
fn SetSrc(self, src: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_url_attribute("src", src)
}
make_setter!(SetSrc, "src")
make_getter!(UseMap)
fn SetUseMap(self, use_map: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_string_attribute("usemap", use_map)
}
make_setter!(SetUseMap, "usemap")
make_bool_getter!(IsMap)
@ -148,45 +139,27 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
make_getter!(Name)
fn SetName(self, name: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_string_attribute("name", name)
}
make_setter!(SetName, "name")
make_getter!(Align)
fn SetAlign(self, align: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_string_attribute("align", align)
}
make_setter!(SetAlign, "align")
make_uint_getter!(Hspace)
fn SetHspace(self, hspace: u32) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_uint_attribute("hspace", hspace)
}
make_uint_setter!(SetHspace, "hspace")
make_uint_getter!(Vspace)
fn SetVspace(self, vspace: u32) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_uint_attribute("vspace", vspace)
}
make_uint_setter!(SetVspace, "vspace")
make_getter!(LongDesc)
fn SetLongDesc(self, longdesc: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_string_attribute("longdesc", longdesc)
}
make_setter!(SetLongDesc, "longdesc")
make_getter!(Border)
fn SetBorder(self, border: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_string_attribute("border", border)
}
make_setter!(SetBorder, "border")
}
impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {

View File

@ -117,46 +117,31 @@ impl<'a> HTMLInputElementMethods for JSRef<'a, HTMLInputElement> {
make_bool_getter!(Disabled)
// http://www.whatwg.org/html/#dom-fe-disabled
fn SetDisabled(self, disabled: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_bool_attribute("disabled", disabled)
}
make_bool_setter!(SetDisabled, "disabled")
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-checked
make_bool_getter!(Checked)
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-checked
fn SetChecked(self, checked: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_bool_attribute("checked", checked)
}
make_bool_setter!(SetChecked, "checked")
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-size
make_uint_getter!(Size)
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-size
fn SetSize(self, size: u32) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_uint_attribute("size", size)
}
make_uint_setter!(SetSize, "size")
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-value
make_getter!(Value)
// https://html.spec.whatwg.org/multipage/forms.html#dom-input-value
fn SetValue(self, value: DOMString) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_string_attribute("value", value)
}
make_setter!(SetValue, "value")
// https://html.spec.whatwg.org/multipage/forms.html#attr-fe-name
make_getter!(Name)
// https://html.spec.whatwg.org/multipage/forms.html#attr-fe-name
fn SetName(self, name: DOMString) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_string_attribute("name", name)
}
make_setter!(SetName, "name")
}
trait HTMLInputElementHelpers {

View File

@ -4,12 +4,12 @@
use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding;
use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding::HTMLOptGroupElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLOptGroupElementDerived, HTMLOptionElementDerived};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{AttributeHandlers, Element, HTMLOptGroupElementTypeId};
use dom::element::{AttributeHandlers, HTMLOptGroupElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId};
@ -49,10 +49,7 @@ impl<'a> HTMLOptGroupElementMethods for JSRef<'a, HTMLOptGroupElement> {
make_bool_getter!(Disabled)
// http://www.whatwg.org/html#dom-optgroup-disabled
fn SetDisabled(self, disabled: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_bool_attribute("disabled", disabled)
}
make_bool_setter!(SetDisabled, "disabled")
}
impl<'a> VirtualMethods for JSRef<'a, HTMLOptGroupElement> {

View File

@ -4,14 +4,14 @@
use dom::bindings::codegen::Bindings::HTMLSelectElementBinding;
use dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLSelectElementDerived, HTMLFieldSetElementDerived};
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong::HTMLElementOrLong;
use dom::bindings::codegen::UnionTypes::HTMLOptionElementOrHTMLOptGroupElement::HTMLOptionElementOrHTMLOptGroupElement;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{AttributeHandlers, Element, HTMLSelectElementTypeId};
use dom::element::{AttributeHandlers, HTMLSelectElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, window_from_node};
@ -61,10 +61,7 @@ impl<'a> HTMLSelectElementMethods for JSRef<'a, HTMLSelectElement> {
make_bool_getter!(Disabled)
// http://www.whatwg.org/html/#dom-fe-disabled
fn SetDisabled(self, disabled: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_bool_attribute("disabled", disabled)
}
make_bool_setter!(SetDisabled, "disabled")
}
impl<'a> VirtualMethods for JSRef<'a, HTMLSelectElement> {

View File

@ -4,12 +4,12 @@
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementDerived, HTMLFieldSetElementDerived};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
use dom::element::{AttributeHandlers, Element, HTMLTextAreaElementTypeId};
use dom::element::{AttributeHandlers, HTMLTextAreaElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId};
@ -49,10 +49,7 @@ impl<'a> HTMLTextAreaElementMethods for JSRef<'a, HTMLTextAreaElement> {
make_bool_getter!(Disabled)
// http://www.whatwg.org/html/#dom-fe-disabled
fn SetDisabled(self, disabled: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self);
elem.set_bool_attribute("disabled", disabled)
}
make_bool_setter!(SetDisabled, "disabled")
}
impl<'a> VirtualMethods for JSRef<'a, HTMLTextAreaElement> {

View File

@ -4,43 +4,109 @@
#[macro_export]
macro_rules! make_getter(
( $attr:ident ) => (
( $attr:ident, $htmlname:expr ) => (
fn $attr(self) -> DOMString {
use dom::element::{Element, AttributeHandlers};
use dom::bindings::codegen::InheritTypes::ElementCast;
#[allow(unused_imports)]
use std::ascii::StrAsciiExt;
let element: JSRef<Element> = ElementCast::from_ref(self);
element.get_string_attribute(stringify!($attr).to_ascii_lower().as_slice())
element.get_string_attribute($htmlname)
}
);
($attr:ident) => {
make_getter!($attr, stringify!($attr).to_ascii_lower().as_slice())
}
)
#[macro_export]
macro_rules! make_bool_getter(
( $attr:ident ) => (
( $attr:ident, $htmlname:expr ) => (
fn $attr(self) -> bool {
use dom::element::{Element, AttributeHandlers};
use dom::bindings::codegen::InheritTypes::ElementCast;
#[allow(unused_imports)]
use std::ascii::StrAsciiExt;
let element: JSRef<Element> = ElementCast::from_ref(self);
element.has_attribute(stringify!($attr).to_ascii_lower().as_slice())
element.has_attribute($htmlname)
}
);
($attr:ident) => {
make_bool_getter!($attr, stringify!($attr).to_ascii_lower().as_slice())
}
)
#[macro_export]
macro_rules! make_uint_getter(
( $attr:ident, $htmlname:expr ) => (
fn $attr(self) -> u32 {
use dom::element::{Element, AttributeHandlers};
use dom::bindings::codegen::InheritTypes::ElementCast;
#[allow(unused_imports)]
use std::ascii::StrAsciiExt;
let element: JSRef<Element> = ElementCast::from_ref(self);
element.get_uint_attribute($htmlname)
}
);
($attr:ident) => {
make_uint_getter!($attr, stringify!($attr).to_ascii_lower().as_slice())
}
)
#[macro_export]
macro_rules! make_url_getter(
( $attr:ident, $htmlname:expr ) => (
fn $attr(self) -> DOMString {
use dom::element::{Element, AttributeHandlers};
use dom::bindings::codegen::InheritTypes::ElementCast;
#[allow(unused_imports)]
use std::ascii::StrAsciiExt;
let element: JSRef<Element> = ElementCast::from_ref(self);
element.get_url_attribute($htmlname)
}
);
($attr:ident) => {
make_url_getter!($attr, stringify!($attr).to_ascii_lower().as_slice())
}
)
// concat_idents! doesn't work for function name positions, so
// we have to specify both the content name and the HTML name here
#[macro_export]
macro_rules! make_setter(
( $attr:ident, $htmlname:expr ) => (
fn $attr(self, value: DOMString) {
use dom::element::{Element, AttributeHandlers};
use dom::bindings::codegen::InheritTypes::ElementCast;
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_string_attribute($htmlname, value)
}
);
)
#[macro_export]
macro_rules! make_uint_getter(
( $attr:ident ) => (
fn $attr(self) -> u32 {
macro_rules! make_bool_setter(
( $attr:ident, $htmlname:expr ) => (
fn $attr(self, value: bool) {
use dom::element::{Element, AttributeHandlers};
use dom::bindings::codegen::InheritTypes::ElementCast;
use std::ascii::StrAsciiExt;
let element: JSRef<Element> = ElementCast::from_ref(self);
element.get_uint_attribute(stringify!($attr).to_ascii_lower().as_slice())
element.set_bool_attribute($htmlname, value)
}
);
)
#[macro_export]
macro_rules! make_uint_setter(
( $attr:ident, $htmlname:expr ) => (
fn $attr(self, value: u32) {
use dom::element::{Element, AttributeHandlers};
use dom::bindings::codegen::InheritTypes::ElementCast;
let element: JSRef<Element> = ElementCast::from_ref(self);
element.set_uint_attribute($htmlname, value)
}
);
)
/// For use on non-jsmanaged types
/// Use #[jstraceable] on JS managed types

View File

@ -6,15 +6,15 @@
// http://www.whatwg.org/html/#htmlformelement
//[OverrideBuiltins]
interface HTMLFormElement : HTMLElement {
// attribute DOMString acceptCharset;
// attribute DOMString action;
// attribute DOMString autocomplete;
// attribute DOMString enctype;
// attribute DOMString encoding;
// attribute DOMString method;
// attribute DOMString name;
// attribute boolean noValidate;
// attribute DOMString target;
attribute DOMString acceptCharset;
attribute DOMString action;
attribute DOMString autocomplete;
attribute DOMString enctype;
attribute DOMString encoding;
attribute DOMString method;
attribute DOMString name;
attribute boolean noValidate;
attribute DOMString target;
//readonly attribute HTMLFormControlsCollection elements;
//readonly attribute long length;

View File

@ -1,18 +0,0 @@
<html>
<head id="foo">
<title></title>
<script src="harness.js"></script>
</head>
<script>
let script = document.getElementById("test");
{
is(script.src, "/x.js");
}
finish();
</script>
<body>
<script src="/x.js" id="test"/>
</body>
</html>