Bug 1588715 - Implement SubmitEvent; r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D62030

--HG--
extra : moz-landing-system : lando
This commit is contained in:
John Dai 2020-02-11 12:46:54 +00:00
Родитель 338c49f1f0
Коммит 5683fcf7c8
10 изменённых файлов: 67 добавлений и 108 удалений

Просмотреть файл

@ -344,6 +344,10 @@ const kEventConstructors = {
}, },
chromeOnly: true, chromeOnly: true,
}, },
SubmitEvent: { create (aName, aProps) {
return new SubmitEvent(aName, aProps);
},
},
TCPSocketErrorEvent: { create(aName, aProps) { TCPSocketErrorEvent: { create(aName, aProps) {
return new TCPSocketErrorEvent(aName, aProps); return new TCPSocketErrorEvent(aName, aProps);
}, },

Просмотреть файл

@ -41,6 +41,7 @@
#include "HTMLFormSubmissionConstants.h" #include "HTMLFormSubmissionConstants.h"
#include "mozilla/dom/FormData.h" #include "mozilla/dom/FormData.h"
#include "mozilla/dom/FormDataEvent.h" #include "mozilla/dom/FormDataEvent.h"
#include "mozilla/dom/SubmitEvent.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "nsIFormSubmitObserver.h" #include "nsIFormSubmitObserver.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
@ -260,10 +261,16 @@ void HTMLFormElement::MaybeSubmit(Element* aSubmitter) {
// dispatch the event. It makes sure that event is not handled if the window // dispatch the event. It makes sure that event is not handled if the window
// is being destroyed. // is being destroyed.
if (RefPtr<PresShell> presShell = doc->GetPresShell()) { if (RefPtr<PresShell> presShell = doc->GetPresShell()) {
InternalFormEvent event(true, eFormSubmit); SubmitEventInit init;
event.mOriginator = aSubmitter; init.mBubbles = true;
init.mCancelable = true;
init.mSubmitter =
aSubmitter ? nsGenericHTMLElement::FromNode(aSubmitter) : nullptr;
RefPtr<SubmitEvent> event =
SubmitEvent::Constructor(this, NS_LITERAL_STRING("submit"), init);
event->SetTrusted(true);
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
presShell->HandleDOMEventWithTarget(this, &event, &status); presShell->HandleDOMEventWithTarget(this, event, &status);
} }
} }
@ -290,7 +297,7 @@ void HTMLFormElement::Submit(ErrorResult& aRv) {
mPendingSubmission = nullptr; mPendingSubmission = nullptr;
} }
aRv = DoSubmitOrReset(nullptr, eFormSubmit); aRv = DoSubmit();
} }
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit // https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit
@ -541,9 +548,12 @@ nsresult HTMLFormElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
if (aVisitor.mEventStatus == nsEventStatus_eIgnore) { if (aVisitor.mEventStatus == nsEventStatus_eIgnore) {
switch (msg) { switch (msg) {
case eFormReset: case eFormReset: {
DoReset();
break;
}
case eFormSubmit: { case eFormSubmit: {
if (mPendingSubmission && msg == eFormSubmit) { if (mPendingSubmission) {
// tell the form to forget a possible pending submission. // tell the form to forget a possible pending submission.
// the reason is that the script returned true (the event was // the reason is that the script returned true (the event was
// ignored) so if there is a stored submission, it will miss // ignored) so if there is a stored submission, it will miss
@ -551,7 +561,7 @@ nsresult HTMLFormElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
// to forget it and the form element will build a new one // to forget it and the form element will build a new one
mPendingSubmission = nullptr; mPendingSubmission = nullptr;
} }
DoSubmitOrReset(aVisitor.mEvent, msg); DoSubmit(aVisitor.mDOMEvent);
break; break;
} }
default: default:
@ -576,36 +586,13 @@ nsresult HTMLFormElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
return NS_OK; return NS_OK;
} }
nsresult HTMLFormElement::DoSubmitOrReset(WidgetEvent* aEvent, nsresult HTMLFormElement::DoReset() {
EventMessage aMessage) {
// Make sure the presentation is up-to-date // Make sure the presentation is up-to-date
Document* doc = GetComposedDoc(); Document* doc = GetComposedDoc();
if (doc) { if (doc) {
doc->FlushPendingNotifications(FlushType::ContentAndNotify); doc->FlushPendingNotifications(FlushType::ContentAndNotify);
} }
// JBK Don't get form frames anymore - bug 34297
// Submit or Reset the form
if (eFormReset == aMessage) {
return DoReset();
}
if (eFormSubmit == aMessage) {
// Don't submit if we're not in a document or if we're in
// a sandboxed frame and form submit is disabled.
if (mIsConstructingEntryList || !doc ||
(doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
return NS_OK;
}
return DoSubmit(aEvent);
}
MOZ_ASSERT(false);
return NS_OK;
}
nsresult HTMLFormElement::DoReset() {
mEverTriedInvalidSubmit = false; mEverTriedInvalidSubmit = false;
// JBK walk the elements[] array instead of form frame controls - bug 34297 // JBK walk the elements[] array instead of form frame controls - bug 34297
uint32_t numElements = GetElementCount(); uint32_t numElements = GetElementCount();
@ -626,8 +613,21 @@ nsresult HTMLFormElement::DoReset() {
return rv; \ return rv; \
} }
nsresult HTMLFormElement::DoSubmit(WidgetEvent* aEvent) { nsresult HTMLFormElement::DoSubmit(Event* aEvent) {
NS_ASSERTION(GetComposedDoc(), "Should never get here without a current doc"); Document* doc = GetComposedDoc();
NS_ASSERTION(doc, "Should never get here without a current doc");
// Make sure the presentation is up-to-date
if (doc) {
doc->FlushPendingNotifications(FlushType::ContentAndNotify);
}
// Don't submit if we're not in a document or if we're in
// a sandboxed frame and form submit is disabled.
if (mIsConstructingEntryList || !doc ||
(doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
return NS_OK;
}
if (mIsSubmitting) { if (mIsSubmitting) {
NS_WARNING("Preventing double form submission"); NS_WARNING("Preventing double form submission");
@ -685,21 +685,15 @@ nsresult HTMLFormElement::DoSubmit(WidgetEvent* aEvent) {
} }
nsresult HTMLFormElement::BuildSubmission(HTMLFormSubmission** aFormSubmission, nsresult HTMLFormElement::BuildSubmission(HTMLFormSubmission** aFormSubmission,
WidgetEvent* aEvent) { Event* aEvent) {
NS_ASSERTION(!mPendingSubmission, "tried to build two submissions!"); NS_ASSERTION(!mPendingSubmission, "tried to build two submissions!");
// Get the originating frame (failure is non-fatal) // Get the originating frame
nsGenericHTMLElement* originatingElement = nullptr; nsGenericHTMLElement* originatingElement = nullptr;
if (aEvent) { if (aEvent) {
InternalFormEvent* formEvent = aEvent->AsFormEvent(); SubmitEvent* submitEvent = aEvent->AsSubmitEvent();
if (formEvent) { if (submitEvent) {
nsIContent* originator = formEvent->mOriginator; originatingElement = submitEvent->GetSubmitter();
if (originator) {
if (!originator->IsHTMLElement()) {
return NS_ERROR_UNEXPECTED;
}
originatingElement = static_cast<nsGenericHTMLElement*>(originator);
}
} }
} }

Просмотреть файл

@ -430,7 +430,6 @@ class HTMLFormElement final : public nsGenericHTMLElement,
RefPtr<HTMLFormElement> mForm; RefPtr<HTMLFormElement> mForm;
}; };
nsresult DoSubmitOrReset(WidgetEvent* aEvent, EventMessage aMessage);
nsresult DoReset(); nsresult DoReset();
// Async callback to handle removal of our default submit // Async callback to handle removal of our default submit
@ -442,12 +441,11 @@ class HTMLFormElement final : public nsGenericHTMLElement,
// //
/** /**
* Attempt to submit (submission might be deferred) * Attempt to submit (submission might be deferred)
* (called by DoSubmitOrReset)
* *
* @param aPresContext the presentation context * @param aPresContext the presentation context
* @param aEvent the DOM event that was passed to us for the submit * @param aEvent the DOM event that was passed to us for the submit
*/ */
nsresult DoSubmit(WidgetEvent* aEvent); nsresult DoSubmit(Event* aEvent = nullptr);
/** /**
* Prepare the submission object (called by DoSubmit) * Prepare the submission object (called by DoSubmit)
@ -455,8 +453,7 @@ class HTMLFormElement final : public nsGenericHTMLElement,
* @param aFormSubmission the submission object * @param aFormSubmission the submission object
* @param aEvent the DOM event that was passed to us for the submit * @param aEvent the DOM event that was passed to us for the submit
*/ */
nsresult BuildSubmission(HTMLFormSubmission** aFormSubmission, nsresult BuildSubmission(HTMLFormSubmission** aFormSubmission, Event* aEvent);
WidgetEvent* aEvent);
/** /**
* Perform the submission (called by DoSubmit and FlushPendingSubmission) * Perform the submission (called by DoSubmit and FlushPendingSubmission)
* *

Просмотреть файл

@ -1052,6 +1052,8 @@ var interfaceNamesInGlobalScope = [
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "SubtleCrypto", insecureContext: true }, { name: "SubtleCrypto", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "SubmitEvent", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "SVGAElement", insecureContext: true }, { name: "SVGAElement", insecureContext: true },
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "SVGAngle", insecureContext: true }, { name: "SVGAngle", insecureContext: true },

Просмотреть файл

@ -0,0 +1,19 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submitevent
*/
[Exposed=Window]
interface SubmitEvent : Event {
constructor(DOMString type, optional SubmitEventInit eventInitDict = {});
readonly attribute HTMLElement? submitter;
};
dictionary SubmitEventInit : EventInit {
HTMLElement? submitter = null;
};

Просмотреть файл

@ -1085,6 +1085,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
'ScrollViewChangeEvent.webidl', 'ScrollViewChangeEvent.webidl',
'SecurityPolicyViolationEvent.webidl', 'SecurityPolicyViolationEvent.webidl',
'StyleSheetApplicableStateChangeEvent.webidl', 'StyleSheetApplicableStateChangeEvent.webidl',
'SubmitEvent.webidl',
'TCPServerSocketEvent.webidl', 'TCPServerSocketEvent.webidl',
'TCPSocketErrorEvent.webidl', 'TCPSocketErrorEvent.webidl',
'TCPSocketEvent.webidl', 'TCPSocketEvent.webidl',

Просмотреть файл

@ -723,28 +723,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.expe
[FormDataEvent interface object length] [FormDataEvent interface object length]
expected: FAIL expected: FAIL
[SubmitEvent interface: attribute submitter]
expected: FAIL
[SubmitEvent interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[SubmitEvent interface object length]
expected: FAIL
[SubmitEvent interface: existence and properties of interface prototype object]
expected: FAIL
[SubmitEvent interface: existence and properties of interface object]
expected: FAIL
[SubmitEvent interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[SubmitEvent interface object name]
expected: FAIL
[idlharness.https.html?include=(Document|Window)] [idlharness.https.html?include=(Document|Window)]
[Document interface: documentWithHandlers must inherit property "onsecuritypolicyviolation" with the proper type] [Document interface: documentWithHandlers must inherit property "onsecuritypolicyviolation" with the proper type]
expected: FAIL expected: FAIL

Просмотреть файл

@ -1,19 +0,0 @@
[SubmitEvent.window.html]
[Successful SubmitEvent constructor]
expected: FAIL
[Failing SubmitEvent constructor]
expected: FAIL
[Successful SubmitEvent constructor; empty dictionary]
expected: FAIL
[Successful SubmitEvent constructor; missing dictionary]
expected: FAIL
[Successful SubmitEvent constructor; null/undefined submitter]
expected: FAIL
[Successful SubmitEvent constructor; null/undefined dictionary]
expected: FAIL

Просмотреть файл

@ -1,13 +0,0 @@
[form-submission-algorithm.html]
[firing an event named submit; form.requestSubmit(submitter)]
expected: FAIL
[firing an event named submit; clicking a submit button]
expected: FAIL
[firing an event named submit; form.requestSubmit(null)]
expected: FAIL
[firing an event named submit; form.requestSubmit()]
expected: FAIL

Просмотреть файл

@ -1,7 +1,3 @@
[implicit-submission.optional.html] [implicit-submission.optional.html]
[Submit event with a submit button] [Submit event with a submit button]
expected: FAIL expected: FAIL
[Submit event with no submit button]
expected: FAIL