LibWeb: Leave input elements' text node contents unchanged while typing

Replacing the text node's contents with the normalized value after each
keystroke made it impossible to type some inputs. For example, `1e`
would cause the text node to be emptied, making it impossible to type
`1e2`. Also, `time`, `date`, and other time-related input types had no
intermediate valid values, so it was genuinely impossible to type in
them.

Additionally, typed numbers weren't being parsed as floats before
normalization, so even just typing `1.` would clear the text node, so
it was impossible to type a fractional number.
This commit is contained in:
Zaggy1024 2026-06-03 22:19:12 -05:00 committed by Jelle Raaijmakers
parent e6664213ac
commit 0ce19a19ea
4 changed files with 39 additions and 19 deletions

View file

@ -565,18 +565,8 @@ WebIDL::ExceptionOr<void> HTMLInputElement::run_input_activation_behavior(DOM::E
void HTMLInputElement::did_edit_text_node(FlyString const& input_type, Optional<Utf16String> const& data)
{
// An input element's dirty value flag must be set to true whenever the user interacts with the control in a way that changes the value.
auto old_value = move(m_value);
m_value = value_sanitization_algorithm(m_text_node->data());
m_dirty_value = true;
m_has_uncommitted_changes = true;
if (m_value != old_value)
relevant_value_was_changed();
update_placeholder_visibility();
user_interaction_did_change_input_value(input_type, data);
}
@ -713,6 +703,36 @@ Optional<String> HTMLInputElement::optional_value() const
}
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
Utf16String HTMLInputElement::relevant_value() const
{
// AD-HOC: If a text node is present, use that as the raw text buffer, so that it can differ from the sanitized
// or canonicalized value.
if (m_text_node)
return m_text_node->data();
return value();
}
WebIDL::ExceptionOr<void> HTMLInputElement::set_relevant_value(Utf16String const& value)
{
if (m_text_node)
m_text_node->set_data(value);
// https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)
// If the user agent provides a user interface for selecting a number, then the value must be set to the best
// representation of the number representing the user's selection as a floating-point number.
if (type_state() == TypeAttributeState::Number) {
m_value = {};
if (auto parsed = parse_floating_point_number(value); parsed.has_value() && isfinite(*parsed))
m_value = convert_number_to_string(*parsed);
} else {
m_value = value_sanitization_algorithm(value);
}
update_placeholder_visibility();
return {};
}
WebIDL::ExceptionOr<void> HTMLInputElement::set_value(Utf16String const& value)
{
auto& realm = this->realm();
@ -933,10 +953,7 @@ void HTMLInputElement::update_button_input_shadow_tree()
void HTMLInputElement::update_text_input_shadow_tree()
{
if (m_text_node) {
m_text_node->set_data(m_value);
update_placeholder_visibility();
}
update_placeholder_visibility();
if (m_type == TypeAttributeState::Number) {
// The `textfield` appearance is used to hide the stepper buttons.
@ -1557,6 +1574,9 @@ void HTMLInputElement::form_associated_element_attribute_changed(FlyString const
if (m_value != old_value)
relevant_value_was_changed();
if (m_text_node)
m_text_node->set_data(m_value);
update_shadow_tree();
}
} else if (name == HTML::AttributeNames::placeholder) {

View file

@ -86,8 +86,8 @@ public:
WebIDL::ExceptionOr<void> set_value(Utf16String const&);
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
virtual Utf16String relevant_value() const override { return value(); }
WebIDL::ExceptionOr<void> set_relevant_value(Utf16String const& value) override { return set_value(value); }
virtual Utf16String relevant_value() const override;
WebIDL::ExceptionOr<void> set_relevant_value(Utf16String const& value) override;
virtual Optional<Utf16String> selected_text_for_stringifier() const override;
virtual void set_dirty_value_flag(bool flag) override { m_dirty_value = flag; }

View file

@ -1,3 +1,3 @@
After '1': value="1"
After '.': value=""
After '5': value="5"
After '.': value="1"
After '5': value="1.5"

View file

@ -2,4 +2,4 @@ after '1': value=""
after '2': value=""
after ':': value=""
after '3': value=""
after '0': value=""
after '0': value="12:30"