fix: allow form submission for input [type=image] (#34203)

* fix: allow form submission for input [type=image]

Signed-off-by: Shane Handley <shanehandley@fastmail.com>

* Fix comments and use existing can_gc where available

Signed-off-by: Shane Handley <shanehandley@fastmail.com>

---------

Signed-off-by: Shane Handley <shanehandley@fastmail.com>
This commit is contained in:
shanehandley 2024-11-15 01:28:48 +11:00 committed by GitHub
parent 3fd1a229df
commit 313597f325
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 75 additions and 145 deletions

View file

@ -538,7 +538,7 @@ impl HTMLInputElement {
self.default_maximum()
}
// when allowed_value_step and minumum both exist, this is the smallest
// when allowed_value_step and minimum both exist, this is the smallest
// value >= minimum that lies on an integer step
fn stepped_minimum(&self) -> Option<f64> {
match (self.minimum(), self.allowed_value_step()) {
@ -1130,6 +1130,7 @@ impl TextControlElement for HTMLInputElement {
}
}
#[allow(non_snake_case)]
impl HTMLInputElementMethods for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#dom-input-accept
make_getter!(Accept, "accept");
@ -2719,11 +2720,15 @@ impl Activatable for HTMLInputElement {
fn is_instance_activatable(&self) -> bool {
match self.input_type() {
// https://html.spec.whatwg.org/multipage/#submit-button-state-%28type=submit%29:activation-behaviour-2
// https://html.spec.whatwg.org/multipage/#reset-button-state-%28type=reset%29:activation-behaviour-2
// https://html.spec.whatwg.org/multipage/#checkbox-state-%28type=checkbox%29:activation-behaviour-2
// https://html.spec.whatwg.org/multipage/#radio-button-state-%28type=radio%29:activation-behaviour-2
InputType::Submit | InputType::Reset | InputType::File => self.is_mutable(),
// https://html.spec.whatwg.org/multipage/#submit-button-state-(type=submit):input-activation-behavior
// https://html.spec.whatwg.org/multipage/#reset-button-state-(type=reset):input-activation-behavior
// https://html.spec.whatwg.org/multipage/#file-upload-state-(type=file):input-activation-behavior
// https://html.spec.whatwg.org/multipage/#image-button-state-(type=image):input-activation-behavior
InputType::Submit | InputType::Reset | InputType::File | InputType::Image => {
self.is_mutable()
},
// https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox):input-activation-behavior
// https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):input-activation-behavior
InputType::Checkbox | InputType::Radio => true,
_ => false,
}
@ -2812,16 +2817,24 @@ impl Activatable for HTMLInputElement {
}
}
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
/// <https://html.spec.whatwg.org/multipage/#input-activation-behavior>
fn activation_behavior(&self, _event: &Event, _target: &EventTarget, can_gc: CanGc) {
let ty = self.input_type();
match ty {
InputType::Submit => {
match self.input_type() {
// https://html.spec.whatwg.org/multipage/#submit-button-state-(type=submit):activation-behavior
// FIXME (Manishearth): support document owners (needs ability to get parent browsing context)
// Check if document owner is fully active
if let Some(o) = self.form_owner() {
o.submit(
// https://html.spec.whatwg.org/multipage/#submit-button-state-(type=image):activation-behavior
InputType::Submit | InputType::Image => {
// Step 1: If the element does not have a form owner, then return.
if let Some(form_owner) = self.form_owner() {
// Step 2: If the element's node document is not fully active, then return.
let document = document_from_node(self);
if !document.is_fully_active() {
return;
}
// Step 3: Submit the element's form owner from the element with userInvolvement
// set to event's user navigation involvement.
form_owner.submit(
SubmittedFrom::NotFromForm,
FormSubmitterElement::Input(self),
CanGc::note(),
@ -2830,24 +2843,39 @@ impl Activatable for HTMLInputElement {
},
InputType::Reset => {
// https://html.spec.whatwg.org/multipage/#reset-button-state-(type=reset):activation-behavior
// FIXME (Manishearth): support document owners (needs ability to get parent browsing context)
// Check if document owner is fully active
if let Some(o) = self.form_owner() {
o.reset(ResetFrom::NotFromForm, CanGc::note())
// Step 1: If the element does not have a form owner, then return.
if let Some(form_owner) = self.form_owner() {
let document = document_from_node(self);
// Step 2: If the element's node document is not fully active, then return.
if !document.is_fully_active() {
return;
}
// Step 3: Reset the form owner from the element.
form_owner.reset(ResetFrom::NotFromForm, can_gc);
}
},
InputType::Checkbox | InputType::Radio => {
// https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox):activation-behavior
// https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):activation-behavior
// Check if document owner is fully active
InputType::Checkbox | InputType::Radio => {
// Step 1: If the element is not connected, then return.
if !self.upcast::<Node>().is_connected() {
return;
}
let target = self.upcast::<EventTarget>();
// Step 2: Fire an event named input at the element with the bubbles and composed
// attributes initialized to true.
target.fire_bubbling_event(atom!("input"), can_gc);
// Step 3: Fire an event named change at the element with the bubbles attribute
// initialized to true.
target.fire_bubbling_event(atom!("change"), can_gc);
},
InputType::File => self.select_files(None, CanGc::note()),
// https://html.spec.whatwg.org/multipage/#file-upload-state-(type=file):input-activation-behavior
InputType::File => self.select_files(None, can_gc),
_ => (),
}
}

View file

@ -5,39 +5,12 @@
[When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <A></A>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.]
expected: FAIL

View file

@ -10,6 +10,3 @@
[Files in a text/plain form show up as File objects in the "formData" IDL attribute]
expected: FAIL
[The constructed FormData object should not contain an entry for the image submit button that was used to submit the form.]
expected: FAIL

View file

@ -1,19 +0,0 @@
[form-submission-algorithm.html]
expected: TIMEOUT
[Submission URL should always have a non-null query part]
expected: NOTRUN
[firing an event named submit; clicking an image button]
expected: TIMEOUT
[firing an event named submit; form.requestSubmit()]
expected: NOTRUN
[firing an event named submit; form.requestSubmit(null)]
expected: NOTRUN
[firing an event named submit; form.requestSubmit(submitter)]
expected: NOTRUN
[Cannot navigate (after constructing the entry list)]
expected: NOTRUN

View file

@ -5,39 +5,12 @@
[When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <A></A>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.]
expected: FAIL
[When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.]
expected: FAIL
@ -50,30 +23,6 @@
[When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <INPUT type=checkbox></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <INPUT type=radio></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <AREA></AREA>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.]
expected: FAIL
@ -115,3 +64,27 @@
[When clicking child <AREA></AREA> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <INPUT type=checkbox></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <INPUT type=radio></INPUT>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.]
expected: FAIL
[When clicking child <A></A> of parent <AREA></AREA>, only child should be activated.]
expected: FAIL

View file

@ -10,6 +10,3 @@
[Files in a text/plain form show up as File objects in the "formData" IDL attribute]
expected: FAIL
[The constructed FormData object should not contain an entry for the image submit button that was used to submit the form.]
expected: FAIL

View file

@ -1,19 +0,0 @@
[form-submission-algorithm.html]
expected: TIMEOUT
[Submission URL should always have a non-null query part]
expected: NOTRUN
[firing an event named submit; clicking an image button]
expected: TIMEOUT
[firing an event named submit; form.requestSubmit()]
expected: NOTRUN
[firing an event named submit; form.requestSubmit(null)]
expected: NOTRUN
[firing an event named submit; form.requestSubmit(submitter)]
expected: NOTRUN
[Cannot navigate (after constructing the entry list)]
expected: NOTRUN