diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index a5897ed80ace..45fbe805b7ac 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1109,7 +1109,10 @@ impl Element { } } - // TODO: set_int_attribute(...) + pub fn set_int_attribute(&self, local_name: &Atom, value: i32) { + assert!(&**local_name == local_name.to_ascii_lowercase()); + self.set_attribute(local_name, AttrValue::Int(DOMString::from(value.to_string()), value)); + } pub fn get_uint_attribute(&self, local_name: &Atom, default: u32) -> u32 { assert!(local_name.chars().all(|ch| !ch.is_ascii() || ch.to_ascii_lowercase() == ch)); diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 19f5d53ef8b5..6cc4f9fdc69b 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -8,8 +8,8 @@ use dom::attr::{Attr, AttrValue}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; -use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::HTMLInputElementBinding; +use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; @@ -104,7 +104,7 @@ impl InputActivationState { } static DEFAULT_INPUT_SIZE: u32 = 20; -static DEFAULT_MAX_LENGTH : i32 = -1; +static DEFAULT_MAX_LENGTH: i32 = -1; impl HTMLInputElement { fn new_inherited(localName: DOMString, prefix: Option, document: &Document) -> HTMLInputElement { @@ -344,15 +344,7 @@ impl HTMLInputElementMethods for HTMLInputElement { make_int_getter!(MaxLength, "maxlength", DEFAULT_MAX_LENGTH); // https://html.spec.whatwg.org/multipage/#dom-input-maxlength - fn SetMaxLength(&self, val: i32) { - self.maxlength.set(val); - - if val >= 0 { - self.textinput.borrow_mut().max_length = Some(val as usize) - } else { - self.textinput.borrow_mut().max_length = None - } - } + make_limited_int_setter!(SetMaxLength, "maxlength", DEFAULT_MAX_LENGTH); // https://html.spec.whatwg.org/multipage/#dom-input-indeterminate fn Indeterminate(&self) -> bool { diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index 8029bb85b2f0..99b4e484752c 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -26,6 +26,26 @@ macro_rules! make_bool_getter( ); ); +#[macro_export] +macro_rules! make_limited_int_setter( + ($attr:ident, $htmlname:tt, $default:expr) => ( + fn $attr(&self, value: i32) -> $crate::dom::bindings::error::ErrorResult { + use dom::bindings::inheritance::Castable; + use dom::element::Element; + + let value = if value < 0 { + return Err($crate::dom::bindings::error::Error::IndexSize); + } else { + value + }; + + let element = self.upcast::(); + element.set_int_attribute(&atom!($htmlname), value); + Ok(()) + } + ); +); + #[macro_export] macro_rules! make_int_getter( ($attr:ident, $htmlname:tt, $default:expr) => ( diff --git a/components/script/dom/webidls/HTMLInputElement.webidl b/components/script/dom/webidls/HTMLInputElement.webidl index b2b7992f5e00..274a10ce957e 100644 --- a/components/script/dom/webidls/HTMLInputElement.webidl +++ b/components/script/dom/webidls/HTMLInputElement.webidl @@ -25,6 +25,7 @@ interface HTMLInputElement : HTMLElement { // attribute DOMString inputMode; //readonly attribute HTMLElement? list; // attribute DOMString max; + [SetterThrows] attribute long maxLength; // attribute DOMString min; // attribute long minLength; diff --git a/components/style/attr.rs b/components/style/attr.rs index e50071e3b3f9..0569b235a9c5 100644 --- a/components/style/attr.rs +++ b/components/style/attr.rs @@ -5,8 +5,8 @@ use cssparser::RGBA; use std::ops::Deref; use string_cache::{Atom, Namespace}; -use util::str::{DOMString, LengthOrPercentageOrAuto, parse_integer, parse_unsigned_integer, parse_legacy_color, parse_length}; -use util::str::{split_html_space_chars, str_join}; +use util::str::{DOMString, LengthOrPercentageOrAuto, parse_unsigned_integer, parse_legacy_color, parse_length}; +use util::str::{split_html_space_chars, str_join, parse_integer}; use values::specified::{Length}; // Duplicated from script::dom::values. @@ -53,12 +53,22 @@ impl AttrValue { AttrValue::UInt(string, result) } - // https://html.spec.whatwg.org/multipage/infrastructure.html#limited-to-only-non-negative-numbers pub fn from_i32(string: DOMString, default: i32) -> AttrValue { let result = parse_integer(string.chars()).unwrap_or(default); AttrValue::Int(string, result) } + // https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers + pub fn from_limited_i32(string: DOMString, default: i32) -> AttrValue { + let result = parse_integer(string.chars()).unwrap_or(default); + + if result < 0 { + AttrValue::Int(string, default) + } else { + AttrValue::Int(string, result) + } + } + // https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers-greater-than-zero pub fn from_limited_u32(string: DOMString, default: u32) -> AttrValue { let result = parse_unsigned_integer(string.chars()).unwrap_or(default); diff --git a/tests/unit/style/attr.rs b/tests/unit/style/attr.rs new file mode 100644 index 000000000000..d114b65af749 --- /dev/null +++ b/tests/unit/style/attr.rs @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 style::attr::AttrValue; +use util::str::DOMString; + +#[test] +fn test_from_limited_i32_should_be_default_when_less_than_0() { + let value = DOMString::from("-1"); + match AttrValue::from_limited_i32(value, 0) { + AttrValue::Int(_, 0) => (), + _ => panic!("expected an IndexSize error") + } +} + +#[test] +fn test_from_limited_i32_should_parse_a_uint_when_value_is_0_or_greater() { + match AttrValue::from_limited_i32(DOMString::from("1"), 0) { + AttrValue::Int(_, 1) => (), + _ => panic!("expected an successful parsing") + } +} + +#[test] +fn test_from_limited_i32_should_keep_parsed_value_when_not_an_int() { + match AttrValue::from_limited_i32(DOMString::from("parsed-value"), 0) { + AttrValue::Int(p, 0) => { + assert_eq!(p, DOMString::from("parsed_value")) + }, + _ => panic!("expected an successful parsing") + } +} diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index 4963607fb7cd..a405d76108d7 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -20,6 +20,7 @@ extern crate util; #[cfg(test)] mod stylesheets; #[cfg(test)] mod media_queries; #[cfg(test)] mod viewport; +#[cfg(test)] mod attr; #[cfg(test)] mod writing_modes { use style::properties::{INITIAL_VALUES, get_writing_mode};