Przeglądaj źródła

LibWeb: Add AriaData object to parse ARIAMixin data

This provides an easily serializeable interface for us to use in IPC.
Jonah 2 lat temu
rodzic
commit
57a6d577ad

+ 18 - 0
Userland/Libraries/LibWeb/ARIA/ARIAMixin.cpp

@@ -61,4 +61,22 @@ bool ARIAMixin::has_global_aria_attribute() const
         || !aria_role_description().is_null();
         || !aria_role_description().is_null();
 }
 }
 
 
+Optional<DeprecatedString> ARIAMixin::parse_id_reference(DeprecatedString const& id_reference) const
+{
+    if (id_reference_exists(id_reference))
+        return id_reference;
+    return {};
+}
+
+Vector<DeprecatedString> ARIAMixin::parse_id_reference_list(DeprecatedString const& id_list) const
+{
+    Vector<DeprecatedString> result;
+    auto id_references = id_list.split_view(Infra::is_ascii_whitespace);
+    for (auto const id_reference : id_references) {
+        if (id_reference_exists(id_reference))
+            result.append(id_reference);
+    }
+    return result;
+}
+
 }
 }

+ 46 - 4
Userland/Libraries/LibWeb/ARIA/ARIAMixin.h

@@ -6,7 +6,9 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <AK/Forward.h>
+#include <AK/DeprecatedString.h>
+#include <AK/Vector.h>
+#include <LibWeb/ARIA/AriaData.h>
 #include <LibWeb/ARIA/Roles.h>
 #include <LibWeb/ARIA/Roles.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 #include <LibWeb/WebIDL/ExceptionOr.h>
 
 
@@ -22,16 +24,22 @@ public:
 
 
     virtual DeprecatedString aria_active_descendant() const = 0;
     virtual DeprecatedString aria_active_descendant() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_active_descendant(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_active_descendant(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_atomic() const = 0;
     virtual DeprecatedString aria_atomic() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_atomic(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_atomic(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_auto_complete() const = 0;
     virtual DeprecatedString aria_auto_complete() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_auto_complete(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_auto_complete(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_busy() const = 0;
     virtual DeprecatedString aria_busy() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_busy(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_busy(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_checked() const = 0;
     virtual DeprecatedString aria_checked() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_checked(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_checked(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_col_count() const = 0;
     virtual DeprecatedString aria_col_count() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_col_count(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_col_count(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_col_index() const = 0;
     virtual DeprecatedString aria_col_index() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_col_index(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_col_index(DeprecatedString const&) = 0;
 
 
@@ -46,32 +54,40 @@ public:
 
 
     virtual DeprecatedString aria_described_by() const = 0;
     virtual DeprecatedString aria_described_by() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_described_by(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_described_by(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_details() const = 0;
     virtual DeprecatedString aria_details() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_details(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_details(DeprecatedString const&) = 0;
+
+    virtual DeprecatedString aria_disabled() const = 0;
+    virtual WebIDL::ExceptionOr<void> set_aria_disabled(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_drop_effect() const = 0;
     virtual DeprecatedString aria_drop_effect() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_drop_effect(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_drop_effect(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_error_message() const = 0;
     virtual DeprecatedString aria_error_message() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_error_message(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_error_message(DeprecatedString const&) = 0;
 
 
-    virtual DeprecatedString aria_disabled() const = 0;
-    virtual WebIDL::ExceptionOr<void> set_aria_disabled(DeprecatedString const&) = 0;
-
     virtual DeprecatedString aria_expanded() const = 0;
     virtual DeprecatedString aria_expanded() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_expanded(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_expanded(DeprecatedString const&) = 0;
 
 
     virtual DeprecatedString aria_flow_to() const = 0;
     virtual DeprecatedString aria_flow_to() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_flow_to(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_flow_to(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_grabbed() const = 0;
     virtual DeprecatedString aria_grabbed() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_grabbed(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_grabbed(DeprecatedString const&) = 0;
 
 
     virtual DeprecatedString aria_has_popup() const = 0;
     virtual DeprecatedString aria_has_popup() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_has_popup(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_has_popup(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_hidden() const = 0;
     virtual DeprecatedString aria_hidden() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_hidden(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_hidden(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_invalid() const = 0;
     virtual DeprecatedString aria_invalid() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_invalid(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_invalid(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_key_shortcuts() const = 0;
     virtual DeprecatedString aria_key_shortcuts() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_key_shortcuts(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_key_shortcuts(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_label() const = 0;
     virtual DeprecatedString aria_label() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_label(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_label(DeprecatedString const&) = 0;
 
 
@@ -80,14 +96,19 @@ public:
 
 
     virtual DeprecatedString aria_level() const = 0;
     virtual DeprecatedString aria_level() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_level(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_level(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_live() const = 0;
     virtual DeprecatedString aria_live() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_live(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_live(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_modal() const = 0;
     virtual DeprecatedString aria_modal() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_modal(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_modal(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_multi_line() const = 0;
     virtual DeprecatedString aria_multi_line() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_multi_line(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_multi_line(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_multi_selectable() const = 0;
     virtual DeprecatedString aria_multi_selectable() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_multi_selectable(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_multi_selectable(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_orientation() const = 0;
     virtual DeprecatedString aria_orientation() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_orientation(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_orientation(DeprecatedString const&) = 0;
 
 
@@ -96,10 +117,13 @@ public:
 
 
     virtual DeprecatedString aria_placeholder() const = 0;
     virtual DeprecatedString aria_placeholder() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_placeholder(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_placeholder(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_pos_in_set() const = 0;
     virtual DeprecatedString aria_pos_in_set() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_pos_in_set(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_pos_in_set(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_pressed() const = 0;
     virtual DeprecatedString aria_pressed() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_pressed(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_pressed(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_read_only() const = 0;
     virtual DeprecatedString aria_read_only() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_read_only(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_read_only(DeprecatedString const&) = 0;
 
 
@@ -108,27 +132,37 @@ public:
 
 
     virtual DeprecatedString aria_required() const = 0;
     virtual DeprecatedString aria_required() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_required(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_required(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_role_description() const = 0;
     virtual DeprecatedString aria_role_description() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_role_description(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_role_description(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_row_count() const = 0;
     virtual DeprecatedString aria_row_count() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_row_count(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_row_count(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_row_index() const = 0;
     virtual DeprecatedString aria_row_index() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_row_index(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_row_index(DeprecatedString const&) = 0;
 
 
     virtual DeprecatedString aria_row_span() const = 0;
     virtual DeprecatedString aria_row_span() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_row_span(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_row_span(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_selected() const = 0;
     virtual DeprecatedString aria_selected() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_selected(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_selected(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_set_size() const = 0;
     virtual DeprecatedString aria_set_size() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_set_size(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_set_size(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_sort() const = 0;
     virtual DeprecatedString aria_sort() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_sort(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_sort(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_value_max() const = 0;
     virtual DeprecatedString aria_value_max() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_max(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_max(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_value_min() const = 0;
     virtual DeprecatedString aria_value_min() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_min(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_min(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_value_now() const = 0;
     virtual DeprecatedString aria_value_now() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_now(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_now(DeprecatedString const&) = 0;
+
     virtual DeprecatedString aria_value_text() const = 0;
     virtual DeprecatedString aria_value_text() const = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_text(DeprecatedString const&) = 0;
     virtual WebIDL::ExceptionOr<void> set_aria_value_text(DeprecatedString const&) = 0;
 
 
@@ -145,8 +179,16 @@ public:
 
 
     bool has_global_aria_attribute() const;
     bool has_global_aria_attribute() const;
 
 
+    // https://www.w3.org/TR/wai-aria-1.2/#valuetype_idref
+    Optional<DeprecatedString> parse_id_reference(DeprecatedString const&) const;
+
+    // https://www.w3.org/TR/wai-aria-1.2/#valuetype_idref_list
+    Vector<DeprecatedString> parse_id_reference_list(DeprecatedString const&) const;
+
 protected:
 protected:
     ARIAMixin() = default;
     ARIAMixin() = default;
+
+    virtual bool id_reference_exists(DeprecatedString const&) const = 0;
 };
 };
 
 
 }
 }

+ 529 - 0
Userland/Libraries/LibWeb/ARIA/AriaData.cpp

@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2023, Jonah Shafran <jonahshafran@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/ARIA/AriaData.h>
+#include <LibWeb/Infra/CharacterTypes.h>
+
+namespace Web::ARIA {
+
+AriaData::AriaData(Web::ARIA::ARIAMixin const& source)
+{
+    m_aria_active_descendant = source.aria_active_descendant();
+    m_aria_atomic = AriaData::parse_optional_true_false(source.aria_atomic());
+    m_aria_auto_complete = AriaData::parse_aria_autocomplete(source.aria_auto_complete());
+    m_aria_busy = AriaData::parse_true_false(source.aria_busy());
+    m_aria_checked = AriaData::parse_tristate(source.aria_checked());
+    m_aria_col_count = AriaData::parse_integer(source.aria_col_count());
+    m_aria_col_index = AriaData::parse_integer(source.aria_col_index());
+    m_aria_col_span = AriaData::parse_integer(source.aria_col_span());
+    m_aria_controls = source.parse_id_reference_list(source.aria_controls());
+    m_aria_current = AriaData::parse_aria_current(source.aria_current());
+    m_aria_described_by = source.parse_id_reference_list(source.aria_described_by());
+    m_aria_details = source.parse_id_reference(source.aria_details());
+    m_aria_disabled = AriaData::parse_true_false(source.aria_disabled());
+    m_aria_drop_effect = AriaData::parse_aria_drop_effect(source.aria_drop_effect());
+    m_aria_error_message = source.parse_id_reference(source.aria_error_message());
+    m_aria_expanded = AriaData::parse_true_false_undefined(source.aria_expanded());
+    m_aria_flow_to = source.parse_id_reference_list(source.aria_flow_to());
+    m_aria_grabbed = AriaData::parse_true_false_undefined(source.aria_grabbed());
+    m_aria_has_popup = AriaData::parse_aria_has_popup(source.aria_has_popup());
+    m_aria_hidden = AriaData::parse_true_false_undefined(source.aria_hidden());
+    m_aria_invalid = AriaData::parse_aria_invalid(source.aria_invalid());
+    m_aria_key_shortcuts = source.aria_key_shortcuts();
+    m_aria_label = source.aria_label();
+    m_aria_labelled_by = source.parse_id_reference_list(source.aria_labelled_by());
+    m_aria_level = AriaData::parse_integer(source.aria_level());
+    m_aria_live = AriaData::parse_aria_live(source.aria_live());
+    m_aria_modal = AriaData::parse_true_false(source.aria_modal());
+    m_aria_multi_line = AriaData::parse_true_false(source.aria_multi_line());
+    m_aria_multi_selectable = AriaData::parse_true_false(source.aria_multi_selectable());
+    m_aria_orientation = AriaData::parse_aria_orientation(source.aria_orientation());
+    m_aria_owns = source.parse_id_reference_list(source.aria_owns());
+    m_aria_placeholder = source.aria_placeholder();
+    m_aria_pos_in_set = AriaData::parse_integer(source.aria_pos_in_set());
+    m_aria_pressed = AriaData::parse_tristate(source.aria_pressed());
+    m_aria_read_only = AriaData::parse_true_false(source.aria_read_only());
+    m_aria_relevant = AriaData::parse_aria_relevant(source.aria_relevant());
+    m_aria_required = AriaData::parse_true_false(source.aria_required());
+    m_aria_role_description = source.aria_role_description();
+    m_aria_row_count = AriaData::parse_integer(source.aria_row_count());
+    m_aria_row_index = AriaData::parse_integer(source.aria_row_index());
+    m_aria_row_span = AriaData::parse_integer(source.aria_row_span());
+    m_aria_selected = AriaData::parse_true_false_undefined(source.aria_selected());
+    m_aria_set_size = AriaData::parse_integer(source.aria_set_size());
+    m_aria_sort = AriaData::parse_aria_sort(source.aria_sort());
+    m_aria_value_max = AriaData::parse_number(source.aria_value_max());
+    m_aria_value_min = AriaData::parse_number(source.aria_value_min());
+    m_aria_value_now = AriaData::parse_number(source.aria_value_now());
+    m_aria_value_text = source.aria_value_text();
+}
+
+bool AriaData::parse_true_false(StringView value)
+{
+    if (value == "true"sv)
+        return true;
+    if (value == "false"sv)
+        return false;
+    return false;
+}
+
+Tristate AriaData::parse_tristate(StringView value)
+{
+    if (value == "true"sv)
+        return Tristate::True;
+    if (value == "false"sv)
+        return Tristate::False;
+    if (value == "mixed"sv)
+        return Tristate::Mixed;
+    if (value == "undefined"sv)
+        return Tristate::Undefined;
+    return Tristate::Undefined;
+}
+
+Optional<bool> AriaData::parse_true_false_undefined(StringView value)
+{
+    if (value == "true"sv)
+        return true;
+    if (value == "false"sv)
+        return false;
+    if (value == "undefined"sv)
+        return {};
+    return {};
+}
+
+Optional<i32> AriaData::parse_integer(StringView value)
+{
+    return value.to_int();
+}
+
+Optional<f64> AriaData::parse_number(StringView value)
+{
+    return value.to_double(TrimWhitespace::Yes);
+}
+
+Optional<DeprecatedString> AriaData::aria_active_descendant_or_default() const
+{
+    return m_aria_active_descendant;
+}
+
+bool AriaData::aria_atomic_or_default(bool default_value) const
+{
+    auto value = m_aria_atomic;
+    if (!value.has_value())
+        return default_value;
+    return value.value();
+}
+
+AriaAutocomplete AriaData::aria_auto_complete_or_default() const
+{
+    return m_aria_auto_complete;
+}
+
+bool AriaData::aria_busy_or_default() const
+{
+    return m_aria_busy;
+}
+
+Tristate AriaData::aria_checked_or_default() const
+{
+    return m_aria_checked;
+}
+
+Optional<i32> AriaData::aria_col_count_or_default() const
+{
+    return m_aria_col_count;
+}
+
+Optional<i32> AriaData::aria_col_index_or_default() const
+{
+    return m_aria_col_index;
+}
+
+Optional<i32> AriaData::aria_col_span_or_default() const
+{
+    return m_aria_col_span;
+}
+
+Vector<DeprecatedString> AriaData::aria_controls_or_default() const
+{
+    return m_aria_controls;
+}
+
+AriaCurrent AriaData::aria_current_or_default() const
+{
+    return m_aria_current;
+}
+
+Vector<DeprecatedString> AriaData::aria_described_by_or_default() const
+{
+    return m_aria_described_by;
+}
+
+Optional<DeprecatedString> AriaData::aria_details_or_default() const
+{
+    return m_aria_details;
+}
+
+bool AriaData::aria_disabled_or_default() const
+{
+    return m_aria_disabled;
+}
+
+Vector<AriaDropEffect> AriaData::aria_drop_effect_or_default() const
+{
+    return m_aria_drop_effect;
+}
+
+Optional<DeprecatedString> AriaData::aria_error_message_or_default() const
+{
+    return m_aria_error_message;
+}
+
+Optional<bool> AriaData::aria_expanded_or_default() const
+{
+    return m_aria_expanded;
+}
+
+Vector<DeprecatedString> AriaData::aria_flow_to_or_default() const
+{
+    return m_aria_flow_to;
+}
+
+Optional<bool> AriaData::aria_grabbed_or_default() const
+{
+    return m_aria_grabbed;
+}
+
+AriaHasPopup AriaData::aria_has_popup_or_default() const
+{
+    return m_aria_has_popup;
+}
+
+Optional<bool> AriaData::aria_hidden_or_default() const
+{
+    return m_aria_hidden;
+}
+
+AriaInvalid AriaData::aria_invalid_or_default() const
+{
+    return m_aria_invalid;
+}
+
+DeprecatedString AriaData::aria_key_shortcuts_or_default() const
+{
+    return m_aria_key_shortcuts;
+}
+
+DeprecatedString AriaData::aria_label_or_default() const
+{
+    return m_aria_label;
+}
+
+Vector<DeprecatedString> AriaData::aria_labelled_by_or_default() const
+{
+    return m_aria_labelled_by;
+}
+
+Optional<i32> AriaData::aria_level_or_default() const
+{
+    return m_aria_level;
+}
+
+AriaLive AriaData::aria_live_or_default(AriaLive default_value) const
+{
+    auto value = m_aria_live;
+    if (!value.has_value())
+        return default_value;
+
+    return value.value();
+}
+
+bool AriaData::aria_modal_or_default() const
+{
+    return m_aria_modal;
+}
+
+bool AriaData::aria_multi_line_or_default() const
+{
+    return m_aria_multi_line;
+}
+
+bool AriaData::aria_multi_selectable_or_default() const
+{
+    return m_aria_multi_selectable;
+}
+
+AriaOrientation AriaData::aria_orientation_or_default(AriaOrientation default_value) const
+{
+    auto value = m_aria_orientation;
+    if (!value.has_value())
+        return default_value;
+
+    return value.value();
+}
+
+Vector<DeprecatedString> AriaData::aria_owns_or_default() const
+{
+    return m_aria_owns;
+}
+
+DeprecatedString AriaData::aria_placeholder_or_default() const
+{
+    return m_aria_placeholder;
+}
+
+Optional<i32> AriaData::aria_pos_in_set_or_default() const
+{
+    return m_aria_pos_in_set;
+}
+
+Tristate AriaData::aria_pressed_or_default() const
+{
+    return m_aria_pressed;
+}
+
+bool AriaData::aria_read_only_or_default() const
+{
+    return m_aria_read_only;
+}
+
+Vector<AriaRelevant> AriaData::aria_relevant_or_default() const
+{
+    return m_aria_relevant;
+}
+
+bool AriaData::aria_required_or_default() const
+{
+    return m_aria_required;
+}
+
+DeprecatedString AriaData::aria_role_description_or_default() const
+{
+    return m_aria_role_description;
+}
+
+Optional<i32> AriaData::aria_row_count_or_default() const
+{
+    return m_aria_row_count;
+}
+
+Optional<i32> AriaData::aria_row_index_or_default() const
+{
+    return m_aria_row_index;
+}
+
+Optional<i32> AriaData::aria_row_span_or_default() const
+{
+    return m_aria_row_span;
+}
+
+Optional<bool> AriaData::aria_selected_or_default() const
+{
+    return m_aria_selected;
+}
+
+Optional<i32> AriaData::aria_set_size_or_default() const
+{
+    return m_aria_set_size;
+}
+
+AriaSort AriaData::aria_sort_or_default() const
+{
+    return m_aria_sort;
+}
+
+Optional<f64> AriaData::aria_value_max_or_default(Optional<f64> default_value) const
+{
+    auto value = m_aria_value_max;
+    if (!value.has_value())
+        return default_value;
+    return value;
+}
+
+Optional<f64> AriaData::aria_value_min_or_default(Optional<f64> default_value) const
+{
+    auto value = m_aria_value_min;
+    if (!value.has_value())
+        return default_value;
+    return value;
+}
+
+Optional<f64> AriaData::aria_value_now_or_default() const
+{
+    return m_aria_value_now;
+}
+
+DeprecatedString AriaData::aria_value_text_or_default() const
+{
+    return m_aria_value_text;
+}
+
+AriaAutocomplete AriaData::parse_aria_autocomplete(StringView value)
+{
+    if (value == "inline"sv)
+        return AriaAutocomplete::Inline;
+    if (value == "list"sv)
+        return AriaAutocomplete::List;
+    if (value == "both"sv)
+        return AriaAutocomplete::Both;
+    if (value == "none"sv)
+        return AriaAutocomplete::None;
+    return AriaAutocomplete::None;
+}
+
+AriaCurrent AriaData::parse_aria_current(StringView value)
+{
+    if (value == "page"sv)
+        return AriaCurrent::Page;
+    if (value == "step"sv)
+        return AriaCurrent::Step;
+    if (value == "location"sv)
+        return AriaCurrent::Location;
+    if (value == "date"sv)
+        return AriaCurrent::Date;
+    if (value == "time"sv)
+        return AriaCurrent::Time;
+    if (value == "true"sv)
+        return AriaCurrent::True;
+    if (value == "false"sv)
+        return AriaCurrent::False;
+    return AriaCurrent::False;
+}
+
+Vector<AriaDropEffect> AriaData::parse_aria_drop_effect(StringView value)
+{
+    Vector<AriaDropEffect> result;
+
+    for (auto token : value.split_view_if(Infra::is_ascii_whitespace)) {
+        if (token == "copy"sv)
+            result.append(AriaDropEffect::Copy);
+        else if (token == "execute"sv)
+            result.append(AriaDropEffect::Execute);
+        else if (token == "link"sv)
+            result.append(AriaDropEffect::Link);
+        else if (token == "move"sv)
+            result.append(AriaDropEffect::Move);
+        else if (token == "popup"sv)
+            result.append(AriaDropEffect::Popup);
+    }
+
+    // None combined with any other token value is ignored
+    if (result.is_empty())
+        result.append(AriaDropEffect::None);
+
+    return result;
+}
+
+AriaHasPopup AriaData::parse_aria_has_popup(StringView value)
+{
+    if (value == "false"sv)
+        return AriaHasPopup::False;
+    if (value == "true"sv)
+        return AriaHasPopup::True;
+    if (value == "menu"sv)
+        return AriaHasPopup::Menu;
+    if (value == "listbox"sv)
+        return AriaHasPopup::Listbox;
+    if (value == "tree"sv)
+        return AriaHasPopup::Tree;
+    if (value == "grid"sv)
+        return AriaHasPopup::Grid;
+    if (value == "dialog"sv)
+        return AriaHasPopup::Dialog;
+    return AriaHasPopup::False;
+}
+
+AriaInvalid AriaData::parse_aria_invalid(StringView value)
+{
+    if (value == "grammar"sv)
+        return AriaInvalid::Grammar;
+    if (value == "false"sv)
+        return AriaInvalid::False;
+    if (value == "spelling"sv)
+        return AriaInvalid::Spelling;
+    if (value == "true"sv)
+        return AriaInvalid::True;
+    return AriaInvalid::False;
+}
+
+Optional<AriaLive> AriaData::parse_aria_live(StringView value)
+{
+    if (value == "assertive"sv)
+        return AriaLive::Assertive;
+    if (value == "off"sv)
+        return AriaLive::Off;
+    if (value == "polite"sv)
+        return AriaLive::Polite;
+    return {};
+}
+
+Optional<AriaOrientation> AriaData::parse_aria_orientation(StringView value)
+{
+    if (value == "horizontal"sv)
+        return AriaOrientation::Horizontal;
+    if (value == "undefined"sv)
+        return AriaOrientation::Undefined;
+    if (value == "vertical"sv)
+        return AriaOrientation::Vertical;
+    return {};
+}
+
+Vector<AriaRelevant> AriaData::parse_aria_relevant(StringView value)
+{
+    Vector<AriaRelevant> result;
+    auto tokens = value.split_view_if(Infra::is_ascii_whitespace);
+    for (size_t i = 0; i < tokens.size(); i++) {
+        if (tokens[i] == "additions"sv) {
+            if (i + 1 < tokens.size()) {
+                if (tokens[i + 1] == "text"sv) {
+                    result.append(AriaRelevant::AdditionsText);
+                    ++i;
+                    continue;
+                }
+                if (tokens[i + 1] == "removals"sv && i + 2 < tokens.size() && tokens[i + 2] == "text"sv) {
+                    result.append(AriaRelevant::All);
+                    i += 2;
+                    continue;
+                }
+            }
+            result.append(AriaRelevant::Additions);
+        } else if (tokens[i] == "all"sv)
+            result.append(AriaRelevant::All);
+        else if (tokens[i] == "removals"sv)
+            result.append(AriaRelevant::Removals);
+        else if (tokens[i] == "text"sv)
+            result.append(AriaRelevant::Text);
+    }
+
+    if (result.is_empty())
+        result.append(AriaRelevant::AdditionsText);
+
+    return result;
+}
+
+AriaSort AriaData::parse_aria_sort(StringView value)
+{
+    if (value == "ascending"sv)
+        return AriaSort::Ascending;
+    if (value == "descending"sv)
+        return AriaSort::Descending;
+    if (value == "none"sv)
+        return AriaSort::None;
+    if (value == "other"sv)
+        return AriaSort::Other;
+    return AriaSort::None;
+}
+
+Optional<bool> AriaData::parse_optional_true_false(StringView value)
+{
+    if (value == "true"sv)
+        return true;
+    if (value == "false"sv)
+        return false;
+    return {};
+}
+
+}

+ 285 - 0
Userland/Libraries/LibWeb/ARIA/AriaData.h

@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2023, Jonah Shafran <jonahshafran@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/NonnullOwnPtr.h>
+#include <AK/Vector.h>
+#include <LibWeb/ARIA/ARIAMixin.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::ARIA {
+
+// https://www.w3.org/TR/wai-aria-1.2/#valuetype_tristate
+enum class Tristate {
+    True,
+    False,
+    Mixed,
+    Undefined
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-autocomplete
+enum class AriaAutocomplete {
+    // When a user is providing input, text suggesting one way to complete the provided input may be dynamically inserted after the caret.
+    Inline,
+    // When a user is providing input, an element containing a collection of values that could complete the provided input may be displayed.
+    List,
+    // When a user is providing input, an element containing a collection of values that could complete the provided input may be displayed.
+    // If displayed, one value in the collection is automatically selected, and the text needed to complete the automatically selected value appears after the caret in the input
+    Both,
+    // When a user is providing input, an automatic suggestion that attempts to predict how the user intends to complete the input is not displayed.
+    None
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-current
+enum class AriaCurrent {
+    // Represents the current page within a set of pages.
+    Page,
+    // Represents the current step within a process.
+    Step,
+    // Represents the current location within an environment or context.
+    Location,
+    // Represents the current date within a collection of dates.
+    Date,
+    // Represents the current time within a set of times.
+    Time,
+    // Represents the current item within a set.
+    True,
+    // Does not represent the current item within a set.
+    False
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-dropeffect
+enum class AriaDropEffect {
+    // A duplicate of the source object will be dropped into the target.
+    Copy,
+    // A function supported by the drop target is executed, using the drag source as an input.
+    Execute,
+    // A reference or shortcut to the dragged object will be created in the target object.
+    Link,
+    // The source object will be removed from its current location and dropped into the target.
+    Move,
+    // No operation can be performed; effectively cancels the drag operation if an attempt is made to drop on this object.
+    // Ignored if combined with any other token value. e.g., 'none copy' is equivalent to a 'copy' value.
+    None,
+    // There is a popup menu or dialog that allows the user to choose one of the drag operations (copy, move, link, execute) and any other drag functionality, such as cancel.
+    Popup
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-haspopup
+enum class AriaHasPopup {
+    // Indicates the element does not have a popup.
+    False,
+    // Indicates the popup is a menu.
+    True,
+    // Indicates the popup is a menu.
+    Menu,
+    // Indicates the popup is a listbox.
+    Listbox,
+    // Indicates the popup is a tree.
+    Tree,
+    // Indicates the popup is a grid.
+    Grid,
+    // Indicates the popup is a dialog.
+    Dialog
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-invalid
+enum class AriaInvalid {
+    // A grammatical error was detected.
+    Grammar,
+    // There are no detected errors in the value.
+    False,
+    // A spelling error was detected.
+    Spelling,
+    // The value entered by the user has failed validation.
+    True
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-live
+enum class AriaLive {
+    // Indicates that updates to the region have the highest priority and should be presented the user immediately.
+    Assertive,
+    // Indicates that updates to the region should not be presented to the user unless the user is currently focused on that region.
+    Off,
+    // Indicates that updates to the region should be presented at the next graceful opportunity, such as at the end of speaking the current sentence or when the user pauses typing.
+    Polite
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-orientation
+enum class AriaOrientation {
+    // The element is oriented horizontally.
+    Horizontal,
+    // The element's orientation is unknown/ambiguous.
+    Undefined,
+    // The element is oriented vertically.
+    Vertical
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-relevant
+enum class AriaRelevant {
+    // Element nodes are added to the accessibility tree within the live region.
+    Additions,
+    // Equivalent to the combination of values, "additions text".
+    AdditionsText,
+    // Equivalent to the combination of all values, "additions removals text".
+    All,
+    // Text content, a text alternative, or an element node within the live region is removed from the accessibility tree.
+    Removals,
+    // Text content or a text alternative is added to any descendant in the accessibility tree of the live region.
+    Text
+};
+
+// https://www.w3.org/TR/wai-aria-1.2/#aria-sort
+enum class AriaSort {
+    // Items are sorted in ascending order by this column.
+    Ascending,
+    // Items are sorted in descending order by this column.
+    Descending,
+    // There is no defined sort applied to the column.
+    None,
+    // A sort algorithm other than ascending or descending has been applied.
+    Other
+};
+
+class AriaData {
+public:
+    AriaData() { }
+
+    static ErrorOr<NonnullOwnPtr<AriaData>> build_data(ARIAMixin const& mixin) { return adopt_nonnull_own_or_enomem(new (nothrow) AriaData(mixin)); }
+
+    Optional<DeprecatedString> aria_active_descendant_or_default() const;
+    bool aria_atomic_or_default(bool default_value = false) const;
+    AriaAutocomplete aria_auto_complete_or_default() const;
+    bool aria_busy_or_default() const;
+    Tristate aria_checked_or_default() const;
+    Optional<i32> aria_col_count_or_default() const;
+    Optional<i32> aria_col_index_or_default() const;
+    Optional<i32> aria_col_span_or_default() const;
+    Vector<DeprecatedString> aria_controls_or_default() const;
+    AriaCurrent aria_current_or_default() const;
+    Vector<DeprecatedString> aria_described_by_or_default() const;
+    Optional<DeprecatedString> aria_details_or_default() const;
+    bool aria_disabled_or_default() const;
+    Vector<AriaDropEffect> aria_drop_effect_or_default() const;
+    Optional<DeprecatedString> aria_error_message_or_default() const;
+    Optional<bool> aria_expanded_or_default() const;
+    Vector<DeprecatedString> aria_flow_to_or_default() const;
+    Optional<bool> aria_grabbed_or_default() const;
+    AriaHasPopup aria_has_popup_or_default() const;
+    Optional<bool> aria_hidden_or_default() const;
+    AriaInvalid aria_invalid_or_default() const;
+    DeprecatedString aria_key_shortcuts_or_default() const;
+    DeprecatedString aria_label_or_default() const;
+    Vector<DeprecatedString> aria_labelled_by_or_default() const;
+    Optional<i32> aria_level_or_default() const;
+    AriaLive aria_live_or_default(AriaLive default_value = AriaLive::Off) const;
+    bool aria_modal_or_default() const;
+    bool aria_multi_line_or_default() const;
+    bool aria_multi_selectable_or_default() const;
+    AriaOrientation aria_orientation_or_default(AriaOrientation default_value = AriaOrientation::Undefined) const;
+    Vector<DeprecatedString> aria_owns_or_default() const;
+    DeprecatedString aria_placeholder_or_default() const;
+    Optional<i32> aria_pos_in_set_or_default() const;
+    Tristate aria_pressed_or_default() const;
+    bool aria_read_only_or_default() const;
+    Vector<AriaRelevant> aria_relevant_or_default() const;
+    bool aria_required_or_default() const;
+    DeprecatedString aria_role_description_or_default() const;
+    Optional<i32> aria_row_count_or_default() const;
+    Optional<i32> aria_row_index_or_default() const;
+    Optional<i32> aria_row_span_or_default() const;
+    Optional<bool> aria_selected_or_default() const;
+    Optional<i32> aria_set_size_or_default() const;
+    AriaSort aria_sort_or_default() const;
+    Optional<f64> aria_value_max_or_default(Optional<f64> default_value = {}) const;
+    Optional<f64> aria_value_min_or_default(Optional<f64> default_value = {}) const;
+    Optional<f64> aria_value_now_or_default() const;
+    DeprecatedString aria_value_text_or_default() const;
+
+private:
+    explicit AriaData(ARIAMixin const&);
+
+    // https://www.w3.org/TR/wai-aria-1.2/#valuetype_true-false
+    // The default value for this value type is false unless otherwise specified.
+    static bool parse_true_false(StringView);
+
+    // https://www.w3.org/TR/wai-aria-1.2/#valuetype_tristate
+    // The default value for this value type is undefined unless otherwise specified.
+    static Tristate parse_tristate(StringView);
+
+    // https://www.w3.org/TR/wai-aria-1.2/#valuetype_true-false-undefined
+    // The default value for this value type is undefined unless otherwise specified.
+    static Optional<bool> parse_true_false_undefined(StringView);
+
+    // https://www.w3.org/TR/wai-aria-1.2/#valuetype_integer
+    static Optional<i32> parse_integer(StringView);
+
+    // https://www.w3.org/TR/wai-aria-1.2/#valuetype_number
+    static Optional<f64> parse_number(StringView);
+
+    static AriaAutocomplete parse_aria_autocomplete(StringView);
+    static AriaCurrent parse_aria_current(StringView);
+    static Vector<AriaDropEffect> parse_aria_drop_effect(StringView);
+    static AriaHasPopup parse_aria_has_popup(StringView);
+    static AriaInvalid parse_aria_invalid(StringView);
+    static Optional<AriaLive> parse_aria_live(StringView);
+    static Optional<AriaOrientation> parse_aria_orientation(StringView);
+    static Vector<AriaRelevant> parse_aria_relevant(StringView);
+    static AriaSort parse_aria_sort(StringView);
+    static Optional<bool> parse_optional_true_false(StringView);
+
+    Optional<DeprecatedString> m_aria_active_descendant;
+    Optional<bool> m_aria_atomic;
+    AriaAutocomplete m_aria_auto_complete;
+    bool m_aria_busy;
+    Tristate m_aria_checked;
+    Optional<i32> m_aria_col_count;
+    Optional<i32> m_aria_col_index;
+    Optional<i32> m_aria_col_span;
+    Vector<DeprecatedString> m_aria_controls;
+    AriaCurrent m_aria_current;
+    Vector<DeprecatedString> m_aria_described_by;
+    Optional<DeprecatedString> m_aria_details;
+    bool m_aria_disabled;
+    Vector<AriaDropEffect> m_aria_drop_effect;
+    Optional<DeprecatedString> m_aria_error_message;
+    Optional<bool> m_aria_expanded;
+    Vector<DeprecatedString> m_aria_flow_to;
+    Optional<bool> m_aria_grabbed;
+    AriaHasPopup m_aria_has_popup;
+    Optional<bool> m_aria_hidden;
+    AriaInvalid m_aria_invalid;
+    DeprecatedString m_aria_key_shortcuts;
+    DeprecatedString m_aria_label;
+    Vector<DeprecatedString> m_aria_labelled_by;
+    Optional<i32> m_aria_level;
+    Optional<AriaLive> m_aria_live;
+    bool m_aria_modal;
+    bool m_aria_multi_line;
+    bool m_aria_multi_selectable;
+    Optional<AriaOrientation> m_aria_orientation;
+    Vector<DeprecatedString> m_aria_owns;
+    DeprecatedString m_aria_placeholder;
+    Optional<i32> m_aria_pos_in_set;
+    Tristate m_aria_pressed;
+    bool m_aria_read_only;
+    Vector<AriaRelevant> m_aria_relevant;
+    bool m_aria_required;
+    DeprecatedString m_aria_role_description;
+    Optional<i32> m_aria_row_count;
+    Optional<i32> m_aria_row_index;
+    Optional<i32> m_aria_row_span;
+    Optional<bool> m_aria_selected;
+    Optional<i32> m_aria_set_size;
+    AriaSort m_aria_sort;
+    Optional<f64> m_aria_value_max;
+    Optional<f64> m_aria_value_min;
+    Optional<f64> m_aria_value_now;
+    DeprecatedString m_aria_value_text;
+};
+
+}

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -1,6 +1,7 @@
 include(libweb_generators)
 include(libweb_generators)
 
 
 set(SOURCES
 set(SOURCES
+    ARIA/AriaData.cpp
     ARIA/ARIAMixin.cpp
     ARIA/ARIAMixin.cpp
     ARIA/ARIAMixin.idl
     ARIA/ARIAMixin.idl
     ARIA/Roles.cpp
     ARIA/Roles.cpp

+ 5 - 0
Userland/Libraries/LibWeb/DOM/Element.cpp

@@ -1779,4 +1779,9 @@ void Element::scroll(HTML::ScrollToOptions const&)
     dbgln("FIXME: Implement Element::scroll(ScrollToOptions)");
     dbgln("FIXME: Implement Element::scroll(ScrollToOptions)");
 }
 }
 
 
+bool Element::id_reference_exists(DeprecatedString const& id_reference) const
+{
+    return document().get_element_by_id(id_reference);
+}
+
 }
 }

+ 2 - 0
Userland/Libraries/LibWeb/DOM/Element.h

@@ -318,6 +318,8 @@ protected:
 
 
     virtual void visit_edges(Cell::Visitor&) override;
     virtual void visit_edges(Cell::Visitor&) override;
 
 
+    virtual bool id_reference_exists(DeprecatedString const&) const override;
+
 private:
 private:
     void make_html_uppercased_qualified_name();
     void make_html_uppercased_qualified_name();
 
 

+ 6 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -23,6 +23,12 @@ class ResourceLoader;
 class XMLDocumentBuilder;
 class XMLDocumentBuilder;
 }
 }
 
 
+namespace Web::ARIA {
+class AriaData;
+class ARIAMixin;
+enum class StateAndProperties;
+}
+
 namespace Web::Bindings {
 namespace Web::Bindings {
 class Intrinsics;
 class Intrinsics;
 class OptionConstructor;
 class OptionConstructor;