#include "NumberInputType.h"
#include "Page.h"
#include "PasswordInputType.h"
+#include "PseudoClassChangeInvalidation.h"
#include "RadioInputType.h"
#include "RangeInputType.h"
#include "RenderElement.h"
{ 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
#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;
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));
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: