Do not dispatch 'change' event if the INPUT value is not changed.
This CL fixes two problems.
* When the INPUT type is changed, m_textAsOfLastFormControlChangeEvent is not
initialized correctly. So, we dispatched unexpected change events.
* When readonly/disabled state is changed, we call
SpinButtonElement::releaseCapture(), which can dispatch a 'change' event. Its
callsite should protect |this|.
BUG=454231,455193
Review URL: https://codereview.chromium.org/880473005
git-svn-id: svn://svn.chromium.org/blink/trunk@189774 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-disabled-crash-expected.txt b/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-disabled-crash-expected.txt
new file mode 100644
index 0000000..018565b
--- /dev/null
+++ b/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-disabled-crash-expected.txt
@@ -0,0 +1,11 @@
+CONSOLE WARNING: The specified value 'a' does not conform to the required format, 'yyyy-MM-dd'.
+Date input with invalid initial value should not dispatch a change event on disabled=true, and should not crash.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS changeEventCounter is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-disabled-crash.html b/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-disabled-crash.html
new file mode 100644
index 0000000..9e13e91
--- /dev/null
+++ b/LayoutTests/fast/forms/date-multiple-fields/date-multiple-fields-disabled-crash.html
@@ -0,0 +1,20 @@
+<body>
+<script src="../../../resources/js-test.js"></script>
+<form>
+<input value="a" id="input1">
+</form>
+<script>
+description('Date input with invalid initial value should not dispatch a change event on disabled=true, and should not crash.');
+var changeEventCounter = 0;
+var input1 = document.querySelector('#input1');
+input1.type = 'date';
+input1.addEventListener('change', function handleChange() {
+ ++changeEventCounter;
+ input1.removeEventListener('change', handleChange);
+ input1.type = 'search';
+}, false);
+input1.disabled = true;
+shouldBe('changeEventCounter', '0');
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/forms/number/number-change-event-by-readonly-expected.txt b/LayoutTests/fast/forms/number/number-change-event-by-readonly-expected.txt
new file mode 100644
index 0000000..20580981
--- /dev/null
+++ b/LayoutTests/fast/forms/number/number-change-event-by-readonly-expected.txt
@@ -0,0 +1,10 @@
+Read-only number input should not dispatch a change event.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS changeEventCounter is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/number/number-change-event-by-readonly.html b/LayoutTests/fast/forms/number/number-change-event-by-readonly.html
new file mode 100644
index 0000000..e092a99
--- /dev/null
+++ b/LayoutTests/fast/forms/number/number-change-event-by-readonly.html
@@ -0,0 +1,11 @@
+<script src="../../../resources/js-test.js"></script>
+<script>
+description('Read-only number input should not dispatch a change event.');
+var changeEventCounter = 0;
+function handleChange() {
+ ++changeEventCounter;
+}
+var parent = document.createElement('div');
+parent.innerHTML = '<input type="number" value="0" onchange="handleChange()" readonly>';
+shouldBe('changeEventCounter', '0');
+</script>
diff --git a/Source/core/html/HTMLInputElement.cpp b/Source/core/html/HTMLInputElement.cpp
index 2385f43..7fe7b74 100644
--- a/Source/core/html/HTMLInputElement.cpp
+++ b/Source/core/html/HTMLInputElement.cpp
@@ -444,6 +444,8 @@
m_inputType->warnIfValueIsInvalid(fastGetAttribute(valueAttr).string());
m_inputTypeView->updateView();
+ setTextAsOfLastFormControlChangeEvent(value());
+ setChangedSinceLastFormControlChangeEvent(false);
}
void HTMLInputElement::updateType()
@@ -508,6 +510,7 @@
if (document().focusedElement() == this)
document().updateFocusAppearanceSoon(true /* restore selection */);
+ setTextAsOfLastFormControlChangeEvent(value());
setChangedSinceLastFormControlChangeEvent(false);
addToRadioButtonGroup();
diff --git a/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp b/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
index c76f9f6..4088373 100644
--- a/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
+++ b/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp
@@ -419,6 +419,7 @@
void BaseMultipleFieldsDateAndTimeInputType::disabledAttributeChanged()
{
+ EventQueueScope scope;
spinButtonElement()->releaseCapture();
if (DateTimeEditElement* edit = dateTimeEditElement())
edit->disabledStateChanged();
@@ -464,6 +465,7 @@
void BaseMultipleFieldsDateAndTimeInputType::readonlyAttributeChanged()
{
+ EventQueueScope scope;
spinButtonElement()->releaseCapture();
if (DateTimeEditElement* edit = dateTimeEditElement())
edit->readOnlyStateChanged();