Changeset 202143 in webkit


Ignore:
Timestamp:
Jun 16, 2016 3:47:02 PM (8 years ago)
Author:
commit-queue@webkit.org
Message:

:in-range & :out-of-range CSS pseudo-classes shouldn't match inputs without range limitations
https://bugs.webkit.org/show_bug.cgi?id=156558

Patch by Benjamin Poulain <bpoulain@apple.com> on 2016-06-16
Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

  • web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange-expected.txt:

One of the previous match was erroneous.
Our results are still very far from being correct. There are several
bugs affecting our range validation.

Source/WebCore:

The pseudo selectors :in-range and :out-of-range should only
apply if:
-minimum/maximum are defined for the input type
-the input value is/is-not suffering from underflow/overflow.

Only certain types have a valid minimum and maximum:
-number
-range
-date
-month
-week
-time
-datetime-local

Of those, only one has a default minimum and maximum: range.
For all the others, the minimum or maximum is only defined
if the min/max attribute is defined and valid.

This patch addresses these constraints for number and range.
The date types range validation is severely broken and is
left untouched. It really needs a clean rewrite.

Tests: fast/css/pseudo-in-range-basics.html

fast/css/pseudo-in-range-out-of-range-trivial.html
fast/css/pseudo-out-of-range-basics.html

  • html/DateInputType.cpp:

(WebCore::DateInputType::createStepRange):

  • html/DateTimeInputType.cpp:

(WebCore::DateTimeInputType::createStepRange):

  • html/DateTimeLocalInputType.cpp:

(WebCore::DateTimeLocalInputType::createStepRange):

  • html/InputType.cpp:

(WebCore::InputType::isInRange):
(WebCore::InputType::isOutOfRange):
Notice the isEmpty() shortcut.
A value can only overflow/underflow if it is not empty.

  • html/MonthInputType.cpp:

(WebCore::MonthInputType::createStepRange):

  • html/NumberInputType.cpp:

(WebCore::NumberInputType::createStepRange):

  • html/RangeInputType.cpp:

(WebCore::RangeInputType::createStepRange):

  • html/StepRange.cpp:

(WebCore::StepRange::StepRange):

  • html/StepRange.h:

(WebCore::StepRange::hasRangeLimitations):

  • html/WeekInputType.cpp:

(WebCore::WeekInputType::createStepRange):

LayoutTests:

  • fast/css/pseudo-in-range-basics-expected.html: Added.
  • fast/css/pseudo-in-range-basics.html: Added.
  • fast/css/pseudo-in-range-out-of-range-trivial-expected.html: Added.
  • fast/css/pseudo-in-range-out-of-range-trivial.html: Added.
  • fast/css/pseudo-out-of-range-basics-expected.html: Added.
  • fast/css/pseudo-out-of-range-basics.html: Added.
Location:
trunk
Files:
6 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r202132 r202143  
     12016-06-16  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        :in-range & :out-of-range CSS pseudo-classes shouldn't match inputs without range limitations
     4        https://bugs.webkit.org/show_bug.cgi?id=156558
     5
     6        Reviewed by Simon Fraser.
     7
     8        * fast/css/pseudo-in-range-basics-expected.html: Added.
     9        * fast/css/pseudo-in-range-basics.html: Added.
     10        * fast/css/pseudo-in-range-out-of-range-trivial-expected.html: Added.
     11        * fast/css/pseudo-in-range-out-of-range-trivial.html: Added.
     12        * fast/css/pseudo-out-of-range-basics-expected.html: Added.
     13        * fast/css/pseudo-out-of-range-basics.html: Added.
     14
    1152016-06-15  Simon Fraser  <simon.fraser@apple.com>
    216
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r202023 r202143  
     12016-06-16  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        :in-range & :out-of-range CSS pseudo-classes shouldn't match inputs without range limitations
     4        https://bugs.webkit.org/show_bug.cgi?id=156558
     5
     6        Reviewed by Simon Fraser.
     7
     8        * web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange-expected.txt:
     9        One of the previous match was erroneous.
     10        Our results are still very far from being correct. There are several
     11        bugs affecting our range validation.
     12
    1132016-06-13  Joseph Pecoraro  <pecoraro@apple.com>
    214
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange-expected.txt

    r200309 r202143  
    11                                                   
    22
    3 FAIL ':in-range' matches all elements that are candidates for constraint validation, have range limitations, and that are neither suffering from an underflow nor suffering from an overflow assert_array_equals: lengths differ, expected 10 got 8
     3FAIL ':in-range' matches all elements that are candidates for constraint validation, have range limitations, and that are neither suffering from an underflow nor suffering from an overflow assert_array_equals: lengths differ, expected 10 got 7
    44FAIL ':out-of-range' matches all elements that are candidates for constraint validation, have range limitations, and that are either suffering from an underflow or suffering from an overflow assert_array_equals: lengths differ, expected 12 got 2
    5 FAIL ':in-range' update number1's value < min assert_array_equals: lengths differ, expected 9 got 7
     5FAIL ':in-range' update number1's value < min assert_array_equals: lengths differ, expected 9 got 6
    66FAIL ':out-of-range' update number1's value < min assert_array_equals: lengths differ, expected 13 got 3
    7 FAIL ':in-range' update number3's min < value assert_array_equals: lengths differ, expected 10 got 8
     7FAIL ':in-range' update number3's min < value assert_array_equals: lengths differ, expected 10 got 7
    88FAIL ':out-of-range' update number3's min < value assert_array_equals: lengths differ, expected 12 got 2
    99
  • trunk/Source/WebCore/ChangeLog

    r202142 r202143  
     12016-06-16  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        :in-range & :out-of-range CSS pseudo-classes shouldn't match inputs without range limitations
     4        https://bugs.webkit.org/show_bug.cgi?id=156558
     5
     6        Reviewed by Simon Fraser.
     7
     8        The pseudo selectors :in-range and :out-of-range should only
     9        apply if:
     10        -minimum/maximum are defined for the input type
     11        -the input value is/is-not suffering from underflow/overflow.
     12
     13        Only certain types have a valid minimum and maximum:
     14        -number
     15        -range
     16        -date
     17        -month
     18        -week
     19        -time
     20        -datetime-local
     21
     22        Of those, only one has a default minimum and maximum: range.
     23        For all the others, the minimum or maximum is only defined
     24        if the min/max attribute is defined and valid.
     25
     26        This patch addresses these constraints for number and range.
     27        The date types range validation is severely broken and is
     28        left untouched. It really needs a clean rewrite.
     29
     30        Tests: fast/css/pseudo-in-range-basics.html
     31               fast/css/pseudo-in-range-out-of-range-trivial.html
     32               fast/css/pseudo-out-of-range-basics.html
     33
     34        * html/DateInputType.cpp:
     35        (WebCore::DateInputType::createStepRange):
     36        * html/DateTimeInputType.cpp:
     37        (WebCore::DateTimeInputType::createStepRange):
     38        * html/DateTimeLocalInputType.cpp:
     39        (WebCore::DateTimeLocalInputType::createStepRange):
     40        * html/InputType.cpp:
     41        (WebCore::InputType::isInRange):
     42        (WebCore::InputType::isOutOfRange):
     43        Notice the isEmpty() shortcut.
     44        A value can only overflow/underflow if it is not empty.
     45
     46        * html/MonthInputType.cpp:
     47        (WebCore::MonthInputType::createStepRange):
     48        * html/NumberInputType.cpp:
     49        (WebCore::NumberInputType::createStepRange):
     50        * html/RangeInputType.cpp:
     51        (WebCore::RangeInputType::createStepRange):
     52        * html/StepRange.cpp:
     53        (WebCore::StepRange::StepRange):
     54        * html/StepRange.h:
     55        (WebCore::StepRange::hasRangeLimitations):
     56        * html/WeekInputType.cpp:
     57        (WebCore::WeekInputType::createStepRange):
     58
    1592016-06-16  Anders Carlsson  <andersca@apple.com>
    260
  • trunk/Source/WebCore/html/DateInputType.cpp

    r194819 r202143  
    6969    const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), Decimal::fromDouble(DateComponents::maximumDate()));
    7070    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    71     return StepRange(stepBase, minimum, maximum, step, stepDescription);
     71    return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    7272}
    7373
  • trunk/Source/WebCore/html/DateTimeInputType.cpp

    r194819 r202143  
    7070    const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), Decimal::fromDouble(DateComponents::maximumDateTime()));
    7171    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    72     return StepRange(stepBase, minimum, maximum, step, stepDescription);
     72    return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    7373}
    7474
  • trunk/Source/WebCore/html/DateTimeLocalInputType.cpp

    r194819 r202143  
    7676    const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), Decimal::fromDouble(DateComponents::maximumDateTime()));
    7777    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    78     return StepRange(stepBase, minimum, maximum, step, stepDescription);
     78    return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    7979}
    8080
  • trunk/Source/WebCore/html/InputType.cpp

    r202105 r202143  
    340340        return false;
    341341
     342    StepRange stepRange(createStepRange(RejectAny));
     343    if (!stepRange.hasRangeLimitations())
     344        return false;
     345   
    342346    const Decimal numericValue = parseToNumberOrNaN(value);
    343347    if (!numericValue.isFinite())
    344348        return true;
    345349
     350    return numericValue >= stepRange.minimum() && numericValue <= stepRange.maximum();
     351}
     352
     353bool InputType::isOutOfRange(const String& value) const
     354{
     355    if (!isSteppable() || value.isEmpty())
     356        return false;
     357
    346358    StepRange stepRange(createStepRange(RejectAny));
    347     return numericValue >= stepRange.minimum() && numericValue <= stepRange.maximum();
    348 }
    349 
    350 bool InputType::isOutOfRange(const String& value) const
    351 {
    352     if (!isSteppable())
     359    if (!stepRange.hasRangeLimitations())
    353360        return false;
    354361
     
    357364        return true;
    358365
    359     StepRange stepRange(createStepRange(RejectAny));
    360366    return numericValue < stepRange.minimum() || numericValue > stepRange.maximum();
    361367}
  • trunk/Source/WebCore/html/MonthInputType.cpp

    r194819 r202143  
    9898    const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), Decimal::fromDouble(DateComponents::maximumMonth()));
    9999    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    100     return StepRange(stepBase, minimum, maximum, step, stepDescription);
     100    return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    101101}
    102102
  • trunk/Source/WebCore/html/NumberInputType.cpp

    r195452 r202143  
    157157    // FIXME: We should use numeric_limits<double>::max for number input type.
    158158    const Decimal floatMax = Decimal::fromDouble(std::numeric_limits<float>::max());
    159     const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), -floatMax);
    160     const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), floatMax);
    161     const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    162     return StepRange(stepBase, minimum, maximum, step, stepDescription);
     159    const Element& element = this->element();
     160
     161    RangeLimitations rangeLimitations = RangeLimitations::Invalid;
     162    auto extractBound = [&] (const QualifiedName& attributeName, const Decimal& defaultValue) -> Decimal {
     163        const AtomicString& attributeValue = element.fastGetAttribute(attributeName);
     164        Decimal valueFromAttribute = parseToNumberOrNaN(attributeValue);
     165        if (valueFromAttribute.isFinite()) {
     166            rangeLimitations = RangeLimitations::Valid;
     167            return valueFromAttribute;
     168        }
     169        return defaultValue;
     170    };
     171    Decimal minimum = extractBound(minAttr, -floatMax);
     172    Decimal maximum = extractBound(maxAttr, floatMax);
     173
     174    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element.fastGetAttribute(stepAttr));
     175    return StepRange(stepBase, rangeLimitations, minimum, maximum, step, stepDescription);
    163176}
    164177
  • trunk/Source/WebCore/html/RangeInputType.cpp

    r202105 r202143  
    124124    if (!precisionValue.isNull()) {
    125125        const Decimal step = equalLettersIgnoringASCIICase(precisionValue, "float") ? Decimal::nan() : 1;
    126         return StepRange(minimum, minimum, maximum, step, stepDescription);
     126        return StepRange(minimum, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    127127    }
    128128
    129129    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    130     return StepRange(minimum, minimum, maximum, step, stepDescription);
     130    return StepRange(minimum, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    131131}
    132132
  • trunk/Source/WebCore/html/StepRange.cpp

    r195452 r202143  
    3636    , m_step(1)
    3737    , m_stepBase(0)
    38     , m_hasStep(false)
    3938{
    4039}
     
    4645    , m_stepBase(stepRange.m_stepBase)
    4746    , m_stepDescription(stepRange.m_stepDescription)
     47    , m_hasRangeLimitations(stepRange.m_hasRangeLimitations)
    4848    , m_hasStep(stepRange.m_hasStep)
    4949{
    5050}
    5151
    52 StepRange::StepRange(const Decimal& stepBase, const Decimal& minimum, const Decimal& maximum, const Decimal& step, const StepDescription& stepDescription)
     52StepRange::StepRange(const Decimal& stepBase, RangeLimitations rangeLimitations, const Decimal& minimum, const Decimal& maximum, const Decimal& step, const StepDescription& stepDescription)
    5353    : m_maximum(maximum)
    5454    , m_minimum(minimum)
     
    5656    , m_stepBase(stepBase.isFinite() ? stepBase : 1)
    5757    , m_stepDescription(stepDescription)
     58    , m_hasRangeLimitations(rangeLimitations == RangeLimitations::Valid)
    5859    , m_hasStep(step.isFinite())
    5960{
  • trunk/Source/WebCore/html/StepRange.h

    r128572 r202143  
    3131
    3232enum AnyStepHandling { RejectAny, AnyIsDefaultStep };
     33
     34enum class RangeLimitations {
     35    Valid,
     36    Invalid
     37};
    3338
    3439class StepRange {
     
    7277    StepRange();
    7378    StepRange(const StepRange&);
    74     StepRange(const Decimal& stepBase, const Decimal& minimum, const Decimal& maximum, const Decimal& step, const StepDescription&);
     79    StepRange(const Decimal& stepBase, RangeLimitations, const Decimal& minimum, const Decimal& maximum, const Decimal& step, const StepDescription&);
    7580    Decimal acceptableError() const;
    7681    Decimal alignValueForStep(const Decimal& currentValue, const Decimal& newValue) const;
    7782    Decimal clampValue(const Decimal& value) const;
    7883    bool hasStep() const { return m_hasStep; }
     84    bool hasRangeLimitations() const { return m_hasRangeLimitations; }
    7985    Decimal maximum() const { return m_maximum; }
    8086    Decimal minimum() const { return m_minimum; }
     
    115121    const Decimal m_stepBase;
    116122    const StepDescription m_stepDescription;
    117     const bool m_hasStep;
     123    const bool m_hasRangeLimitations { false };
     124    const bool m_hasStep { false };
    118125};
    119126
  • trunk/Source/WebCore/html/TimeInputType.cpp

    r194819 r202143  
    8585    const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), Decimal::fromDouble(DateComponents::maximumTime()));
    8686    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    87     return StepRange(stepBase, minimum, maximum, step, stepDescription);
     87    return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    8888}
    8989
  • trunk/Source/WebCore/html/WeekInputType.cpp

    r194819 r202143  
    6464    const Decimal maximum = parseToNumber(element().fastGetAttribute(maxAttr), Decimal::fromDouble(DateComponents::maximumWeek()));
    6565    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
    66     return StepRange(stepBase, minimum, maximum, step, stepDescription);
     66    return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    6767}
    6868
Note: See TracChangeset for help on using the changeset viewer.