Commit 778c5dab authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

Implement form.requestSubmit().

https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit

Intent: https://groups.google.com/a/chromium.org/d/msg/blink-dev/CxelaeahNho/aC6Zp8KvAwAJ

Bug: 964062
Change-Id: Iea72587605c8f1c13c98b05be3b7d971c9fe7543
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1616924
Commit-Queue: Kent Tamura <tkent@chromium.org>
Reviewed-by: default avatarKeishi Hattori <keishi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662958}
parent 0b0b9e45
...@@ -112,7 +112,7 @@ void HTMLButtonElement::DefaultEventHandler(Event& event) { ...@@ -112,7 +112,7 @@ void HTMLButtonElement::DefaultEventHandler(Event& event) {
if (event.type() == event_type_names::kDOMActivate && if (event.type() == event_type_names::kDOMActivate &&
!IsDisabledFormControl()) { !IsDisabledFormControl()) {
if (Form() && type_ == SUBMIT) { if (Form() && type_ == SUBMIT) {
Form()->PrepareForSubmission(event, this); Form()->PrepareForSubmission(&event, this);
event.SetDefaultHandled(); event.SetDefaultHandled();
} }
if (Form() && type_ == RESET) { if (Form() && type_ == RESET) {
......
...@@ -212,7 +212,7 @@ void HTMLFormElement::SubmitImplicitly(Event& event, ...@@ -212,7 +212,7 @@ void HTMLFormElement::SubmitImplicitly(Event& event,
} }
} }
if (from_implicit_submission_trigger && submission_trigger_count == 1) if (from_implicit_submission_trigger && submission_trigger_count == 1)
PrepareForSubmission(event, nullptr); PrepareForSubmission(&event, nullptr);
} }
bool HTMLFormElement::ValidateInteractively() { bool HTMLFormElement::ValidateInteractively() {
...@@ -258,7 +258,7 @@ bool HTMLFormElement::ValidateInteractively() { ...@@ -258,7 +258,7 @@ bool HTMLFormElement::ValidateInteractively() {
} }
void HTMLFormElement::PrepareForSubmission( void HTMLFormElement::PrepareForSubmission(
Event& event, Event* event,
HTMLFormControlElement* submit_button) { HTMLFormControlElement* submit_button) {
LocalFrame* frame = GetDocument().GetFrame(); LocalFrame* frame = GetDocument().GetFrame();
if (!frame || is_submitting_ || in_user_js_submit_event_) if (!frame || is_submitting_ || in_user_js_submit_event_)
...@@ -327,7 +327,7 @@ void HTMLFormElement::PrepareForSubmission( ...@@ -327,7 +327,7 @@ void HTMLFormElement::PrepareForSubmission(
} }
if (should_submit) { if (should_submit) {
planned_navigation_ = nullptr; planned_navigation_ = nullptr;
Submit(&event, submit_button); Submit(event, submit_button);
} }
if (!planned_navigation_) if (!planned_navigation_)
return; return;
...@@ -340,6 +340,39 @@ void HTMLFormElement::submitFromJavaScript() { ...@@ -340,6 +340,39 @@ void HTMLFormElement::submitFromJavaScript() {
Submit(nullptr, nullptr); Submit(nullptr, nullptr);
} }
void HTMLFormElement::requestSubmit(ExceptionState& exception_state) {
requestSubmit(nullptr, exception_state);
}
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit
void HTMLFormElement::requestSubmit(HTMLElement* submitter,
ExceptionState& exception_state) {
HTMLFormControlElement* control = nullptr;
// 1. If submitter was given, then:
if (submitter) {
// 1.1. If submitter is not a submit button, then throw a TypeError.
control = ToHTMLFormControlElementOrNull(submitter);
// button[type] is a subset of input[type]. So it's ok to compare button's
// type and input_type_names.
if (!control || (control->type() != input_type_names::kSubmit &&
control->type() != input_type_names::kImage)) {
exception_state.ThrowTypeError(
"The specified element is not a submit button.");
return;
}
// 1.2. If submitter's form owner is not this form element, then throw a
// "NotFoundError" DOMException.
if (control->formOwner() != this) {
exception_state.ThrowDOMException(
DOMExceptionCode::kNotFoundError,
"The specified element is not owned by this form element.");
return;
}
}
// 3. Submit this form element, from submitter.
PrepareForSubmission(nullptr, control);
}
void HTMLFormElement::SubmitDialog(FormSubmission* form_submission) { void HTMLFormElement::SubmitDialog(FormSubmission* form_submission) {
for (Node* node = this; node; node = node->ParentOrShadowHostNode()) { for (Node* node = this; node; node = node->ParentOrShadowHostNode()) {
if (auto* dialog = ToHTMLDialogElementOrNull(*node)) { if (auto* dialog = ToHTMLDialogElementOrNull(*node)) {
......
...@@ -74,8 +74,10 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement { ...@@ -74,8 +74,10 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
void Disassociate(HTMLImageElement&); void Disassociate(HTMLImageElement&);
void DidAssociateByParser(); void DidAssociateByParser();
void PrepareForSubmission(Event&, HTMLFormControlElement* submit_button); void PrepareForSubmission(Event*, HTMLFormControlElement* submit_button);
void submitFromJavaScript(); void submitFromJavaScript();
void requestSubmit(ExceptionState& exception_state);
void requestSubmit(HTMLElement* submitter, ExceptionState& exception_state);
void reset(); void reset();
void SubmitImplicitly(Event&, bool from_implicit_submission_trigger); void SubmitImplicitly(Event&, bool from_implicit_submission_trigger);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
[NotEnumerable] getter (RadioNodeList or Element) (DOMString name); [NotEnumerable] getter (RadioNodeList or Element) (DOMString name);
[ImplementedAs=submitFromJavaScript] void submit(); [ImplementedAs=submitFromJavaScript] void submit();
[RaisesException] void requestSubmit(optional HTMLElement submitter);
[CEReactions, CustomElementCallbacks] void reset(); [CEReactions, CustomElementCallbacks] void reset();
boolean checkValidity(); boolean checkValidity();
boolean reportValidity(); boolean reportValidity();
......
...@@ -101,8 +101,8 @@ void ImageInputType::HandleDOMActivateEvent(Event& event) { ...@@ -101,8 +101,8 @@ void ImageInputType::HandleDOMActivateEvent(Event& event) {
if (GetElement().IsDisabledFormControl() || !GetElement().Form()) if (GetElement().IsDisabledFormControl() || !GetElement().Form())
return; return;
click_location_ = ExtractClickLocation(event); click_location_ = ExtractClickLocation(event);
GetElement().Form()->PrepareForSubmission( // Event handlers can run.
event, &GetElement()); // Event handlers can run. GetElement().Form()->PrepareForSubmission(&event, &GetElement());
event.SetDefaultHandled(); event.SetDefaultHandled();
} }
......
...@@ -64,8 +64,8 @@ bool SubmitInputType::SupportsRequired() const { ...@@ -64,8 +64,8 @@ bool SubmitInputType::SupportsRequired() const {
void SubmitInputType::HandleDOMActivateEvent(Event& event) { void SubmitInputType::HandleDOMActivateEvent(Event& event) {
if (GetElement().IsDisabledFormControl() || !GetElement().Form()) if (GetElement().IsDisabledFormControl() || !GetElement().Form())
return; return;
GetElement().Form()->PrepareForSubmission( // Event handlers can run.
event, &GetElement()); // Event handlers can run. GetElement().Form()->PrepareForSubmission(&event, &GetElement());
event.SetDefaultHandled(); event.SetDefaultHandled();
} }
......
This is a testharness.js-based test.
PASS Passing an element which is not a submit button should throw
FAIL Passing a submit button not owned by the context object should throw assert_throws: function "() => {
form.requestSubmit(submitButton);
}" threw object "TypeError: form.requestSubmit is not a function" that is not a DOMException NotFoundError: property "code" is equal to undefined, expected 8
FAIL requestSubmit() should accept button[type=submit], input[type=submit], and input[type=image] form.requestSubmit is not a function
FAIL requestSubmit() should trigger interactive form validation form.requestSubmit is not a function
FAIL requestSubmit() doesn't run form submission reentrantly form.requestSubmit is not a function
FAIL requestSubmit() doesn't run interactive validation reentrantly form.requestSubmit is not a function
FAIL requestSubmit() for a disconnected form should not submit the form form.requestSubmit is not a function
FAIL The value of the submitter should be appended, and form* attributes of the submitter should be handled. form.requestSubmit is not a function
Harness: the test ran to completion.
...@@ -504,6 +504,7 @@ html element form ...@@ -504,6 +504,7 @@ html element form
property name property name
property noValidate property noValidate
property reportValidity property reportValidity
property requestSubmit
property reset property reset
property submit property submit
property target property target
......
...@@ -2427,6 +2427,7 @@ interface HTMLFormElement : HTMLElement ...@@ -2427,6 +2427,7 @@ interface HTMLFormElement : HTMLElement
method checkValidity method checkValidity
method constructor method constructor
method reportValidity method reportValidity
method requestSubmit
method reset method reset
method submit method submit
setter acceptCharset setter acceptCharset
......
...@@ -567,6 +567,7 @@ html element form ...@@ -567,6 +567,7 @@ html element form
property name property name
property noValidate property noValidate
property reportValidity property reportValidity
property requestSubmit
property reset property reset
property submit property submit
property target property target
......
...@@ -2990,6 +2990,7 @@ interface HTMLFormElement : HTMLElement ...@@ -2990,6 +2990,7 @@ interface HTMLFormElement : HTMLElement
method checkValidity method checkValidity
method constructor method constructor
method reportValidity method reportValidity
method requestSubmit
method reset method reset
method submit method submit
setter acceptCharset setter acceptCharset
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment