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.
This commit is contained in:
Tim Ledbetter 2024-09-07 23:17:56 +01:00 committed by Andreas Kling
parent f83d082980
commit c25dda767e
Notes: github-actions[bot] 2024-09-08 07:48:53 +00:00
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 // 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) 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 // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-reset-control
virtual void reset_algorithm() {}; virtual void reset_algorithm() {};
String form_action() const;
WebIDL::ExceptionOr<void> set_form_action(String const&);
protected: protected:
FormAssociatedElement() = default; FormAssociatedElement() = default;
virtual ~FormAssociatedElement() = default; virtual ~FormAssociatedElement() = default;

View file

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