diff --git a/dom/bindings/Errors.msg b/dom/bindings/Errors.msg index db689e5bc0..a2661597b3 100644 --- a/dom/bindings/Errors.msg +++ b/dom/bindings/Errors.msg @@ -111,3 +111,4 @@ MSG_DEF(MSG_PMO_INVALID_MEMBERS, 0, JSEXN_TYPEERR, "PerformanceMeasureOptions ca MSG_DEF(MSG_PMO_CONSTRUCTOR_INACCESSIBLE, 0, JSEXN_TYPEERR, "Can't access PerformanceMark constructor, performance is null.") MSG_DEF(MSG_PMO_UNEXPECTED_START_TIME, 0, JSEXN_TYPEERR, "Expected startTime >= 0.") MSG_DEF(MSG_PMO_INVALID_ATTR_FOR_NON_GLOBAL, 1, JSEXN_TYPEERR, "Cannot get PerformanceTiming attribute values for non-Window global object. Given: {0}.") +MSG_DEF(MSG_NOT_SUBMIT_BUTTON, 0, JSEXN_TYPEERR, "The submitter is not a submit button.") diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index f44077c54e..a5f2442489 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -276,6 +276,41 @@ HTMLFormElement::Submit() return rv.StealNSResult(); } +// https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit +void +HTMLFormElement::RequestSubmit(nsGenericHTMLElement* aSubmitter, + ErrorResult& aRv) { + // 1. If submitter is not null, then: + if (aSubmitter) { + nsCOMPtr fc = do_QueryObject(aSubmitter); + + // 1.1. If submitter is not a submit button, then throw a TypeError. + if (!fc || !fc->IsSubmitControl()) { + aRv.ThrowTypeError(); + return; + } + + // 1.2. If submitter's form owner is not this form element, then throw a + // "NotFoundError" DOMException. + if (fc->GetFormElement() != this) { + aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); + return; + } + } + + // 2. Otherwise, set submitter to this form element. + // 3. Submit this form element, from submitter. + // We go through the presShell here for the corner case a submit event + // is pending while the window is being destroyed. + InternalFormEvent event(true, eFormSubmit); + event.mOriginator = aSubmitter; + nsEventStatus status = nsEventStatus_eIgnore; + nsCOMPtr presShell = GetComposedDoc()->GetShell(); + if (MOZ_LIKELY(presShell)) { + presShell->HandleDOMEventWithTarget(this, &event, &status); + } +} + NS_IMETHODIMP HTMLFormElement::Reset() { diff --git a/dom/html/HTMLFormElement.h b/dom/html/HTMLFormElement.h index b0d355d5a7..e752fd5a82 100644 --- a/dom/html/HTMLFormElement.h +++ b/dom/html/HTMLFormElement.h @@ -391,6 +391,19 @@ public: void Submit(ErrorResult& aRv); + /** + * Requests to submit the form. Unlike submit(), this method includes + * interactive constraint validation and firing a submit event, + * either of which can cancel submission. + * + * @param aSubmitter The submitter argument can be used to point to a specific + * submit button. + * @param aRv An ErrorResult. + * @see + * https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit + */ + void RequestSubmit(nsGenericHTMLElement* aSubmitter, ErrorResult& aRv); + // XPCOM Reset() is OK bool CheckValidity() diff --git a/dom/webidl/HTMLFormElement.webidl b/dom/webidl/HTMLFormElement.webidl index 064fe9fade..a1407a718e 100644 --- a/dom/webidl/HTMLFormElement.webidl +++ b/dom/webidl/HTMLFormElement.webidl @@ -43,6 +43,8 @@ interface HTMLFormElement : HTMLElement { [Throws] void submit(); + [Pref="dom.forms.requestsubmit.enabled", Throws] + void requestSubmit(optional HTMLElement? submitter = null); [CEReactions] void reset(); boolean checkValidity(); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index cd7b37dffb..5f7d02ac62 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1203,6 +1203,9 @@ pref("dom.forms.autocomplete.experimental", false); // Enables requestAutocomplete DOM API on forms. pref("dom.forms.requestAutocomplete", false); +// Enables requestSubmit DOM API on forms. +pref("dom.forms.requestsubmit.enabled", true); + // Enable Directory API. By default, disabled. pref("dom.input.dirpicker", false);