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.

(cherry picked from commit c25dda767eb43d1620602ccc2c955bc56ef1745b)
This commit is contained in:
Tim Ledbetter 2024-09-07 23:17:56 +01:00 committed by Nico Weber
parent d511b366a3
commit 42d17fb875
5 changed files with 47 additions and 1 deletions

View file

@ -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

View file

@ -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>

View file

@ -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)
{

View file

@ -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;

View file

@ -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;