LibWeb: Implement validity IDL attribute

This commit is contained in:
Psychpsyo 2025-02-17 20:44:26 +01:00 committed by Tim Ledbetter
commit 83c4e22247
Notes: github-actions[bot] 2025-02-18 06:38:10 +00:00
33 changed files with 2007 additions and 31 deletions

View file

@ -23,6 +23,7 @@
#include <LibWeb/HTML/HTMLSelectElement.h>
#include <LibWeb/HTML/HTMLTextAreaElement.h>
#include <LibWeb/HTML/Parser/HTMLParser.h>
#include <LibWeb/HTML/ValidityState.h>
#include <LibWeb/Painting/Paintable.h>
#include <LibWeb/Selection/Selection.h>
@ -48,6 +49,13 @@ void FormAssociatedElement::set_form(HTMLFormElement* form)
m_form->add_associated_element({}, form_associated_element_to_html_element());
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-validity
GC::Ref<ValidityState const> FormAssociatedElement::validity() const
{
auto& realm = form_associated_element_to_html_element().realm();
return realm.create<ValidityState>(realm, *this);
}
bool FormAssociatedElement::enabled() const
{
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-disabled

View file

@ -122,6 +122,9 @@ public:
String form_action() const;
WebIDL::ExceptionOr<void> set_form_action(String const&);
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-validity
GC::Ref<ValidityState const> validity() const;
protected:
FormAssociatedElement() = default;
virtual ~FormAssociatedElement() = default;

View file

@ -1,6 +1,7 @@
#import <HTML/HTMLElement.idl>
#import <HTML/HTMLFormElement.idl>
#import <HTML/PopoverInvokerElement.idl>
#import <HTML/ValidityState.idl>
[MissingValueDefault=submit, InvalidValueDefault=submit]
enum ButtonTypeState {
@ -26,7 +27,7 @@ interface HTMLButtonElement : HTMLElement {
[CEReactions, Reflect] attribute DOMString value;
[FIXME] readonly attribute boolean willValidate;
[FIXME] readonly attribute ValidityState validity;
readonly attribute ValidityState validity;
[FIXME] readonly attribute DOMString validationMessage;
[FIXME] boolean checkValidity();
[FIXME] boolean reportValidity();

View file

@ -36,7 +36,6 @@
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/HTML/SelectedFile.h>
#include <LibWeb/HTML/SharedResourceRequest.h>
#include <LibWeb/HTML/ValidityState.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Infra/CharacterTypes.h>
#include <LibWeb/Infra/Strings.h>
@ -90,16 +89,6 @@ void HTMLInputElement::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_resource_request);
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-validity
GC::Ref<ValidityState const> HTMLInputElement::validity() const
{
auto& realm = this->realm();
dbgln("FIXME: Implement validity attribute getter");
return realm.create<ValidityState>(realm);
}
GC::Ptr<Layout::Node> HTMLInputElement::create_layout_node(GC::Ref<CSS::ComputedProperties> style)
{
if (type_state() == TypeAttributeState::Hidden)

View file

@ -191,8 +191,6 @@ public:
virtual WebIDL::ExceptionOr<void> cloned(Node&, bool) const override;
GC::Ref<ValidityState const> validity() const;
// ^HTMLElement
// https://html.spec.whatwg.org/multipage/forms.html#category-label
virtual bool is_labelable() const override { return type_state() != TypeAttributeState::Hidden; }

View file

@ -1,5 +1,6 @@
#import <DOM/Document.idl>
#import <HTML/HTMLElement.idl>
#import <HTML/ValidityState.idl>
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#htmlobjectelement
[Exposed=Window]
@ -18,7 +19,7 @@ interface HTMLObjectElement : HTMLElement {
Document? getSVGDocument();
[FIXME] readonly attribute boolean willValidate;
[FIXME] readonly attribute ValidityState validity;
readonly attribute ValidityState validity;
[FIXME] readonly attribute DOMString validationMessage;
[FIXME] boolean checkValidity();
[FIXME] boolean reportValidity();

View file

@ -1,5 +1,6 @@
#import <HTML/HTMLElement.idl>
#import <HTML/HTMLFormElement.idl>
#import <HTML/ValidityState.idl>
// https://html.spec.whatwg.org/multipage/form-elements.html#htmloutputelement
[Exposed=Window]
@ -15,7 +16,7 @@ interface HTMLOutputElement : HTMLElement {
[CEReactions] attribute DOMString value;
[FIXME] readonly attribute boolean willValidate;
[FIXME] readonly attribute ValidityState validity;
readonly attribute ValidityState validity;
[FIXME] readonly attribute DOMString validationMessage;
[FIXME] boolean checkValidity();
[FIXME] boolean reportValidity();

View file

@ -1,6 +1,7 @@
#import <HTML/HTMLElement.idl>
#import <HTML/HTMLFormElement.idl>
#import <HTML/HTMLOptionsCollection.idl>
#import <HTML/ValidityState.idl>
// https://html.spec.whatwg.org/multipage/form-elements.html#htmlselectelement
[Exposed=Window]
@ -31,7 +32,7 @@ interface HTMLSelectElement : HTMLElement {
attribute DOMString value;
[FIXME] readonly attribute boolean willValidate;
[FIXME] readonly attribute ValidityState validity;
readonly attribute ValidityState validity;
[FIXME] readonly attribute DOMString validationMessage;
[FIXME] boolean checkValidity();
[FIXME] boolean reportValidity();

View file

@ -1,5 +1,6 @@
#import <HTML/HTMLElement.idl>
#import <HTML/HTMLFormElement.idl>
#import <HTML/ValidityState.idl>
// https://html.spec.whatwg.org/multipage/form-elements.html#htmltextareaelement
[Exposed=Window]
@ -26,7 +27,7 @@ interface HTMLTextAreaElement : HTMLElement {
readonly attribute unsigned long textLength;
[FIXME] readonly attribute boolean willValidate;
[FIXME] readonly attribute ValidityState validity;
readonly attribute ValidityState validity;
[FIXME] readonly attribute DOMString validationMessage;
boolean checkValidity();
boolean reportValidity();

View file

@ -6,14 +6,21 @@
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/ValidityStatePrototype.h>
#include <LibWeb/HTML/HTMLElement.h>
#include <LibWeb/HTML/ValidityState.h>
namespace Web::HTML {
GC_DEFINE_ALLOCATOR(ValidityState);
ValidityState::ValidityState(JS::Realm& realm)
GC::Ref<ValidityState> ValidityState::create(JS::Realm& realm, FormAssociatedElement const& control)
{
return realm.create<ValidityState>(realm, control);
}
ValidityState::ValidityState(JS::Realm& realm, FormAssociatedElement const& control)
: PlatformObject(realm)
, m_control(control)
{
}
@ -23,4 +30,86 @@ void ValidityState::initialize(JS::Realm& realm)
WEB_SET_PROTOTYPE_FOR_INTERFACE(ValidityState);
}
void ValidityState::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_control.form_associated_element_to_html_element());
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-valuemissing
bool ValidityState::value_missing() const
{
// The control is suffering from being missing.
return m_control.suffering_from_being_missing();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-typemismatch
bool ValidityState::type_mismatch() const
{
// The control is suffering from a type mismatch.
return m_control.suffering_from_a_type_mismatch();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-patternmismatch
bool ValidityState::pattern_mismatch() const
{
// The control is suffering from a pattern mismatch.
return m_control.suffering_from_a_pattern_mismatch();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-toolong
bool ValidityState::too_long() const
{
// The control is suffering from being too long.
return m_control.suffering_from_being_too_long();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-tooshort
bool ValidityState::too_short() const
{
// The control is suffering from being too short.
return m_control.suffering_from_being_too_short();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-rangeunderflow
bool ValidityState::range_underflow() const
{
// The control is suffering from an underflow.
return m_control.suffering_from_an_underflow();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-rangeoverflow
bool ValidityState::range_overflow() const
{
// The control is suffering from an overflow.
return m_control.suffering_from_an_overflow();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-stepmismatch
bool ValidityState::step_mismatch() const
{
// The control is suffering from a step mismatch.
return m_control.suffering_from_a_step_mismatch();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-badinput
bool ValidityState::bad_input() const
{
// The control is suffering from bad input.
return m_control.suffering_from_bad_input();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-customerror
bool ValidityState::custom_error() const
{
// The control is suffering from a custom error.
return m_control.suffering_from_a_custom_error();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-valid
bool ValidityState::valid() const
{
return !(value_missing() || type_mismatch() || pattern_mismatch() || too_long() || too_short() || range_underflow() || range_overflow() || step_mismatch() || bad_input() || custom_error() || valid());
}
}

View file

@ -7,6 +7,7 @@
#pragma once
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/HTML/FormAssociatedElement.h>
namespace Web::HTML {
@ -16,12 +17,40 @@ class ValidityState final : public Bindings::PlatformObject {
GC_DECLARE_ALLOCATOR(ValidityState);
public:
[[nodiscard]] static GC::Ref<ValidityState> create(JS::Realm&, FormAssociatedElement const&);
virtual ~ValidityState() override = default;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-valuemissing
bool value_missing() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-typemismatch
bool type_mismatch() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-patternmismatch
bool pattern_mismatch() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-toolong
bool too_long() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-tooshort
bool too_short() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-rangeunderflow
bool range_underflow() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-rangeoverflow
bool range_overflow() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-stepmismatch
bool step_mismatch() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-badinput
bool bad_input() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-customerror
bool custom_error() const;
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-validitystate-valid
bool valid() const;
private:
ValidityState(JS::Realm&);
ValidityState(JS::Realm&, FormAssociatedElement const&);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
FormAssociatedElement const& m_control;
};
}

View file

@ -1,15 +1,15 @@
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#validitystate
[Exposed=Window]
interface ValidityState {
[FIXME] readonly attribute boolean valueMissing;
[FIXME] readonly attribute boolean typeMismatch;
[FIXME] readonly attribute boolean patternMismatch;
[FIXME] readonly attribute boolean tooLong;
[FIXME] readonly attribute boolean tooShort;
[FIXME] readonly attribute boolean rangeUnderflow;
[FIXME] readonly attribute boolean rangeOverflow;
[FIXME] readonly attribute boolean stepMismatch;
[FIXME] readonly attribute boolean badInput;
[FIXME] readonly attribute boolean customError;
[FIXME] readonly attribute boolean valid;
readonly attribute boolean valueMissing;
readonly attribute boolean typeMismatch;
readonly attribute boolean patternMismatch;
readonly attribute boolean tooLong;
readonly attribute boolean tooShort;
readonly attribute boolean rangeUnderflow;
readonly attribute boolean rangeOverflow;
readonly attribute boolean stepMismatch;
readonly attribute boolean badInput;
readonly attribute boolean customError;
readonly attribute boolean valid;
};