Changeset 271672 in webkit


Ignore:
Timestamp:
Jan 20, 2021 1:54:37 PM (18 months ago)
Author:
ysuzuki@apple.com
Message:

Accelerate HTMLInputElement creation
https://bugs.webkit.org/show_bug.cgi?id=220758

Reviewed by Simon Fraser.

HTMLInputElement creation is too slow.

  1. InputType is excessively using virtual dispatching, which is too slow for hot path.
  2. HTMLInputElement creates internal elements as a shadow DOM and its creation is too generic.
  3. We are setting inner text element's editability in a very generic way. This allocates ElementData for each elements while attributes are almost the same.

In this patch,

  1. We add m_type field in InputType, and for the hot path, we attempt to devirtualize things due to performance problem.
  2. We pass "parsing phase" information to shadow DOM creation to make them fast.
  3. We initialize editibility when creating TextControlInnerTextElement. And we use parserSetAttributes to set shared ElementData. This is faster and less memory.
  4. We also shrink sizeof(Style::Scope) to reduce size of allocation when using shadow DOM.

This change offers 1% progression in Speedometer2/jQuery.

  • html/BaseButtonInputType.h:

(WebCore::BaseButtonInputType::BaseButtonInputType):

  • html/BaseCheckableInputType.h:

(WebCore::BaseCheckableInputType::BaseCheckableInputType):

  • html/BaseClickableWithKeyInputType.h:

(WebCore::BaseClickableWithKeyInputType::BaseClickableWithKeyInputType):

  • html/BaseDateAndTimeInputType.cpp:

(WebCore::BaseDateAndTimeInputType::isSteppableSlow const):
(WebCore::BaseDateAndTimeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
(WebCore::BaseDateAndTimeInputType::isSteppable const): Deleted.
(WebCore::BaseDateAndTimeInputType::createShadowSubtree): Deleted.

  • html/BaseDateAndTimeInputType.h:

(WebCore::BaseDateAndTimeInputType::BaseDateAndTimeInputType):

  • html/BaseTextInputType.h:

(WebCore::BaseTextInputType::BaseTextInputType):

  • html/ButtonInputType.h:
  • html/CheckboxInputType.h:
  • html/ColorInputType.cpp:

(WebCore::ColorInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
(WebCore::ColorInputType::createShadowSubtree): Deleted.

  • html/ColorInputType.h:
  • html/DateInputType.cpp:

(WebCore::DateInputType::DateInputType):

  • html/DateInputType.h:
  • html/DateTimeLocalInputType.h:
  • html/EmailInputType.h:
  • html/FileInputType.cpp:

(WebCore::FileInputType::FileInputType):
(WebCore::FileInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
(WebCore::FileInputType::createShadowSubtree): Deleted.

  • html/FileInputType.h:
  • html/HTMLInputElement.cpp:

(WebCore::HTMLInputElement::didAddUserAgentShadowRoot):
(WebCore::HTMLInputElement::isValid const):
(WebCore::HTMLInputElement::updateType):

  • html/HTMLTextAreaElement.cpp:

(WebCore::HTMLTextAreaElement::didAddUserAgentShadowRoot):

  • html/HTMLTextFormControlElement.cpp:

(WebCore::HTMLTextFormControlElement::updateInnerTextElementEditability):

  • html/HiddenInputType.h:
  • html/ImageInputType.cpp:

(WebCore::ImageInputType::ImageInputType):

  • html/ImageInputType.h:
  • html/InputType.cpp:

(WebCore::InputType::isInvalid const):
(WebCore::InputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
(WebCore::InputType::isSteppable const):
(WebCore::InputType::createShadowSubtree): Deleted.

  • html/InputType.h:

(WebCore::InputType::InputType):
(WebCore::InputType::isSteppableSlow const):
(WebCore::isInvalidInputType):

  • html/MonthInputType.h:
  • html/NumberInputType.cpp:

(WebCore::NumberInputType::isSteppableSlow const):
(WebCore::NumberInputType::isSteppable const): Deleted.

  • html/NumberInputType.h:
  • html/PasswordInputType.h:
  • html/RadioInputType.h:
  • html/RangeInputType.cpp:

(WebCore::RangeInputType::RangeInputType):
(WebCore::RangeInputType::isSteppableSlow const):
(WebCore::RangeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
(WebCore::RangeInputType::isSteppable const): Deleted.
(WebCore::RangeInputType::createShadowSubtree): Deleted.

  • html/RangeInputType.h:
  • html/ResetInputType.h:
  • html/SearchInputType.cpp:

(WebCore::SearchInputType::SearchInputType):
(WebCore::SearchInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
(WebCore::SearchInputType::createShadowSubtree): Deleted.

  • html/SearchInputType.h:
  • html/SubmitInputType.h:
  • html/TelephoneInputType.h:
  • html/TextFieldInputType.cpp:

(WebCore::TextFieldInputType::TextFieldInputType):
(WebCore::TextFieldInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
(WebCore::TextFieldInputType::createShadowSubtree): Deleted.

  • html/TextFieldInputType.h:
  • html/TextInputType.h:
  • html/TimeInputType.cpp:

(WebCore::TimeInputType::TimeInputType):

  • html/TimeInputType.h:
  • html/URLInputType.h:
  • html/WeekInputType.h:
  • html/shadow/TextControlInnerElements.cpp:

(WebCore::TextControlInnerTextElement::create):
(WebCore::TextControlInnerTextElement::updateInnerTextElementEditabilityImpl):

  • html/shadow/TextControlInnerElements.h:
  • style/StyleScope.h:
Location:
trunk/Source/WebCore
Files:
47 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r271671 r271672  
     12021-01-20  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        Accelerate HTMLInputElement creation
     4        https://bugs.webkit.org/show_bug.cgi?id=220758
     5
     6        Reviewed by Simon Fraser.
     7
     8        HTMLInputElement creation is too slow.
     9
     10        1. InputType is excessively using virtual dispatching, which is too slow for hot path.
     11        2. HTMLInputElement creates internal elements as a shadow DOM and its creation is too generic.
     12        3. We are setting inner text element's editability in a very generic way. This allocates ElementData for each elements while attributes are almost the same.
     13
     14        In this patch,
     15
     16        1. We add m_type field in InputType, and for the hot path, we attempt to devirtualize things due to performance problem.
     17        2. We pass "parsing phase" information to shadow DOM creation to make them fast.
     18        3. We initialize editibility when creating TextControlInnerTextElement. And we use parserSetAttributes to set shared ElementData. This is faster and less memory.
     19        4. We also shrink sizeof(Style::Scope) to reduce size of allocation when using shadow DOM.
     20
     21        This change offers 1% progression in Speedometer2/jQuery.
     22
     23        * html/BaseButtonInputType.h:
     24        (WebCore::BaseButtonInputType::BaseButtonInputType):
     25        * html/BaseCheckableInputType.h:
     26        (WebCore::BaseCheckableInputType::BaseCheckableInputType):
     27        * html/BaseClickableWithKeyInputType.h:
     28        (WebCore::BaseClickableWithKeyInputType::BaseClickableWithKeyInputType):
     29        * html/BaseDateAndTimeInputType.cpp:
     30        (WebCore::BaseDateAndTimeInputType::isSteppableSlow const):
     31        (WebCore::BaseDateAndTimeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
     32        (WebCore::BaseDateAndTimeInputType::isSteppable const): Deleted.
     33        (WebCore::BaseDateAndTimeInputType::createShadowSubtree): Deleted.
     34        * html/BaseDateAndTimeInputType.h:
     35        (WebCore::BaseDateAndTimeInputType::BaseDateAndTimeInputType):
     36        * html/BaseTextInputType.h:
     37        (WebCore::BaseTextInputType::BaseTextInputType):
     38        * html/ButtonInputType.h:
     39        * html/CheckboxInputType.h:
     40        * html/ColorInputType.cpp:
     41        (WebCore::ColorInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
     42        (WebCore::ColorInputType::createShadowSubtree): Deleted.
     43        * html/ColorInputType.h:
     44        * html/DateInputType.cpp:
     45        (WebCore::DateInputType::DateInputType):
     46        * html/DateInputType.h:
     47        * html/DateTimeLocalInputType.h:
     48        * html/EmailInputType.h:
     49        * html/FileInputType.cpp:
     50        (WebCore::FileInputType::FileInputType):
     51        (WebCore::FileInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
     52        (WebCore::FileInputType::createShadowSubtree): Deleted.
     53        * html/FileInputType.h:
     54        * html/HTMLInputElement.cpp:
     55        (WebCore::HTMLInputElement::didAddUserAgentShadowRoot):
     56        (WebCore::HTMLInputElement::isValid const):
     57        (WebCore::HTMLInputElement::updateType):
     58        * html/HTMLTextAreaElement.cpp:
     59        (WebCore::HTMLTextAreaElement::didAddUserAgentShadowRoot):
     60        * html/HTMLTextFormControlElement.cpp:
     61        (WebCore::HTMLTextFormControlElement::updateInnerTextElementEditability):
     62        * html/HiddenInputType.h:
     63        * html/ImageInputType.cpp:
     64        (WebCore::ImageInputType::ImageInputType):
     65        * html/ImageInputType.h:
     66        * html/InputType.cpp:
     67        (WebCore::InputType::isInvalid const):
     68        (WebCore::InputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
     69        (WebCore::InputType::isSteppable const):
     70        (WebCore::InputType::createShadowSubtree): Deleted.
     71        * html/InputType.h:
     72        (WebCore::InputType::InputType):
     73        (WebCore::InputType::isSteppableSlow const):
     74        (WebCore::isInvalidInputType):
     75        * html/MonthInputType.h:
     76        * html/NumberInputType.cpp:
     77        (WebCore::NumberInputType::isSteppableSlow const):
     78        (WebCore::NumberInputType::isSteppable const): Deleted.
     79        * html/NumberInputType.h:
     80        * html/PasswordInputType.h:
     81        * html/RadioInputType.h:
     82        * html/RangeInputType.cpp:
     83        (WebCore::RangeInputType::RangeInputType):
     84        (WebCore::RangeInputType::isSteppableSlow const):
     85        (WebCore::RangeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
     86        (WebCore::RangeInputType::isSteppable const): Deleted.
     87        (WebCore::RangeInputType::createShadowSubtree): Deleted.
     88        * html/RangeInputType.h:
     89        * html/ResetInputType.h:
     90        * html/SearchInputType.cpp:
     91        (WebCore::SearchInputType::SearchInputType):
     92        (WebCore::SearchInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
     93        (WebCore::SearchInputType::createShadowSubtree): Deleted.
     94        * html/SearchInputType.h:
     95        * html/SubmitInputType.h:
     96        * html/TelephoneInputType.h:
     97        * html/TextFieldInputType.cpp:
     98        (WebCore::TextFieldInputType::TextFieldInputType):
     99        (WebCore::TextFieldInputType::createShadowSubtreeAndUpdateInnerTextElementEditability):
     100        (WebCore::TextFieldInputType::createShadowSubtree): Deleted.
     101        * html/TextFieldInputType.h:
     102        * html/TextInputType.h:
     103        * html/TimeInputType.cpp:
     104        (WebCore::TimeInputType::TimeInputType):
     105        * html/TimeInputType.h:
     106        * html/URLInputType.h:
     107        * html/WeekInputType.h:
     108        * html/shadow/TextControlInnerElements.cpp:
     109        (WebCore::TextControlInnerTextElement::create):
     110        (WebCore::TextControlInnerTextElement::updateInnerTextElementEditabilityImpl):
     111        * html/shadow/TextControlInnerElements.h:
     112        * style/StyleScope.h:
     113
    11142021-01-20  Manuel Rego Casasnovas  <rego@igalia.com>
    2115
  • trunk/Source/WebCore/html/BaseButtonInputType.h

    r221914 r271672  
    3838class BaseButtonInputType : public BaseClickableWithKeyInputType {
    3939protected:
    40     explicit BaseButtonInputType(HTMLInputElement& element) : BaseClickableWithKeyInputType(element) { }
     40    explicit BaseButtonInputType(Type type, HTMLInputElement& element) : BaseClickableWithKeyInputType(type, element) { }
    4141
    4242private:
  • trunk/Source/WebCore/html/BaseCheckableInputType.h

    r259687 r271672  
    3838class BaseCheckableInputType : public InputType {
    3939protected:
    40     explicit BaseCheckableInputType(HTMLInputElement& element) : InputType(element) { }
     40    explicit BaseCheckableInputType(Type type, HTMLInputElement& element) : InputType(type, element) { }
    4141    ShouldCallBaseEventHandler handleKeydownEvent(KeyboardEvent&) override;
    4242    void fireInputAndChangeEvents();
  • trunk/Source/WebCore/html/BaseClickableWithKeyInputType.h

    r259687 r271672  
    4444   
    4545protected:
    46     explicit BaseClickableWithKeyInputType(HTMLInputElement& element) : InputType(element) { }
     46    explicit BaseClickableWithKeyInputType(Type type, HTMLInputElement& element) : InputType(type, element) { }
    4747
    4848private:
  • trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp

    r269027 r271672  
    168168}
    169169
    170 bool BaseDateAndTimeInputType::isSteppable() const
     170bool BaseDateAndTimeInputType::isSteppableSlow() const
    171171{
    172172    return true;
     
    308308}
    309309
    310 void BaseDateAndTimeInputType::createShadowSubtree()
     310void BaseDateAndTimeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool)
    311311{
    312312    ASSERT(element());
  • trunk/Source/WebCore/html/BaseDateAndTimeInputType.h

    r267003 r271672  
    5959    };
    6060
    61     BaseDateAndTimeInputType(HTMLInputElement& element) : InputType(element) { }
     61    BaseDateAndTimeInputType(Type type, HTMLInputElement& element) : InputType(type, element) { }
    6262    ~BaseDateAndTimeInputType();
    6363
     
    6868    bool shouldHaveSecondField(const DateComponents&) const;
    6969    bool shouldHaveMillisecondField(const DateComponents&) const;
     70    bool typeMismatchFor(const String&) const final;
     71    bool typeMismatch() const final;
     72    bool valueMissing(const String&) const final;
    7073
    7174private:
     
    97100    double valueAsDouble() const final;
    98101    ExceptionOr<void> setValueAsDecimal(const Decimal&, TextFieldEventBehavior) const final;
    99     bool typeMismatchFor(const String&) const final;
    100     bool typeMismatch() const final;
    101     bool valueMissing(const String&) const final;
    102102    Decimal defaultValueForStepUp() const override;
    103     bool isSteppable() const final;
     103    bool isSteppableSlow() const final;
    104104    String localizeValue(const String&) const final;
    105105    bool supportsReadOnly() const final;
     
    109109
    110110    void handleDOMActivateEvent(Event&) override;
    111     void createShadowSubtree() final;
     111    void createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool) final;
    112112    void destroyShadowSubtree() final;
    113113    void updateInnerTextValue() final;
  • trunk/Source/WebCore/html/BaseTextInputType.h

    r208179 r271672  
    3939class BaseTextInputType : public TextFieldInputType {
    4040protected:
    41     explicit BaseTextInputType(HTMLInputElement& element) : TextFieldInputType(element) { }
     41    explicit BaseTextInputType(Type type, HTMLInputElement& element) : TextFieldInputType(type, element) { }
    4242
    43 private:
    4443    bool isTextType() const override;
    4544    bool patternMismatch(const String&) const override;
  • trunk/Source/WebCore/html/ButtonInputType.h

    r246490 r271672  
    3636
    3737class ButtonInputType final : public BaseButtonInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit ButtonInputType(HTMLInputElement& element) : BaseButtonInputType(element) { }
     40    explicit ButtonInputType(HTMLInputElement& element) : BaseButtonInputType(Type::Button, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/CheckboxInputType.h

    r246490 r271672  
    3636
    3737class CheckboxInputType final : public BaseCheckableInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit CheckboxInputType(HTMLInputElement& element) : BaseCheckableInputType(element) { }
     40    explicit CheckboxInputType(HTMLInputElement& element) : BaseCheckableInputType(Type::Checkbox, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/ColorInputType.cpp

    r264565 r271672  
    140140}
    141141
    142 void ColorInputType::createShadowSubtree()
     142void ColorInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool)
    143143{
    144144    ASSERT(element());
  • trunk/Source/WebCore/html/ColorInputType.h

    r264280 r271672  
    4141
    4242class ColorInputType final : public BaseClickableWithKeyInputType, private ColorChooserClient {
     43    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4344public:
    44     explicit ColorInputType(HTMLInputElement& element) : BaseClickableWithKeyInputType(element) { }
     45    explicit ColorInputType(HTMLInputElement& element) : BaseClickableWithKeyInputType(Type::Color, element) { }
    4546    virtual ~ColorInputType();
    4647
     
    5859    String fallbackValue() const final;
    5960    String sanitizeValue(const String&) const final;
    60     void createShadowSubtree() final;
     61    void createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool) final;
    6162    void setValue(const String&, bool valueChanged, TextFieldEventBehavior) final;
    6263    void handleDOMActivateEvent(Event&) final;
  • trunk/Source/WebCore/html/DateInputType.cpp

    r267003 r271672  
    5151
    5252DateInputType::DateInputType(HTMLInputElement& element)
    53     : BaseDateAndTimeInputType(element)
     53    : BaseDateAndTimeInputType(Type::Date, element)
    5454{
    5555}
  • trunk/Source/WebCore/html/DateInputType.h

    r267003 r271672  
    3838
    3939class DateInputType final : public BaseDateAndTimeInputType {
     40    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4041public:
    4142    explicit DateInputType(HTMLInputElement&);
  • trunk/Source/WebCore/html/DateTimeLocalInputType.h

    r267003 r271672  
    3838
    3939class DateTimeLocalInputType final : public BaseDateAndTimeInputType {
     40    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4041public:
    4142    explicit DateTimeLocalInputType(HTMLInputElement& element)
    42         : BaseDateAndTimeInputType(element)
     43        : BaseDateAndTimeInputType(Type::DateTimeLocal, element)
    4344    {
    4445    }
  • trunk/Source/WebCore/html/EmailInputType.h

    r246490 r271672  
    3636
    3737class EmailInputType final : public BaseTextInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit EmailInputType(HTMLInputElement& element) : BaseTextInputType(element) { }
     40    explicit EmailInputType(HTMLInputElement& element) : BaseTextInputType(Type::Email, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/FileInputType.cpp

    r270784 r271672  
    107107
    108108FileInputType::FileInputType(HTMLInputElement& element)
    109     : BaseClickableWithKeyInputType(element)
     109    : BaseClickableWithKeyInputType(Type::File, element)
    110110    , m_fileList(FileList::create())
    111111{
     
    279279}
    280280
    281 void FileInputType::createShadowSubtree()
     281void FileInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool)
    282282{
    283283    ASSERT(element());
  • trunk/Source/WebCore/html/FileInputType.h

    r265422 r271672  
    4646
    4747class FileInputType final : public BaseClickableWithKeyInputType, private FileChooserClient, private FileIconLoaderClient, public CanMakeWeakPtr<FileInputType> {
     48    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4849public:
    4950    explicit FileInputType(HTMLInputElement&);
     
    7879    Icon* icon() const final;
    7980    bool isFileUpload() const final;
    80     void createShadowSubtree() final;
     81    void createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool) final;
    8182    void disabledStateChanged() final;
    8283    void attributeChanged(const QualifiedName&) final;
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r269587 r271672  
    159159{
    160160    Ref<InputType> protectedInputType(*m_inputType);
    161     protectedInputType->createShadowSubtree();
    162     updateInnerTextElementEditability();
     161    protectedInputType->createShadowSubtreeAndUpdateInnerTextElementEditability(m_parsingInProgress ? ChildChange::Source::Parser : ChildChange::Source::API, isInnerTextElementEditable());
    163162}
    164163
     
    391390
    392391    String value = this->value();
    393     bool someError = m_inputType->typeMismatch() || m_inputType->stepMismatch(value) || m_inputType->rangeUnderflow(value) || m_inputType->rangeOverflow(value)
    394         || tooShort(value, CheckDirtyFlag) || tooLong(value, CheckDirtyFlag) || m_inputType->patternMismatch(value) || m_inputType->valueMissing(value)
    395         || m_inputType->hasBadInput() || customError();
     392    bool someError = m_inputType->isInvalid(value) || tooShort(value, CheckDirtyFlag) || tooLong(value, CheckDirtyFlag) || customError();
    396393    return !someError;
    397394}
     
    565562
    566563    m_inputType = WTFMove(newType);
    567     m_inputType->createShadowSubtree();
    568     updateInnerTextElementEditability();
     564    m_inputType->createShadowSubtreeAndUpdateInnerTextElementEditability(m_parsingInProgress ? ChildChange::Source::Parser : ChildChange::Source::API, isInnerTextElementEditable());
    569565
    570566    setNeedsWillValidateCheck();
  • trunk/Source/WebCore/html/HTMLTextAreaElement.cpp

    r269587 r271672  
    111111void HTMLTextAreaElement::didAddUserAgentShadowRoot(ShadowRoot& root)
    112112{
    113     root.appendChild(TextControlInnerTextElement::create(document()));
    114     updateInnerTextElementEditability();
     113    root.appendChild(TextControlInnerTextElement::create(document(), isInnerTextElementEditable()));
    115114}
    116115
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp

    r270983 r271672  
    541541void HTMLTextFormControlElement::updateInnerTextElementEditability()
    542542{
    543     if (auto innerText = innerTextElement()) {
    544         static MainThreadNeverDestroyed<const AtomString> plainTextOnlyName("plaintext-only", AtomString::ConstructFromLiteral);
    545         static MainThreadNeverDestroyed<const AtomString> falseName("false", AtomString::ConstructFromLiteral);
    546         const auto& value = isInnerTextElementEditable() ? plainTextOnlyName.get() : falseName.get();
    547         innerText->setAttributeWithoutSynchronization(contenteditableAttr, value);
    548     }
     543    if (auto innerText = innerTextElement())
     544        innerText->updateInnerTextElementEditability(isInnerTextElementEditable());
    549545}
    550546
  • trunk/Source/WebCore/html/HiddenInputType.h

    r259687 r271672  
    3636
    3737class HiddenInputType final : public InputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit HiddenInputType(HTMLInputElement& element) : InputType(element) { }
     40    explicit HiddenInputType(HTMLInputElement& element) : InputType(Type::Hidden, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/ImageInputType.cpp

    r246490 r271672  
    4141
    4242ImageInputType::ImageInputType(HTMLInputElement& element)
    43     : BaseButtonInputType(element)
     43    : BaseButtonInputType(Type::Image, element)
    4444{
    4545}
  • trunk/Source/WebCore/html/ImageInputType.h

    r246490 r271672  
    3939
    4040class ImageInputType final : public BaseButtonInputType {
     41    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4142public:
    4243    explicit ImageInputType(HTMLInputElement&);
  • trunk/Source/WebCore/html/InputType.cpp

    r271446 r271672  
    302302}
    303303
     304bool InputType::isInvalid(const String& value) const
     305{
     306    switch (m_type) {
     307    case Type::Button:
     308        return isInvalidInputType<ButtonInputType>(*this, value);
     309    case Type::Checkbox:
     310        return isInvalidInputType<CheckboxInputType>(*this, value);
     311    case Type::Color:
     312#if ENABLE(INPUT_TYPE_COLOR)
     313        return isInvalidInputType<ColorInputType>(*this, value);
     314#else
     315        return false;
     316#endif
     317    case Type::Date:
     318#if ENABLE(INPUT_TYPE_DATE)
     319        return isInvalidInputType<DateInputType>(*this, value);
     320#else
     321        return false;
     322#endif
     323    case Type::DateTimeLocal:
     324#if ENABLE(INPUT_TYPE_DATETIMELOCAL)
     325        return isInvalidInputType<DateTimeLocalInputType>(*this, value);
     326#else
     327        return false;
     328#endif
     329    case Type::Email:
     330        return isInvalidInputType<EmailInputType>(*this, value);
     331    case Type::File:
     332        return isInvalidInputType<FileInputType>(*this, value);
     333    case Type::Hidden:
     334        return isInvalidInputType<HiddenInputType>(*this, value);
     335    case Type::Image:
     336        return isInvalidInputType<ImageInputType>(*this, value);
     337    case Type::Month:
     338#if ENABLE(INPUT_TYPE_MONTH)
     339        return isInvalidInputType<MonthInputType>(*this, value);
     340#else
     341        return false;
     342#endif
     343    case Type::Number:
     344        return isInvalidInputType<NumberInputType>(*this, value);
     345    case Type::Password:
     346        return isInvalidInputType<PasswordInputType>(*this, value);
     347    case Type::Radio:
     348        return isInvalidInputType<RadioInputType>(*this, value);
     349    case Type::Range:
     350        return isInvalidInputType<RangeInputType>(*this, value);
     351    case Type::Reset:
     352        return isInvalidInputType<ResetInputType>(*this, value);
     353    case Type::Search:
     354        return isInvalidInputType<SearchInputType>(*this, value);
     355    case Type::Submit:
     356        return isInvalidInputType<SubmitInputType>(*this, value);
     357    case Type::Telephone:
     358        return isInvalidInputType<TelephoneInputType>(*this, value);
     359    case Type::Time:
     360#if ENABLE(INPUT_TYPE_TIME)
     361        return isInvalidInputType<TimeInputType>(*this, value);
     362#else
     363        return false;
     364#endif
     365    case Type::URL:
     366        return isInvalidInputType<URLInputType>(*this, value);
     367    case Type::Week:
     368#if ENABLE(INPUT_TYPE_WEEK)
     369        return isInvalidInputType<WeekInputType>(*this, value);
     370#else
     371        return false;
     372#endif
     373    case Type::Text:
     374        return isInvalidInputType<TextInputType>(*this, value);
     375    }
     376    ASSERT_NOT_REACHED();
     377    return false;
     378}
     379
    304380Decimal InputType::defaultValueForStepUp() const
    305381{
     
    493569}
    494570
    495 void InputType::createShadowSubtree()
     571void InputType::createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool)
    496572{
    497573}
     
    856932}
    857933
     934// Do not use virtual function for performance reason.
    858935bool InputType::isSteppable() const
    859936{
    860     return false;
     937    switch (m_type) {
     938    case Type::Date:
     939    case Type::DateTimeLocal:
     940    case Type::Month:
     941    case Type::Time:
     942    case Type::Week:
     943    case Type::Number:
     944    case Type::Range:
     945        ASSERT(isSteppableSlow());
     946        return true;
     947    default:
     948        ASSERT(!isSteppableSlow());
     949        return false;
     950    }
    861951}
    862952
  • trunk/Source/WebCore/html/InputType.h

    r266114 r271672  
    7171class InputType : public RefCounted<InputType> {
    7272    WTF_MAKE_FAST_ALLOCATED;
    73 
    7473public:
     74    enum class Type : uint8_t {
     75        Button,
     76        Checkbox,
     77        Color,
     78        Date,
     79        DateTimeLocal,
     80        Email,
     81        File,
     82        Hidden,
     83        Image,
     84        Month,
     85        Number,
     86        Password,
     87        Radio,
     88        Range,
     89        Reset,
     90        Search,
     91        Submit,
     92        Telephone,
     93        Time,
     94        URL,
     95        Week,
     96        Text,
     97    };
     98
    7599    static Ref<InputType> create(HTMLInputElement&, const AtomString&);
    76100    static Ref<InputType> createText(HTMLInputElement&);
     
    218242    // Shadow tree handling.
    219243
    220     virtual void createShadowSubtree();
     244    virtual void createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool);
    221245    virtual void destroyShadowSubtree();
    222246
     
    255279    virtual bool isEnumeratable();
    256280    virtual bool isCheckable();
    257     virtual bool isSteppable() const;
    258281    virtual bool shouldRespectHeightAndWidthAttributes();
    259282    virtual bool supportsPlaceholder() const;
     
    276299    virtual Vector<Color> suggestedColors() const;
    277300
     301    bool isSteppable() const;
     302
    278303    // Parses the specified string for the type, and return
    279304    // the Decimal value for the parsing result if the parsing
     
    292317    virtual unsigned width() const;
    293318
     319    bool isInvalid(const String&) const;
     320
    294321    void dispatchSimulatedClickIfActive(KeyboardEvent&) const;
    295322
     
    308335
    309336protected:
    310     explicit InputType(HTMLInputElement& element)
    311         : m_element(makeWeakPtr(element)) { }
     337    explicit InputType(Type type, HTMLInputElement& element)
     338        : m_type(type)
     339        , m_element(makeWeakPtr(element)) { }
    312340    HTMLInputElement* element() const { return m_element.get(); }
    313341    Chrome* chrome() const;
    314342    Decimal parseToNumberOrNaN(const String&) const;
     343    virtual bool isSteppableSlow() const { return false; }
    315344
    316345private:
     
    318347    ExceptionOr<void> applyStep(int count, AnyStepHandling, TextFieldEventBehavior);
    319348
     349    const Type m_type;
    320350    // m_element is null if this InputType is no longer associated with an element (either the element died or changed input type).
    321351    WeakPtr<HTMLInputElement> m_element;
    322352};
     353
     354template<typename DowncastedType>
     355ALWAYS_INLINE bool isInvalidInputType(const InputType& baseInputType, const String& value)
     356{
     357    auto& inputType = static_cast<const DowncastedType&>(baseInputType);
     358    return inputType.typeMismatch() || inputType.stepMismatch(value) || inputType.rangeUnderflow(value) || inputType.rangeOverflow(value) || inputType.patternMismatch(value) || inputType.valueMissing(value) || inputType.hasBadInput();
     359}
    323360
    324361} // namespace WebCore
  • trunk/Source/WebCore/html/MonthInputType.h

    r267003 r271672  
    3838
    3939class MonthInputType final : public BaseDateAndTimeInputType {
     40    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4041public:
    4142    explicit MonthInputType(HTMLInputElement& element)
    42         : BaseDateAndTimeInputType(element)
     43        : BaseDateAndTimeInputType(Type::Month, element)
    4344    {
    4445    }
  • trunk/Source/WebCore/html/NumberInputType.cpp

    r264600 r271672  
    211211}
    212212
    213 bool NumberInputType::isSteppable() const
     213bool NumberInputType::isSteppableSlow() const
    214214{
    215215    return true;
  • trunk/Source/WebCore/html/NumberInputType.h

    r246490 r271672  
    3737
    3838class NumberInputType final : public TextFieldInputType {
     39    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3940public:
    40     explicit NumberInputType(HTMLInputElement& element) : TextFieldInputType(element) { }
     41    explicit NumberInputType(HTMLInputElement& element) : TextFieldInputType(Type::Number, element) { }
    4142
    4243private:
     
    5051    bool sizeShouldIncludeDecoration(int defaultSize, int& preferredSize) const final;
    5152    float decorationWidth() const final;
    52     bool isSteppable() const final;
     53    bool isSteppableSlow() const final;
    5354    StepRange createStepRange(AnyStepHandling) const final;
    5455    ShouldCallBaseEventHandler handleKeydownEvent(KeyboardEvent&) final;
  • trunk/Source/WebCore/html/PasswordInputType.h

    r246490 r271672  
    3636
    3737class PasswordInputType final : public BaseTextInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit PasswordInputType(HTMLInputElement& element) : BaseTextInputType(element) { }
     40    explicit PasswordInputType(HTMLInputElement& element) : BaseTextInputType(Type::Password, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/RadioInputType.h

    r246490 r271672  
    3737
    3838class RadioInputType final : public BaseCheckableInputType {
     39    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3940public:
    40     explicit RadioInputType(HTMLInputElement& element) : BaseCheckableInputType(element) { }
     41    explicit RadioInputType(HTMLInputElement& element) : BaseCheckableInputType(Type::Radio, element) { }
    4142
    4243private:
  • trunk/Source/WebCore/html/RangeInputType.cpp

    r264600 r271672  
    8181
    8282RangeInputType::RangeInputType(HTMLInputElement& element)
    83     : InputType(element)
     83    : InputType(Type::Range, element)
    8484{
    8585}
     
    134134}
    135135
    136 bool RangeInputType::isSteppable() const
     136bool RangeInputType::isSteppableSlow() const
    137137{
    138138    return true;
     
    253253}
    254254
    255 void RangeInputType::createShadowSubtree()
     255void RangeInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool)
    256256{
    257257    ASSERT(element());
  • trunk/Source/WebCore/html/RangeInputType.h

    r259687 r271672  
    3939
    4040class RangeInputType final : public InputType {
     41    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4142public:
    4243    explicit RangeInputType(HTMLInputElement&);
     
    5051    bool supportsRequired() const final;
    5152    StepRange createStepRange(AnyStepHandling) const final;
    52     bool isSteppable() const final;
     53    bool isSteppableSlow() const final;
    5354    void handleMouseDownEvent(MouseEvent&) final;
    5455    ShouldCallBaseEventHandler handleKeydownEvent(KeyboardEvent&) final;
    5556    RenderPtr<RenderElement> createInputRenderer(RenderStyle&&) final;
    56     void createShadowSubtree() final;
     57    void createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool) final;
    5758    Decimal parseToNumber(const String&, const Decimal&) const final;
    5859    String serialize(const Decimal&) const final;
  • trunk/Source/WebCore/html/ResetInputType.h

    r246490 r271672  
    3636
    3737class ResetInputType final : public BaseButtonInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit ResetInputType(HTMLInputElement& element) : BaseButtonInputType(element) { }
     40    explicit ResetInputType(HTMLInputElement& element) : BaseButtonInputType(Type::Reset, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/SearchInputType.cpp

    r261013 r271672  
    4646
    4747SearchInputType::SearchInputType(HTMLInputElement& element)
    48     : BaseTextInputType(element)
     48    : BaseTextInputType(Type::Search, element)
    4949    , m_searchEventTimer(*this, &SearchInputType::searchEventTimerFired)
    5050{
     
    108108}
    109109
    110 void SearchInputType::createShadowSubtree()
     110void SearchInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source source, bool isInnerTextElementEditable)
    111111{
    112112    ASSERT(!m_resultsButton);
    113113    ASSERT(!m_cancelButton);
    114114
    115     TextFieldInputType::createShadowSubtree();
     115    TextFieldInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(source, isInnerTextElementEditable);
    116116    RefPtr<HTMLElement> container = containerElement();
    117117    RefPtr<HTMLElement> textWrapper = innerBlockElement();
  • trunk/Source/WebCore/html/SearchInputType.h

    r246490 r271672  
    4040
    4141class SearchInputType final : public BaseTextInputType {
     42    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4243public:
    4344    explicit SearchInputType(HTMLInputElement&);
     
    5253    bool isSearchField() const final;
    5354    bool needsContainer() const final;
    54     void createShadowSubtree() final;
     55    void createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool) final;
    5556    void destroyShadowSubtree() final;
    5657    HTMLElement* resultsButtonElement() const final;
  • trunk/Source/WebCore/html/SubmitInputType.h

    r246490 r271672  
    3636
    3737class SubmitInputType final : public BaseButtonInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit SubmitInputType(HTMLInputElement& element) : BaseButtonInputType(element) { }
     40    explicit SubmitInputType(HTMLInputElement& element) : BaseButtonInputType(Type::Submit, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/TelephoneInputType.h

    r246490 r271672  
    3636
    3737class TelephoneInputType final : public BaseTextInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit TelephoneInputType(HTMLInputElement& element) : BaseTextInputType(element) { }
     40    explicit TelephoneInputType(HTMLInputElement& element) : BaseTextInputType(Type::Telephone, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/TextFieldInputType.cpp

    r271559 r271672  
    7272using namespace HTMLNames;
    7373
    74 TextFieldInputType::TextFieldInputType(HTMLInputElement& element)
    75     : InputType(element)
     74TextFieldInputType::TextFieldInputType(Type type, HTMLInputElement& element)
     75    : InputType(type, element)
    7676{
    7777}
     
    319319}
    320320
    321 void TextFieldInputType::createShadowSubtree()
     321void TextFieldInputType::createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source source, bool isInnerTextElementEditable)
    322322{
    323323    ASSERT(element());
     
    335335    bool createsContainer = shouldHaveSpinButton || shouldHaveCapsLockIndicator || needsContainer();
    336336
    337     m_innerText = TextControlInnerTextElement::create(document);
     337    m_innerText = TextControlInnerTextElement::create(document, isInnerTextElementEditable);
    338338
    339339    if (!createsContainer) {
    340         element()->userAgentShadowRoot()->appendChild(*m_innerText);
     340        if (source == ContainerNode::ChildChange::Source::Parser)
     341            element()->userAgentShadowRoot()->parserAppendChild(*m_innerText);
     342        else
     343            element()->userAgentShadowRoot()->appendChild(*m_innerText);
    341344        updatePlaceholderText();
    342345        return;
     
    348351    if (shouldHaveSpinButton) {
    349352        m_innerSpinButton = SpinButtonElement::create(document, *this);
    350         m_container->appendChild(*m_innerSpinButton);
     353        if (source == ContainerNode::ChildChange::Source::Parser)
     354            m_container->parserAppendChild(*m_innerSpinButton);
     355        else
     356            m_container->appendChild(*m_innerSpinButton);
    351357    }
    352358
     
    359365        m_capsLockIndicator->setInlineStyleProperty(CSSPropertyDisplay, shouldDrawCapsLockIndicator ? CSSValueBlock : CSSValueNone, true);
    360366
    361         m_container->appendChild(*m_capsLockIndicator);
     367        if (source == ContainerNode::ChildChange::Source::Parser)
     368            m_container->parserAppendChild(*m_capsLockIndicator);
     369        else
     370            m_container->appendChild(*m_capsLockIndicator);
    362371    }
    363372    updateAutoFillButton();
  • trunk/Source/WebCore/html/TextFieldInputType.h

    r259402 r271672  
    5252{
    5353protected:
    54     explicit TextFieldInputType(HTMLInputElement&);
     54    explicit TextFieldInputType(Type, HTMLInputElement&);
    5555    virtual ~TextFieldInputType();
    5656    ShouldCallBaseEventHandler handleKeydownEvent(KeyboardEvent&) override;
     
    7171
    7272    virtual bool needsContainer() const;
    73     void createShadowSubtree() override;
     73    void createShadowSubtreeAndUpdateInnerTextElementEditability(ContainerNode::ChildChange::Source, bool) override;
    7474    void destroyShadowSubtree() override;
    7575    void attributeChanged(const QualifiedName&) override;
     
    8282    void updateInnerTextValue() final;
    8383    String sanitizeValue(const String&) const override;
     84    bool valueMissing(const String&) const final;
    8485
    8586    virtual String convertFromVisibleValue(const String&) const;
     
    9192    bool isTextField() const final;
    9293    bool isEmptyValue() const final;
    93     bool valueMissing(const String&) const final;
    9494    void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent&) final;
    9595    void forwardEvent(Event&) final;
  • trunk/Source/WebCore/html/TextInputType.h

    r246490 r271672  
    3636
    3737class TextInputType final : public BaseTextInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit TextInputType(HTMLInputElement& element) : BaseTextInputType(element) { }
     40    explicit TextInputType(HTMLInputElement& element) : BaseTextInputType(Type::Text, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/TimeInputType.cpp

    r267003 r271672  
    5454
    5555TimeInputType::TimeInputType(HTMLInputElement& element)
    56     : BaseDateAndTimeInputType(element)
     56    : BaseDateAndTimeInputType(Type::Time, element)
    5757{
    5858}
  • trunk/Source/WebCore/html/TimeInputType.h

    r267003 r271672  
    3838
    3939class TimeInputType final : public BaseDateAndTimeInputType {
     40    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4041public:
    4142    explicit TimeInputType(HTMLInputElement&);
  • trunk/Source/WebCore/html/URLInputType.h

    r246490 r271672  
    3636
    3737class URLInputType final : public BaseTextInputType {
     38    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    3839public:
    39     explicit URLInputType(HTMLInputElement& element) : BaseTextInputType(element) { }
     40    explicit URLInputType(HTMLInputElement& element) : BaseTextInputType(Type::URL, element) { }
    4041
    4142private:
  • trunk/Source/WebCore/html/WeekInputType.h

    r267003 r271672  
    3838
    3939class WeekInputType final : public BaseDateAndTimeInputType {
     40    template<typename DowncastedType> friend bool isInvalidInputType(const InputType&, const String&);
    4041public:
    4142    explicit WeekInputType(HTMLInputElement& element)
    42         : BaseDateAndTimeInputType(element)
     43        : BaseDateAndTimeInputType(Type::Week, element)
    4344    {
    4445    }
  • trunk/Source/WebCore/html/shadow/TextControlInnerElements.cpp

    r267074 r271672  
    139139}
    140140
    141 Ref<TextControlInnerTextElement> TextControlInnerTextElement::create(Document& document)
    142 {
    143     return adoptRef(*new TextControlInnerTextElement(document));
     141Ref<TextControlInnerTextElement> TextControlInnerTextElement::create(Document& document, bool isEditable)
     142{
     143    auto result = adoptRef(*new TextControlInnerTextElement(document));
     144    constexpr bool initialization = true;
     145    result->updateInnerTextElementEditabilityImpl(isEditable, initialization);
     146    return result;
     147}
     148
     149void TextControlInnerTextElement::updateInnerTextElementEditabilityImpl(bool isEditable, bool initialization)
     150{
     151    static MainThreadNeverDestroyed<const AtomString> plainTextOnlyName("plaintext-only", AtomString::ConstructFromLiteral);
     152    static MainThreadNeverDestroyed<const AtomString> falseName("false", AtomString::ConstructFromLiteral);
     153    const auto& value = isEditable ? plainTextOnlyName.get() : falseName.get();
     154    if (initialization) {
     155        Vector<Attribute> attributes { Attribute(contenteditableAttr, value) };
     156        parserSetAttributes(attributes);
     157    } else
     158        setAttributeWithoutSynchronization(contenteditableAttr, value);
    144159}
    145160
  • trunk/Source/WebCore/html/shadow/TextControlInnerElements.h

    r260415 r271672  
    5959    WTF_MAKE_ISO_ALLOCATED(TextControlInnerTextElement);
    6060public:
    61     static Ref<TextControlInnerTextElement> create(Document&);
     61    static Ref<TextControlInnerTextElement> create(Document&, bool isEditable);
    6262
    6363    void defaultEventHandler(Event&) override;
     
    6565    RenderTextControlInnerBlock* renderer() const;
    6666
     67    inline void updateInnerTextElementEditability(bool isEditable)
     68    {
     69        constexpr bool initialization = false;
     70        updateInnerTextElementEditabilityImpl(isEditable, initialization);
     71    }
     72
    6773private:
     74    void updateInnerTextElementEditabilityImpl(bool isEditable, bool initialization);
     75
    6876    TextControlInnerTextElement(Document&);
    6977    RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override;
  • trunk/Source/WebCore/style/StyleScope.h

    r253949 r271672  
    136136    void didRemovePendingStylesheet();
    137137
    138     enum class UpdateType { ActiveSet, ContentsOrInterpretation };
     138    enum class UpdateType : uint8_t { ActiveSet, ContentsOrInterpretation };
    139139    void updateActiveStyleSheets(UpdateType);
    140140    void scheduleUpdate(UpdateType);
     
    184184    HashSet<const Element*> m_elementsInBodyWithPendingSheets;
    185185
     186
     187    ListHashSet<Node*> m_styleSheetCandidateNodes;
     188
     189    String m_preferredStylesheetSetName;
     190
    186191    Optional<UpdateType> m_pendingUpdate;
     192
    187193    bool m_hasDescendantWithPendingUpdate { false };
    188 
    189     ListHashSet<Node*> m_styleSheetCandidateNodes;
    190 
    191     String m_preferredStylesheetSetName;
    192 
    193194    bool m_usesStyleBasedEditability { false };
    194195    bool m_isUpdatingStyleResolver { false };
Note: See TracChangeset for help on using the changeset viewer.