Преглед на файлове

LibWeb: Return document URL if formAction attribute is missing or empty

This change also ensures that relative URLs are resolved relative to
the document's base URL.
Tim Ledbetter преди 10 месеца
родител
ревизия
c25dda767e

+ 3 - 0
Tests/LibWeb/Text/expected/HTML/formAction-attribute.txt

@@ -0,0 +1,3 @@
+button.formAction initial value: http://www.example.com/
+Final segment of button.formAction after setting to the empty string: formAction-attribute.html
+Final segment of button.formAction after setting to "../test.html": test.html

+ 19 - 0
Tests/LibWeb/Text/input/HTML/formAction-attribute.html

@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="../include.js"></script>
+<button formaction="http://www.example.com/"></button>
+<script>
+    test(() => {
+        const elementNames = [
+            "button",
+        ];
+        for (const elementName of elementNames) {
+            const element = document.querySelector(elementName);
+            println(`${elementName}.formAction initial value: ${element.formAction}`);
+            element.formAction = "";
+            println(`Final segment of ${elementName}.formAction after setting to the empty string: ${element.formAction.split('/').pop()}`);
+            element.formAction = "../test.html";
+            println(`Final segment of ${elementName}.formAction after setting to "../test.html": ${element.formAction.split('/').pop()}`);
+            element.remove();
+        }
+    });
+</script>

+ 21 - 0
Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp

@@ -166,6 +166,27 @@ void FormAssociatedElement::reset_form_owner()
     }
 }
 
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-fs-formaction
+String FormAssociatedElement::form_action() const
+{
+    // The formAction IDL attribute must reflect the formaction content attribute, except that on getting, when the content attribute is missing or its value is the empty string,
+    // the element's node document's URL must be returned instead.
+    auto& html_element = form_associated_element_to_html_element();
+    auto form_action_attribute = html_element.attribute(HTML::AttributeNames::formaction);
+    if (!form_action_attribute.has_value() || form_action_attribute.value().is_empty()) {
+        return html_element.document().url_string();
+    }
+
+    auto document_base_url = html_element.document().base_url();
+    return MUST(document_base_url.complete_url(form_action_attribute.value()).to_string());
+}
+
+WebIDL::ExceptionOr<void> FormAssociatedElement::set_form_action(String const& value)
+{
+    auto& html_element = form_associated_element_to_html_element();
+    return html_element.set_attribute(HTML::AttributeNames::formaction, value);
+}
+
 // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-textarea/input-relevant-value
 void FormAssociatedTextControlElement::relevant_value_was_changed(JS::GCPtr<DOM::Text> text_node)
 {

+ 3 - 0
Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h

@@ -98,6 +98,9 @@ public:
     // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-reset-control
     virtual void reset_algorithm() {};
 
+    String form_action() const;
+    WebIDL::ExceptionOr<void> set_form_action(String const&);
+
 protected:
     FormAssociatedElement() = default;
     virtual ~FormAssociatedElement() = default;

+ 1 - 1
Userland/Libraries/LibWeb/HTML/HTMLButtonElement.idl

@@ -15,7 +15,7 @@ interface HTMLButtonElement : HTMLElement {
 
     [CEReactions, Reflect] attribute boolean disabled;
     readonly attribute HTMLFormElement? form;
-    [CEReactions, Reflect=formaction] attribute USVString formAction;
+    [CEReactions] attribute USVString formAction;
     [CEReactions, Reflect=formenctype] attribute DOMString formEnctype;
     [CEReactions, Reflect=formmethod] attribute DOMString formMethod;
     [CEReactions, Reflect=formnovalidate] attribute boolean formNoValidate;