AX: AXIsolatedTree::updateChildren sometimes fails to update isolated subtrees when...
[WebKit-https.git] / Source / WebCore / html / InputType.cpp
index 85846c193f25c873f46338236db0bf6af2f5c8b7..40f4e7435ff419fbbed6317c2af6138ab3e3ffbf 100644 (file)
@@ -59,6 +59,7 @@
 #include "NumberInputType.h"
 #include "Page.h"
 #include "PasswordInputType.h"
+#include "PseudoClassChangeInvalidation.h"
 #include "RadioInputType.h"
 #include "RangeInputType.h"
 #include "RenderElement.h"
@@ -130,6 +131,7 @@ static InputTypeFactoryMap createInputTypeFactoryMap()
         { nullptr, &InputTypeNames::search, &createInputType<SearchInputType> },
         { nullptr, &InputTypeNames::submit, &createInputType<SubmitInputType> },
         { nullptr, &InputTypeNames::telephone, &createInputType<TelephoneInputType> },
+        { nullptr, &InputTypeNames::text, &createInputType<TextInputType> },
 #if ENABLE(INPUT_TYPE_TIME)
         { &Settings::inputTypeTimeEnabled, &InputTypeNames::time, &createInputType<TimeInputType> },
 #endif
@@ -137,7 +139,6 @@ static InputTypeFactoryMap createInputTypeFactoryMap()
 #if ENABLE(INPUT_TYPE_WEEK)
         { &Settings::inputTypeWeekEnabled, &InputTypeNames::week, &createInputType<WeekInputType> },
 #endif
-        // No need to register "text" because it is the default type.
     };
 
     InputTypeFactoryMap map;
@@ -146,12 +147,20 @@ static InputTypeFactoryMap createInputTypeFactoryMap()
     return map;
 }
 
+static inline std::pair<InputTypeConditionalFunction, InputTypeFactoryFunction> findFactory(const AtomString& typeName)
+{
+    static NeverDestroyed factoryMap = createInputTypeFactoryMap();
+    auto factory = factoryMap.get().get(typeName);
+    if (UNLIKELY(!factory.second))
+        factory = factoryMap.get().get(typeName.convertToASCIILowercase());
+    return factory;
+}
+
 Ref<InputType> InputType::create(HTMLInputElement& element, const AtomString& typeName)
 {
     if (!typeName.isEmpty()) {
-        static NeverDestroyed factoryMap = createInputTypeFactoryMap();
-        auto&& [conditional, factory] = factoryMap.get().get(typeName.convertToASCIILowercase());
-        if (factory && (!conditional || std::invoke(conditional, element.document().settings())))
+        auto [conditional, factory] = findFactory(typeName);
+        if (LIKELY(factory && (!conditional || std::invoke(conditional, element.document().settings()))))
             return factory(element);
     }
     return adoptRef(*new TextInputType(element));
@@ -794,10 +803,25 @@ bool InputType::storesValueSeparateFromAttribute()
 void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior, TextControlSetValueSelection)
 {
     ASSERT(element());
-    element()->setValueInternal(sanitizedValue, eventBehavior);
-    if (!valueChanged)
+    if (!valueChanged) {
+        element()->setValueInternal(sanitizedValue, eventBehavior);
         return;
-    element()->invalidateStyleForSubtree();
+    }
+
+    bool wasInRange = isInRange(element()->value());
+    bool inRange = isInRange(sanitizedValue);
+
+    bool dummy;
+    auto oldDirection = element()->directionalityIfhasDirAutoAttribute(dummy);
+
+    std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation;
+    if (wasInRange != inRange)
+        emplace(styleInvalidation, *element(), { { CSSSelector::PseudoClassInRange, inRange }, { CSSSelector::PseudoClassOutOfRange, !inRange } });
+
+    element()->setValueInternal(sanitizedValue, eventBehavior);
+
+    if (oldDirection != element()->directionalityIfhasDirAutoAttribute(dummy))
+        element()->invalidateStyleInternal();
 
     switch (eventBehavior) {
     case DispatchChangeEvent: