diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp
index 1bbc0ceef822..39eb716ba49e 100644
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2071,6 +2071,7 @@ bool nsGenericHTMLFormElement::IsElementDisabledForEvents(WidgetEvent* aEvent,
case eAnimationEnd:
case eAnimationIteration:
case eAnimationCancel:
+ case eFormChange:
case eMouseMove:
case eMouseOver:
case eMouseOut:
@@ -2093,6 +2094,10 @@ bool nsGenericHTMLFormElement::IsElementDisabledForEvents(WidgetEvent* aEvent,
break;
}
+ if (aEvent->mSpecifiedEventType == nsGkAtoms::oninput) {
+ return false;
+ }
+
// FIXME(emilio): This poking at the style of the frame is slightly bogus
// unless we flush before every event, which we don't really want to do.
if (aFrame && aFrame->StyleUI()->mUserInput == StyleUserInput::None) {
diff --git a/testing/web-platform/tests/dom/events/Event-dispatch-click.html b/testing/web-platform/tests/dom/events/Event-dispatch-click.html
index bbc408df8825..a92bde13d247 100644
--- a/testing/web-platform/tests/dom/events/Event-dispatch-click.html
+++ b/testing/web-platform/tests/dom/events/Event-dispatch-click.html
@@ -289,6 +289,23 @@ test(t => {
assert_false(input.checked);
}, `disabled radio should get legacy-canceled-activation behavior 2`);
+for (const type of ["checkbox", "radio"]) {
+ for (const handler of ["oninput", "onchange"]) {
+ async_test(t => {
+ const input = document.createElement("input");
+ input.type = type;
+ input.onclick = t.step_func(ev => {
+ input.disabled = true;
+ });
+ input[handler] = t.step_func(ev => {
+ assert_equals(input.checked, true);
+ t.done();
+ });
+ input.click();
+ }, `disabling ${type} in onclick listener shouldn't suppress ${handler}`);
+ }
+}
+
async_test(function(t) {
var form = document.createElement("form")
var didSubmit = false