diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index c32b5f83082f..a70f2ccb0db5 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -995,7 +995,6 @@ nsresult EventDispatcher::Dispatch(EventTarget* aTarget, if (preVisitor.mWantsActivationBehavior) { MOZ_ASSERT(&chain[0] == targetEtci); activationTargetItemIndex.emplace(0); - preVisitor.mEvent->mFlags.mMultiplePreActionsPrevented = true; } if (!preVisitor.mCanHandle) { @@ -1065,7 +1064,6 @@ nsresult EventDispatcher::Dispatch(EventTarget* aTarget, activationTargetItemIndex.isNothing() && aEvent->mFlags.mBubbles) { MOZ_ASSERT(&chain.LastElement() == parentEtci); activationTargetItemIndex.emplace(chain.Length() - 1); - preVisitor.mEvent->mFlags.mMultiplePreActionsPrevented = true; } if (preVisitor.mCanHandle) { diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp index fc5f3b779a1d..3343da4fe417 100644 --- a/dom/html/HTMLButtonElement.cpp +++ b/dom/html/HTMLButtonElement.cpp @@ -172,21 +172,25 @@ void HTMLButtonElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { if (outerActivateEvent) { aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT; - if (mType == FormControlType::ButtonSubmit && mForm && - !aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented) { - aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented = true; - aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK; - aVisitor.mItemData = static_cast(mForm); - // tell the form that we are about to enter a click handler. - // that means that if there are scripted submissions, the - // latest one will be deferred until after the exit point of the handler. - mForm->OnSubmitClickBegin(this); - } + aVisitor.mWantsActivationBehavior = true; } nsGenericHTMLElement::GetEventTargetParent(aVisitor); } +void HTMLButtonElement::LegacyPreActivationBehavior( + EventChainVisitor& aVisitor) { + // out-of-spec legacy pre-activation behavior needed because of bug 1803805 + if (mType == FormControlType::ButtonSubmit && mForm) { + aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK; + aVisitor.mItemData = static_cast(mForm); + // tell the form that we are about to enter a click handler. + // that means that if there are scripted submissions, the + // latest one will be deferred until after the exit point of the handler. + mForm->OnSubmitClickBegin(this); + } +} + nsresult HTMLButtonElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { nsresult rv = NS_OK; if (!aVisitor.mPresContext) { @@ -223,24 +227,19 @@ nsresult HTMLButtonElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { HandleKeyboardActivation(aVisitor); } - if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) { - if (mForm) { - // Hold a strong ref while dispatching - RefPtr form(mForm); - if (mType == FormControlType::ButtonReset) { - form->MaybeReset(this); - aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; - } else if (mType == FormControlType::ButtonSubmit) { - form->MaybeSubmit(this); - aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; - } - // https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-type-button-state - // NS_FORM_BUTTON_BUTTON do nothing. - } - HandlePopoverTargetAction(); + // Bug 1459231: Temporarily needed till links respect activation target + // Then also remove NS_OUTER_ACTIVATE_EVENT + if ((aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) && mForm && + (mType == FormControlType::ButtonReset || + mType == FormControlType::ButtonSubmit)) { + aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true; } } + return rv; +} + +void EndSubmitClick(EventChainVisitor& aVisitor) { if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK)) { nsCOMPtr content(do_QueryInterface(aVisitor.mItemData)); RefPtr form = HTMLFormElement::FromNodeOrNull(content); @@ -257,8 +256,40 @@ nsresult HTMLButtonElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { // Note, NS_IN_SUBMIT_CLICK is set only when we're in outer activate event. form->FlushPendingSubmission(); } +} - return rv; +void HTMLButtonElement::ActivationBehavior(EventChainPostVisitor& aVisitor) { + if (!aVisitor.mPresContext) { + // Should check whether EndSubmitClick is needed here. + return; + } + + if (!IsDisabled()) { + if (mForm) { + // Hold a strong ref while dispatching + RefPtr form(mForm); + if (mType == FormControlType::ButtonReset) { + form->MaybeReset(this); + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; + } else if (mType == FormControlType::ButtonSubmit) { + form->MaybeSubmit(this); + aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; + } + // https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-type-button-state + // NS_FORM_BUTTON_BUTTON do nothing. + } + HandlePopoverTargetAction(); + } + + EndSubmitClick(aVisitor); +} + +void HTMLButtonElement::LegacyCanceledActivationBehavior( + EventChainPostVisitor& aVisitor) { + // still need to end submission, see bug 1803805 + // e.g. when parent element of button has event handler preventing default + // legacy canceled instead of activation behavior will be run + EndSubmitClick(aVisitor); } nsresult HTMLButtonElement::BindToTree(BindContext& aContext, diff --git a/dom/html/HTMLButtonElement.h b/dom/html/HTMLButtonElement.h index 15c00213d0d3..75839df7227d 100644 --- a/dom/html/HTMLButtonElement.h +++ b/dom/html/HTMLButtonElement.h @@ -53,6 +53,11 @@ class HTMLButtonElement final : public nsGenericHTMLFormControlElementWithState, void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; + void LegacyPreActivationBehavior(EventChainVisitor& aVisitor) override; + MOZ_CAN_RUN_SCRIPT + void ActivationBehavior(EventChainPostVisitor& aVisitor) override; + void LegacyCanceledActivationBehavior( + EventChainPostVisitor& aVisitor) override; // nsINode nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 082dff60cd1c..609a7bd93954 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -3125,8 +3125,7 @@ bool HTMLInputElement::CheckActivationBehaviorPreconditions( if (outerActivateEvent) { aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT; } - return outerActivateEvent && - !aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented; + return outerActivateEvent; } default: return false; diff --git a/testing/web-platform/meta/dom/events/Event-dispatch-single-activation-behavior.html.ini b/testing/web-platform/meta/dom/events/Event-dispatch-single-activation-behavior.html.ini index 7160d8c33d73..be6e34a1ce00 100644 --- a/testing/web-platform/meta/dom/events/Event-dispatch-single-activation-behavior.html.ini +++ b/testing/web-platform/meta/dom/events/Event-dispatch-single-activation-behavior.html.ini @@ -1,10 +1,4 @@ [Event-dispatch-single-activation-behavior.html] - [When clicking child
of parent , only child should be activated.] - expected: FAIL - - [When clicking child
of parent , only child should be activated.] - expected: FAIL - [When clicking child of parent , only child should be activated.] expected: FAIL @@ -38,47 +32,8 @@ [When clicking child of parent
, only child should be activated.] expected: FAIL - [When clicking child of parent , only child should be activated.] - expected: FAIL - - [When clicking child of parent
, only child should be activated.] - expected: FAIL - - [When clicking child of parent
, only child should be activated.] - expected: FAIL - - [When clicking child of parent
, only child should be activated.] - expected: FAIL - - [When clicking child of parent
, only child should be activated.] - expected: FAIL - - [When clicking child of parent
, only child should be activated.] - expected: FAIL - [When clicking child of parent , only child should be activated.] expected: FAIL [When clicking child of parent , only child should be activated.] expected: FAIL - - [When clicking child of parent , only child should be activated.] - expected: FAIL - - [When clicking child
of parent
, only child should be activated.] - expected: FAIL - - [When clicking child
of parent
, only child should be activated.] - expected: FAIL - - [When clicking child
of parent
, only child should be activated.] - expected: FAIL - - [When clicking child
of parent
, only child should be activated.] - expected: FAIL - - [When clicking child
of parent
, only child should be activated.] - expected: FAIL - - [When clicking child
of parent
, only child should be activated.] - expected: FAIL diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-click-submits.html b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-click-submits.html index f09d06080fbe..86b92402e468 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-click-submits.html +++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-click-submits.html @@ -198,7 +198,6 @@ async_test(t => { })); span.addEventListener("click", t.step_func(ev => { - ev.preventDefault(); t.step_timeout(() => t.done(), 500); })); @@ -207,4 +206,27 @@ async_test(t => { }, "clicking the child of a button by dispatching a non-bubbling event should not trigger submit"); +async_test(t => { + + const form = document.createElement("form"); + const button = document.createElement("button"); + button.disabled = true; + const span = document.createElement("span"); + button.appendChild(span); + form.appendChild(button); + document.body.appendChild(form); + + form.addEventListener("submit", t.step_func_done(ev => { + ev.preventDefault(); + assert_unreached("Form should not be submitted"); + })); + + span.addEventListener("click", t.step_func(ev => { + assert_true(true, "span was clicked"); + t.step_timeout(() => t.done(), 500); + })); + + span.click(); + +}, "clicking the child of a disabled button with .click() should not trigger submit"); diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-submit-children.html b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-submit-children.html index 06218f4fc9e9..9cec2bd87586 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-submit-children.html +++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-submit-children.html @@ -7,11 +7,13 @@
- +
+ +
diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h index 04711fad54a5..b3707f1cf4d5 100644 --- a/widget/BasicEvents.h +++ b/widget/BasicEvents.h @@ -99,8 +99,6 @@ struct BaseEventFlags { // the first