From 7785a1072987e817dc49a70ed2b80d1ebccf8235 Mon Sep 17 00:00:00 2001 From: Pavel Shliak Date: Fri, 20 Dec 2024 21:26:49 +0400 Subject: [PATCH] LibWeb: Update FormData constructor to reflect the spec --- Libraries/LibWeb/XHR/FormData.cpp | 30 ++++++++++++++++++++++++++---- Libraries/LibWeb/XHR/FormData.h | 2 +- Libraries/LibWeb/XHR/FormData.idl | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Libraries/LibWeb/XHR/FormData.cpp b/Libraries/LibWeb/XHR/FormData.cpp index 3c1421f75b17..ef26f842a87f 100644 --- a/Libraries/LibWeb/XHR/FormData.cpp +++ b/Libraries/LibWeb/XHR/FormData.cpp @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include #include #include @@ -18,17 +20,37 @@ namespace Web::XHR { GC_DEFINE_ALLOCATOR(FormData); // https://xhr.spec.whatwg.org/#dom-formdata -WebIDL::ExceptionOr> FormData::construct_impl(JS::Realm& realm, GC::Ptr form) +WebIDL::ExceptionOr> FormData::construct_impl(JS::Realm& realm, GC::Ptr form, Optional> submitter) { Vector list; // 1. If form is given, then: if (form) { - // 1. Let list be the result of constructing the entry list for form. + // 1. If submitter is non-null, then: + if (submitter.has_value() && submitter.value()) { + auto& submitter_element = submitter.value(); + + // 1. If submitter is not a submit button, then throw a TypeError. + if (!is(*submitter_element)) { + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Submitter is not associated with a form."sv }; + } + auto* form_associated_element = dynamic_cast(submitter_element.ptr()); + + if (!form_associated_element->is_submit_button()) { + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Submitter is not a valid submit button."sv }; + } + // 2. If submitter’s form owner is not form, then throw a "NotFoundError" DOMException. + auto* form_owner = form_associated_element->form(); + if (form_owner && form_owner != form) { + return WebIDL::NotFoundError::create(realm, "Submitter does not belong to the provided form."_string); + } + } + + // 2. Let list be the result of constructing the entry list for form. auto entry_list = TRY(construct_entry_list(realm, *form)); - // 2. If list is null, then throw an "InvalidStateError" DOMException. + // 3. If list is null, then throw an "InvalidStateError" DOMException. if (!entry_list.has_value()) return WebIDL::InvalidStateError::create(realm, "Form element does not contain any entries."_string); - // 3. Set this’s entry list to list. + // 4. Set this’s entry list to list. list = entry_list.release_value(); } diff --git a/Libraries/LibWeb/XHR/FormData.h b/Libraries/LibWeb/XHR/FormData.h index fc37565dd819..a185bba9ce68 100644 --- a/Libraries/LibWeb/XHR/FormData.h +++ b/Libraries/LibWeb/XHR/FormData.h @@ -24,7 +24,7 @@ class FormData : public Bindings::PlatformObject { public: virtual ~FormData() override; - static WebIDL::ExceptionOr> construct_impl(JS::Realm&, GC::Ptr form = {}); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, GC::Ptr form = {}, Optional> submitter = {}); static WebIDL::ExceptionOr> construct_impl(JS::Realm&, Vector entry_list); static WebIDL::ExceptionOr> create(JS::Realm&, Vector entry_list); diff --git a/Libraries/LibWeb/XHR/FormData.idl b/Libraries/LibWeb/XHR/FormData.idl index fb844b2e7a8f..aa6f86a6d625 100644 --- a/Libraries/LibWeb/XHR/FormData.idl +++ b/Libraries/LibWeb/XHR/FormData.idl @@ -11,7 +11,7 @@ typedef (File or USVString) FormDataEntryValue; // https://xhr.spec.whatwg.org/#interface-formdata [Exposed=(Window,Worker)] interface FormData { - constructor(optional HTMLFormElement form); + constructor(optional HTMLFormElement form, optional HTMLElement? submitter = null); undefined append(USVString name, USVString value); undefined append(USVString name, Blob blobValue, optional USVString filename);