From 8448149de66451af9aff225a796a13b978d8c47d Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Thu, 30 Jan 2025 14:50:23 +0000 Subject: [PATCH] LibWeb/HTML: Extract dialog show_modal() into its own algorithm Corresponds to https://github.com/whatwg/html/pull/10961 --- Libraries/LibWeb/HTML/HTMLDialogElement.cpp | 92 +++++++++++---------- Libraries/LibWeb/HTML/HTMLDialogElement.h | 2 + 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/Libraries/LibWeb/HTML/HTMLDialogElement.cpp b/Libraries/LibWeb/HTML/HTMLDialogElement.cpp index e3d9f3606931..3d2bc69814e8 100644 --- a/Libraries/LibWeb/HTML/HTMLDialogElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLDialogElement.cpp @@ -150,80 +150,88 @@ WebIDL::ExceptionOr HTMLDialogElement::show() // https://html.spec.whatwg.org/multipage/interactive-elements.html#dom-dialog-showmodal WebIDL::ExceptionOr HTMLDialogElement::show_modal() { - // 1. If this has an open attribute and is modal of this is true, then return. - if (has_attribute(AttributeNames::open) && m_is_modal) + // The showModal() method steps are to show a modal dialog given this. + return show_a_modal_dialog(*this); +} + +WebIDL::ExceptionOr HTMLDialogElement::show_a_modal_dialog(HTMLDialogElement& subject) +{ + // To show a modal dialog given a dialog element subject: + auto& realm = subject.realm(); + + // 1. If subject has an open attribute and is modal of subject is true, then return. + if (subject.has_attribute(AttributeNames::open) && subject.m_is_modal) return {}; - // 2. If this has an open attribute, then throw an "InvalidStateError" DOMException. - if (has_attribute(AttributeNames::open)) - return WebIDL::InvalidStateError::create(realm(), "Dialog already open"_string); + // 2. If subject has an open attribute, then throw an "InvalidStateError" DOMException. + if (subject.has_attribute(AttributeNames::open)) + return WebIDL::InvalidStateError::create(realm, "Dialog already open"_string); - // 3. If this's node document is not fully active, then throw an "InvalidStateError" DOMException. - if (!document().is_fully_active()) - return WebIDL::InvalidStateError::create(realm(), "Document is not fully active"_string); + // 3. If subject's node document is not fully active, then throw an "InvalidStateError" DOMException. + if (!subject.document().is_fully_active()) + return WebIDL::InvalidStateError::create(realm, "Document is not fully active"_string); - // 4. If this is not connected, then throw an "InvalidStateError" DOMException. - if (!is_connected()) - return WebIDL::InvalidStateError::create(realm(), "Dialog not connected"_string); + // 4. If subject is not connected, then throw an "InvalidStateError" DOMException. + if (!subject.is_connected()) + return WebIDL::InvalidStateError::create(realm, "Dialog not connected"_string); - // 5. If this is in the popover showing state, then throw an "InvalidStateError" DOMException. - if (popover_visibility_state() == PopoverVisibilityState::Showing) - return WebIDL::InvalidStateError::create(realm(), "Dialog already open as popover"_string); + // 5. If subject is in the popover showing state, then throw an "InvalidStateError" DOMException. + if (subject.popover_visibility_state() == PopoverVisibilityState::Showing) + return WebIDL::InvalidStateError::create(realm, "Dialog already open as popover"_string); // 6. If the result of firing an event named beforetoggle, using ToggleEvent, // with the cancelable attribute initialized to true, the oldState attribute initialized to "closed", - // and the newState attribute initialized to "open" at this is false, then return. + // and the newState attribute initialized to "open" at subject is false, then return. ToggleEventInit event_init {}; event_init.cancelable = true; event_init.old_state = "closed"_string; event_init.new_state = "open"_string; - auto beforetoggle_result = dispatch_event(ToggleEvent::create(realm(), HTML::EventNames::beforetoggle, move(event_init))); + auto beforetoggle_result = subject.dispatch_event(ToggleEvent::create(realm, EventNames::beforetoggle, move(event_init))); if (!beforetoggle_result) return {}; - // 7. If this has an open attribute, then return. - if (has_attribute(AttributeNames::open)) + // 7. If subject has an open attribute, then return. + if (subject.has_attribute(AttributeNames::open)) return {}; - // 8. If this is not connected, then return. - if (!is_connected()) + // 8. If subject is not connected, then return. + if (!subject.is_connected()) return {}; - // 9. If this is in the popover showing state, then return. - if (popover_visibility_state() == PopoverVisibilityState::Showing) + // 9. If subject is in the popover showing state, then return. + if (subject.popover_visibility_state() == PopoverVisibilityState::Showing) return {}; // 10. Queue a dialog toggle event task given subject, "closed", and "open". - queue_a_dialog_toggle_event_task("closed"_string, "open"_string); + subject.queue_a_dialog_toggle_event_task("closed"_string, "open"_string); - // 11. Add an open attribute to this, whose value is the empty string. - TRY(set_attribute(AttributeNames::open, {})); + // 11. Add an open attribute to subject, whose value is the empty string. + TRY(subject.set_attribute(AttributeNames::open, {})); - // 12. Set is modal of this to true. - m_is_modal = true; + // 12. Set is modal of subject to true. + subject.m_is_modal = true; - // FIXME: 13. Assert: this's node document's open dialogs list does not contain this. - // FIXME: 14. Add this to this's node document's open dialogs list. - // FIXME: 15. Let this's node document be blocked by the modal dialog this. + // FIXME: 13. Assert: subject's node document's open dialogs list does not contain subject. + // FIXME: 14. Add subject to subject's node document's open dialogs list. + // FIXME: 15. Let subject's node document be blocked by the modal dialog subject. - // 16. If this's node document's top layer does not already contain this, then add an element to the top layer given this. - if (!document().top_layer_elements().contains(*this)) - document().add_an_element_to_the_top_layer(*this); + // 16. If subject's node document's top layer does not already contain subject, then add an element to the top layer given subject. + if (!subject.document().top_layer_elements().contains(subject)) + subject.document().add_an_element_to_the_top_layer(subject); - // 17. Set the dialog close watcher with this. - set_close_watcher(); - - // FIXME: 18. Set this's previously focused element to the focused element. + // 17. Set the dialog close watcher with subject. + subject.set_close_watcher(); - // FIXME: 19. Let document be this's node document. - // FIXME: 20. Let hideUntil be the result of running topmost popover ancestor given this, document's showing hint popover list, null, and false. - // FIXME: 21. If hideUntil is null, then set hideUntil to the result of running topmost popover ancestor given this, document's showing auto popover list, null, and false. + // FIXME: 18. Set subject's previously focused element to the focused element. + // FIXME: 19. Let document be subject's node document. + // FIXME: 20. Let hideUntil be the result of running topmost popover ancestor given subject, document's showing hint popover list, null, and false. + // FIXME: 21. If hideUntil is null, then set hideUntil to the result of running topmost popover ancestor given subject, document's showing auto popover list, null, and false. // FIXME: 22. If hideUntil is null, then set hideUntil to document. // FIXME: 23. Run hide all popovers until given hideUntil, false, and true. - // 24. Run the dialog focusing steps given this. - run_dialog_focusing_steps(); + // 24. Run the dialog focusing steps given subject. + subject.run_dialog_focusing_steps(); return {}; } diff --git a/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Libraries/LibWeb/HTML/HTMLDialogElement.h index de4e3f54aff0..3c8eb41f2a4e 100644 --- a/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -26,6 +26,8 @@ class HTMLDialogElement final : public HTMLElement { String return_value() const; void set_return_value(String); + static WebIDL::ExceptionOr show_a_modal_dialog(HTMLDialogElement&); + WebIDL::ExceptionOr show(); WebIDL::ExceptionOr show_modal(); void close(Optional return_value);