Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Finish implementation of HTML5 form validation. #17657

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -7,6 +7,7 @@ use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementBinding::HTMLElementMethods;
use dom::bindings::codegen::Bindings::HTMLFormControlsCollectionBinding::HTMLFormControlsCollectionMethods;
use dom::bindings::codegen::Bindings::HTMLFormElementBinding;
use dom::bindings::codegen::Bindings::HTMLFormElementBinding::HTMLFormElementMethods;
@@ -454,13 +455,18 @@ impl HTMLFormElement {
/// Interactively validate the constraints of form elements
/// https://html.spec.whatwg.org/multipage/#interactively-validate-the-constraints
fn interactive_validation(&self) -> Result<(), ()> {
// Step 1-3
let _unhandled_invalid_controls = match self.static_validation() {
// Step 1-2
let unhandled_invalid_controls = match self.static_validation() {
Ok(()) => return Ok(()),
Err(err) => err
};
// TODO: Report the problems with the constraints of at least one of
// the elements given in unhandled invalid controls to the user
// Step 3
// TODO: Replace println! by something more visible to the user when a better reporting method
// becomes available.
let ref first_invalid_element = unhandled_invalid_controls[0].as_html_element();
println!("Validation error in element {}",
first_invalid_element.upcast::<Element>().get_string_attribute(&local_name!("name")));
first_invalid_element.Focus();
// Step 4
Err(())
}
@@ -757,6 +763,16 @@ impl FormSubmittableElement {
unreachable!()
}
}

fn as_html_element(&self) -> &HTMLElement {
match *self {
FormSubmittableElement::ButtonElement(ref button) => button.upcast(),
FormSubmittableElement::InputElement(ref input) => input.upcast(),
FormSubmittableElement::ObjectElement(ref object) => object.upcast(),
FormSubmittableElement::SelectElement(ref select) => select.upcast(),
FormSubmittableElement::TextAreaElement(ref textarea) => textarea.upcast()
}
}
}

#[derive(Copy, Clone, HeapSizeOf)]
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use caseless::compatibility_caseless_match_str;
use core::borrow::Borrow;
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
@@ -43,11 +44,13 @@ use mime_guess;
use net_traits::{CoreResourceMsg, IpcSend};
use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern};
use regex::Regex;
use script_layout_interface::rpc::TextIndexResponse;
use script_traits::ScriptMsg as ConstellationMsg;
use servo_atoms::Atom;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::error::{Error as StdError};
use std::ops::Range;
use style::attr::AttrValue;
use style::element_state::*;
@@ -1188,7 +1191,63 @@ impl Validatable for HTMLInputElement {
true
}
fn validate(&self, _validate_flags: ValidationFlags) -> bool {

This comment has been minimized.

Copy link
@KiChjang

KiChjang Aug 3, 2017

Member

The _ prefix can be removed from validate_flags.

// call stub methods defined in validityState.rs file here according to the flags set in validate_flags
use dom::validitystate::*;

let value = self.Value();
let value_str: &str = value.borrow();

This comment has been minimized.

Copy link
@KiChjang

KiChjang Aug 3, 2017

Member

Why is this call to borrow necessary?

// https://html.spec.whatwg.org/multipage/#suffering-from-being-missing
if _validate_flags.contains(VALUE_MISSING) {
if value_str.is_empty() {
return false;
}
}
// https://html.spec.whatwg.org/multipage/#suffering-from-a-type-mismatch
if _validate_flags.contains(TYPE_MISMATCH) {
let validation_patterns = match self.Type().borrow() {
"url" => vec!(".", "/"),
"email" => vec!("@"),
_ => vec!(),
};

if validation_patterns.iter().all(|&p| !value_str.contains(p)) {
return false;
}
}
// https://html.spec.whatwg.org/multipage/#suffering-from-a-pattern-mismatch
if _validate_flags.contains(PATTERN_MISMATCH) {
let pattern = self.Pattern();
let pattern_str: &str = pattern.borrow();
if pattern_str.len() > 0 {
let pattern_regex = format!("^{}$", pattern_str);
match Regex::new(pattern_regex.as_str()) {
Ok(regex) => {
if !regex.is_match(value_str) {
return false;
}
},
Err(error) => {
// TODO When possible, report this error to the developer console, as suggested in
// https://html.spec.whatwg.org/multipage/#attr-input-pattern
println!("Invalid pattern for element {}: {}",
self.Name(), error.description());
}
};
}
}
// https://html.spec.whatwg.org/multipage/#suffering-from-being-too-long
if _validate_flags.contains(TOO_LONG) {
let maxlength = self.maxlength.get();
if maxlength != DEFAULT_MAX_LENGTH && value_str.len() > (maxlength as usize) {
return false;
}
}
// https://html.spec.whatwg.org/multipage/#suffering-from-being-too-short
if _validate_flags.contains(TOO_SHORT) {
let minlength = self.minlength.get();
if minlength != DEFAULT_MIN_LENGTH && value_str.len() < (minlength as usize) {
return false;
}
}
true
}
}
@@ -70,56 +70,56 @@ impl ValidityState {
impl ValidityStateMethods for ValidityState {
// https://html.spec.whatwg.org/multipage/#dom-validitystate-valuemissing
fn ValueMissing(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(VALUE_MISSING))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-typemismatch
fn TypeMismatch(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(TYPE_MISMATCH))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-patternmismatch
fn PatternMismatch(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(PATTERN_MISMATCH))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-toolong
fn TooLong(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(TOO_LONG))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-tooshort
fn TooShort(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(TOO_SHORT))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeunderflow
fn RangeUnderflow(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(RANGE_UNDERFLOW))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeoverflow
fn RangeOverflow(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(RANGE_OVERFLOW))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-stepmismatch
fn StepMismatch(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(STEP_MISMATCH))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-badinput
fn BadInput(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(BAD_INPUT))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-customerror
fn CustomError(&self) -> bool {
false
self.element.as_maybe_validatable().map_or(false, |e| e.validate(CUSTOM_ERROR))
}

// https://html.spec.whatwg.org/multipage/#dom-validitystate-valid
fn Valid(&self) -> bool {
false
!self.element.as_maybe_validatable().map_or(false, |e| e.validate(ValidationFlags::all()))
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.