LibWeb: Implement “suffering from overflow/underflow” for inputs

This change implements the requirements for the “suffering from an
overflow” and “suffering from an underflow” algorithms for
HTMLInputElement constraint validation.
This commit is contained in:
sideshowbarker 2025-03-07 16:44:29 +09:00 committed by Tim Ledbetter
parent ad9f70dff9
commit cf1425d09e
Notes: github-actions[bot] 2025-03-07 08:33:18 +00:00
6 changed files with 100 additions and 57 deletions

View file

@ -3006,6 +3006,19 @@ bool HTMLInputElement::is_focusable() const
return m_type != TypeAttributeState::Hidden && enabled();
}
// https://html.spec.whatwg.org/multipage/input.html#has-a-reversed-range
bool HTMLInputElement::has_reversed_range() const
{
auto minimum = min();
if (!minimum.has_value())
return false;
auto maximum = max();
if (!maximum.has_value())
return false;
// An element has a reversed range if it has a periodic domain and its maximum is less than its minimum.
return has_periodic_domain() && maximum.value() < minimum.value();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#suffering-from-being-missing
bool HTMLInputElement::suffering_from_being_missing() const
{
@ -3122,32 +3135,57 @@ bool HTMLInputElement::suffering_from_a_pattern_mismatch() const
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#suffering-from-an-underflow
bool HTMLInputElement::suffering_from_an_underflow() const
{
// and the result of applying the algorithm to convert a string to a number to the string given by the element's
// value is a number
auto result = convert_string_to_number(value());
if (!result.has_value())
return false;
auto number = result.value();
// https://html.spec.whatwg.org/multipage/input.html#the-min-and-max-attributes%3Asuffering-from-an-underflow-2
// When the element has a minimum and does not have a reversed range, and the result of applying the algorithm to convert a string to a number to the string
// given by the element's value is a number, and the number obtained from that algorithm is less than the minimum, the element is suffering from an underflow.
// FIXME: Implement this.
// When the element has a minimum and does not have a reversed range,
auto minimum = min();
if (minimum.has_value() && !has_reversed_range()) {
// and the number obtained from that algorithm is less than the minimum, the element is suffering from an underflow.
return number < minimum.value();
}
if (!minimum.has_value())
return false;
auto maximum = max();
if (!maximum.has_value())
return false;
// https://html.spec.whatwg.org/multipage/input.html#the-min-and-max-attributes%3Asuffering-from-an-underflow-3
// When an element has a reversed range, and the result of applying the algorithm to convert a string to a number to the string given by the element's value is a
// number, and the number obtained from that algorithm is more than the maximum and less than the minimum, the element is simultaneously suffering from an underflow and
// suffering from an overflow.
// FIXME: Implement this.
return false;
// When an element has a reversed range, and the number obtained from that algorithm is more than the maximum and
// less than the minimum, the element is simultaneously suffering from an underflow and suffering from an overflow.
return has_reversed_range() && number > maximum.value() && number < minimum.value();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#suffering-from-an-overflow
bool HTMLInputElement::suffering_from_an_overflow() const
{
// and the result of applying the algorithm to convert a string to a number to the string given by the element's
// value is a number
auto result = convert_string_to_number(value());
if (!result.has_value())
return false;
auto number = result.value();
auto maximum = max();
// https://html.spec.whatwg.org/multipage/input.html#the-min-and-max-attributes%3Asuffering-from-an-overflow-2
// When the element has a maximum and does not have a reversed range, and the result of applying the algorithm to convert a string to a number to the string
// given by the element's value is a number, and the number obtained from that algorithm is more than the maximum, the element is suffering from an overflow.
// When the element has a maximum and does not have a reversed range,
if (maximum.has_value() && !has_reversed_range()) {
// and the number obtained from that algorithm is more than the maximum, the element is suffering from an overflow.
return number > maximum.value();
}
if (!maximum.has_value())
return false;
auto minimum = min();
if (!minimum.has_value())
return false;
// https://html.spec.whatwg.org/multipage/input.html#the-min-and-max-attributes%3Asuffering-from-an-underflow-3
// When an element has a reversed range, and the result of applying the algorithm to convert a string to a number to the string given by the element's value is a
// number, and the number obtained from that algorithm is more than the maximum and less than the minimum, the element is simultaneously suffering from an underflow and
// suffering from an overflow.
// FIXME: Implement this.
return false;
// When an element has a reversed range, and the number obtained from that algorithm is more than the maximum and
// less than the minimum, the element is simultaneously suffering from an underflow and suffering from an overflow.
return has_reversed_range() && number > maximum.value() && number < minimum.value();
}
// https://html.spec.whatwg.org/multipage/input.html#the-step-attribute%3Asuffering-from-a-step-mismatch

View file

@ -232,6 +232,11 @@ public:
virtual void did_edit_text_node() override;
virtual GC::Ptr<DOM::Text> form_associated_element_to_text_node() override { return m_text_node; }
// https://html.spec.whatwg.org/multipage/input.html#has-a-periodic-domain/
bool has_periodic_domain() const { return type_state() == HTMLInputElement::TypeAttributeState::Time; }
// https://html.spec.whatwg.org/multipage/input.html#has-a-reversed-range
bool has_reversed_range() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#definitions
virtual bool suffering_from_being_missing() const override;
virtual bool suffering_from_a_type_mismatch() const override;

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 132 tests
118 Pass
14 Fail
126 Pass
6 Fail
Pass [INPUT in TEXT status] no constraint
Pass [INPUT in TEXT status] no constraint (in a form)
Pass [INPUT in TEXT status] not suffering from being too long
@ -98,18 +98,18 @@ Pass [INPUT in WEEK status] suffering from being missing
Pass [INPUT in WEEK status] suffering from being missing (in a form)
Pass [INPUT in TIME status] no constraint
Pass [INPUT in TIME status] no constraint (in a form)
Fail [INPUT in TIME status] suffering from an overflow
Fail [INPUT in TIME status] suffering from an overflow (in a form)
Fail [INPUT in TIME status] suffering from an underflow
Fail [INPUT in TIME status] suffering from an underflow (in a form)
Pass [INPUT in TIME status] suffering from an overflow
Pass [INPUT in TIME status] suffering from an overflow (in a form)
Pass [INPUT in TIME status] suffering from an underflow
Pass [INPUT in TIME status] suffering from an underflow (in a form)
Pass [INPUT in TIME status] suffering from a step mismatch
Pass [INPUT in TIME status] suffering from a step mismatch (in a form)
Pass [INPUT in TIME status] suffering from being missing
Pass [INPUT in TIME status] suffering from being missing (in a form)
Fail [INPUT in NUMBER status] suffering from an overflow
Fail [INPUT in NUMBER status] suffering from an overflow (in a form)
Fail [INPUT in NUMBER status] suffering from an underflow
Fail [INPUT in NUMBER status] suffering from an underflow (in a form)
Pass [INPUT in NUMBER status] suffering from an overflow
Pass [INPUT in NUMBER status] suffering from an overflow (in a form)
Pass [INPUT in NUMBER status] suffering from an underflow
Pass [INPUT in NUMBER status] suffering from an underflow (in a form)
Pass [INPUT in NUMBER status] suffering from a step mismatch
Pass [INPUT in NUMBER status] suffering from a step mismatch (in a form)
Pass [INPUT in NUMBER status] (with 'value' content attribute) suffering from a step mismatch

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 49 tests
32 Pass
17 Fail
41 Pass
8 Fail
Pass [INPUT in DATETIME-LOCAL status] The max attribute is not set
Pass [INPUT in DATETIME-LOCAL status] Value is empty string
Pass [INPUT in DATETIME-LOCAL status] The max attribute is an invalid local date time string
@ -23,8 +23,8 @@ Pass [INPUT in DATE status] The value is an invalid date(year is three digits)
Pass [INPUT in DATE status] The value is an invalid date(month is greater than 12)
Pass [INPUT in DATE status] The value is an invalid date(date is greater than 29 for Feb)
Pass [INPUT in DATE status] The max attribute is greater than value attribute
Fail [INPUT in DATE status] The value attribute is greater than max attribute
Fail [INPUT in DATE status] The value attribute is greater than max attribute(Year is 10000 should be valid)
Pass [INPUT in DATE status] The value attribute is greater than max attribute
Pass [INPUT in DATE status] The value attribute is greater than max attribute(Year is 10000 should be valid)
Pass [INPUT in TIME status] The max attribute is not set
Pass [INPUT in TIME status] Value is empty string
Pass [INPUT in TIME status] The max attribute is an invalid time string
@ -34,13 +34,13 @@ Pass [INPUT in TIME status] The value attribute is an invalid time string(minute
Pass [INPUT in TIME status] The value attribute is an invalid time string(second is greater than 59)
Pass [INPUT in TIME status] The max attribute is greater than value attribute
Pass [INPUT in TIME status] The time missing second and minute parts is invalid
Fail [INPUT in TIME status] The value attribute is greater than max attribute
Pass [INPUT in TIME status] The value attribute is greater than max attribute
Fail [INPUT in TIME status] The value is greater than max(with millisecond in 1 digit)
Fail [INPUT in TIME status] The value is greater than max(with millisecond in 2 digit)
Fail [INPUT in TIME status] The value is greater than max(with millisecond in 3 digit)
Fail [INPUT in TIME status] The time missing second part is valid
Pass [INPUT in TIME status] The time missing second part is valid
Pass [INPUT in TIME status] The time is max for reversed range
Fail [INPUT in TIME status] The time is outside the accepted range for reversed range
Pass [INPUT in TIME status] The time is outside the accepted range for reversed range
Pass [INPUT in TIME status] The time is min for reversed range
Pass [INPUT in TIME status] The time is inside the accepted range for reversed range
Pass [INPUT in NUMBER status] The max attribute is not set
@ -49,7 +49,7 @@ Pass [INPUT in NUMBER status] The max is greater than value(integer)
Pass [INPUT in NUMBER status] The max is greater than value(floating number)
Pass [INPUT in NUMBER status] The max equals to value
Pass [INPUT in NUMBER status] The value is not a number
Fail [INPUT in NUMBER status] The value is greater than max(integer)
Fail [INPUT in NUMBER status] The value is greater than max(floating number)
Fail [INPUT in NUMBER status] The value is greater than max(special floating number)
Fail [INPUT in NUMBER status] The value is greater than max(scientific notation)
Pass [INPUT in NUMBER status] The value is greater than max(integer)
Pass [INPUT in NUMBER status] The value is greater than max(floating number)
Pass [INPUT in NUMBER status] The value is greater than max(special floating number)
Pass [INPUT in NUMBER status] The value is greater than max(scientific notation)

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 47 tests
30 Pass
17 Fail
39 Pass
8 Fail
Pass [INPUT in DATETIME-LOCAL status] The min attribute is not set
Pass [INPUT in DATETIME-LOCAL status] Value is empty string
Pass [INPUT in DATETIME-LOCAL status] The min attribute is an invalid local date time string
@ -24,21 +24,21 @@ Pass [INPUT in DATE status] The value is an invalid date(year is three digits)
Pass [INPUT in DATE status] The value is an invalid date(month is less than 12)
Pass [INPUT in DATE status] The value is an invalid date(date is less than 29 for Feb)
Pass [INPUT in DATE status] The min attribute is less than value attribute
Fail [INPUT in DATE status] The value attribute is less than min attribute
Fail [INPUT in DATE status] The value attribute is less than min attribute(Year is 10000 should be valid)
Pass [INPUT in DATE status] The value attribute is less than min attribute
Pass [INPUT in DATE status] The value attribute is less than min attribute(Year is 10000 should be valid)
Pass [INPUT in TIME status] The min attribute is not set
Pass [INPUT in TIME status] Value is empty string
Pass [INPUT in TIME status] The min attribute is an invalid time string
Pass [INPUT in TIME status] The value attribute is an invalid time string
Pass [INPUT in TIME status] The min attribute is less than value attribute
Pass [INPUT in TIME status] The time missing second and minute parts is invalid
Fail [INPUT in TIME status] The value attribute is less than min attribute
Pass [INPUT in TIME status] The value attribute is less than min attribute
Fail [INPUT in TIME status] The value is less than min(with millisecond in 1 digit)
Fail [INPUT in TIME status] The value is less than min(with millisecond in 2 digit)
Fail [INPUT in TIME status] The value is less than min(with millisecond in 3 digit)
Fail [INPUT in TIME status] The time missing second part is valid
Pass [INPUT in TIME status] The time missing second part is valid
Pass [INPUT in TIME status] The time is max for reversed range
Fail [INPUT in TIME status] The time is outside the accepted range for reversed range
Pass [INPUT in TIME status] The time is outside the accepted range for reversed range
Pass [INPUT in TIME status] The time is min for reversed range
Pass [INPUT in TIME status] The time is inside the accepted range for reversed range
Pass [INPUT in NUMBER status] The min attribute is not set
@ -47,7 +47,7 @@ Pass [INPUT in NUMBER status] The min is less than value(integer)
Pass [INPUT in NUMBER status] The min is less than value(floating number)
Pass [INPUT in NUMBER status] The min equals to value
Pass [INPUT in NUMBER status] The value is not a number
Fail [INPUT in NUMBER status] The value is less than min(integer)
Fail [INPUT in NUMBER status] The value is less than min(floating number)
Fail [INPUT in NUMBER status] The value is less than min(special floating number)
Fail [INPUT in NUMBER status] The value is less than min(scientific notation)
Pass [INPUT in NUMBER status] The value is less than min(integer)
Pass [INPUT in NUMBER status] The value is less than min(floating number)
Pass [INPUT in NUMBER status] The value is less than min(special floating number)
Pass [INPUT in NUMBER status] The value is less than min(scientific notation)

View file

@ -2,18 +2,18 @@ Harness status: OK
Found 30 tests
22 Pass
8 Fail
26 Pass
4 Fail
Pass ':valid' matches elements that satisfy their constraints
Pass ':valid' matches form elements that are not the form owner of any elements that themselves are candidates for constraint validation but do not satisfy their constraints
Pass ':valid' matches fieldset elements that have no descendant elements that themselves are candidates for constraint validation but do not satisfy their constraints
Pass ':valid' matches elements that satisfy their pattern constraints
Fail ':valid' matches elements that satisfy their number constraints
Pass ':valid' matches elements that satisfy their number constraints
Pass ':invalid' matches elements that do not satisfy their simple text constraints
Pass ':invalid' matches form elements that are the form owner of one or more elements that themselves are candidates for constraint validation but do not satisfy their constraints
Pass ':invalid' matches fieldset elements that have of one or more descendant elements that themselves are candidates for constraint validation but do not satisfy their constraints
Pass ':invalid' matches elements that do not satisfy their pattern constraints
Fail ':invalid' matches elements that do not satisfy their number constraints
Pass ':invalid' matches elements that do not satisfy their number constraints
Pass ':valid' matches new elements that satisfy their constraints
Pass ':invalid' doesn't match new elements that satisfy their constraints
Pass ':valid' doesn't match new elements that do not satisfy their constraints
@ -21,16 +21,16 @@ Pass ':invalid' matches new elements that do not satisfy their constraints
Pass :valid/:invalid styling for <form>
Pass empty form correctly styled on page-load
Pass valid form correctly styled on page-load
Fail invalid form correctly styled on page-load
Pass invalid form correctly styled on page-load
Pass programmatically adding valid to empty form results in correct style
Fail programmatically adding invalid to empty form results in correct style
Pass programmatically adding invalid to empty form results in correct style
Fail programmatically-invalidated form correctly styled
Pass programmatically-validated form correctly styled
Fail programmatically-validated form correctly styled
Pass :valid/:invalid styling for <fieldset>
Pass empty fieldset correctly styled on page-load
Pass valid fieldset correctly styled on page-load
Fail invalid fieldset correctly styled on page-load
Pass invalid fieldset correctly styled on page-load
Pass programmatically adding valid to empty fieldset results in correct style
Fail programmatically adding invalid to empty fieldset results in correct style
Pass programmatically adding invalid to empty fieldset results in correct style
Fail programmatically-invalidated fieldset correctly styled
Pass programmatically-validated fieldset correctly styled
Fail programmatically-validated fieldset correctly styled