Bug 1640040 - Only handle updating the DOM state from TextControlState::SetValue on the outer caller. r=masayuki

The issue here is that AccessibleCaret flushes layout from the middle of
the SetValue call, because it hides the caret (see the call stack in
comment 11).

That changes the placeholder-shown state because it goes from empty to
non-empty but the SetValue call from UnbindFromFrame is not supposed to
change that state (because we're in the middle of restyling).

Call OnValueChanged later, at the outer caller instead.

Differential Revision: https://phabricator.services.mozilla.com/D85745
This commit is contained in:
Emilio Cobos Álvarez
2020-08-04 11:22:42 +00:00
parent 4c9ac50688
commit 4d216de887
3 changed files with 24 additions and 11 deletions

View File

@@ -2568,6 +2568,9 @@ bool TextControlState::SetValue(const nsAString& aValue,
aOldValue = nullptr;
}
const bool wasHandlingSetValue =
mHandlingState && mHandlingState->IsHandling(TextControlAction::SetValue);
ErrorResult error;
AutoTextControlHandlingState handlingSetValue(
*this, TextControlAction::SetValue, aValue, aOldValue, aFlags, error);
@@ -2646,25 +2649,23 @@ bool TextControlState::SetValue(const nsAString& aValue,
}
if (mTextEditor && mBoundFrame) {
AutoWeakFrame weakFrame(mBoundFrame);
if (!SetValueWithTextEditor(handlingSetValue)) {
return false;
}
if (!weakFrame.IsAlive()) {
return true;
}
} else if (!SetValueWithoutTextEditor(handlingSetValue)) {
return false;
}
// TODO(emilio): It seems wrong to pass ValueChangeKind::Script if
// BySetUserInput is in aFlags.
auto changeKind = (aFlags & eSetValue_Internal) ? ValueChangeKind::Internal
: ValueChangeKind::Script;
// If we were handling SetValue() before, don't update the DOM state twice,
// just let the outer call do so.
if (!wasHandlingSetValue) {
// TODO(emilio): It seems wrong to pass ValueChangeKind::Script if
// BySetUserInput is in aFlags.
auto changeKind = (aFlags & eSetValue_Internal) ? ValueChangeKind::Internal
: ValueChangeKind::Script;
handlingSetValue.GetTextControlElement()->OnValueChanged(changeKind);
handlingSetValue.GetTextControlElement()->OnValueChanged(changeKind);
}
return true;
}