Bug 1368888 - Don't get previous value twice in input.value setter. r=smaug

We get previous input.value twice in HTMLInputElement::SetValue and nsTextEditorState::SetValue when setting input.value.  Since nsTextEditorState::GetValue uses DocumentEncoder, it is expensive.  So we should use old value as parameter of nsTextEditorState::SetValue if possible.

MozReview-Commit-ID: A1UPfETTVCn

--HG--
extra : rebase_source : f751289b42b4d9d5c389042f688c53bde47d1620
This commit is contained in:
Makoto Kato 2017-06-14 18:21:01 +09:00
Родитель 4de4243edc
Коммит 23c3e741f1
4 изменённых файлов: 53 добавлений и 7 удалений

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

@ -1873,8 +1873,12 @@ HTMLInputElement::SetValue(const nsAString& aValue, CallerType aCallerType,
nsAutoString currentValue;
GetValue(currentValue, aCallerType);
// Some types sanitize value, so GetValue doesn't return pure
// previous value correctly.
nsresult rv =
SetValueInternal(aValue,
(IsExperimentalMobileType(mType) || IsDateTimeInputType(mType)) ?
nullptr : &currentValue,
nsTextEditorState::eSetValue_ByContent |
nsTextEditorState::eSetValue_Notify |
nsTextEditorState::eSetValue_MoveCursorToEndIfValueChanged);
@ -3032,7 +3036,9 @@ HTMLInputElement::UpdateFileList()
}
nsresult
HTMLInputElement::SetValueInternal(const nsAString& aValue, uint32_t aFlags)
HTMLInputElement::SetValueInternal(const nsAString& aValue,
const nsAString* aOldValue,
uint32_t aFlags)
{
NS_PRECONDITION(GetValueMode() != VALUE_MODE_FILENAME,
"Don't call SetValueInternal for file inputs");
@ -3056,7 +3062,7 @@ HTMLInputElement::SetValueInternal(const nsAString& aValue, uint32_t aFlags)
}
if (IsSingleLineTextControl(false)) {
if (!mInputData.mState->SetValue(value, aFlags)) {
if (!mInputData.mState->SetValue(value, aOldValue, aFlags)) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (mType == NS_FORM_INPUT_EMAIL) {

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

@ -942,9 +942,19 @@ protected:
* Setting the value.
*
* @param aValue String to set.
* @param aOldValue Previous value before setting aValue.
If previous value is unknown, aOldValue can be nullptr.
* @param aFlags See nsTextEditorState::SetValueFlags.
*/
nsresult SetValueInternal(const nsAString& aValue, uint32_t aFlags);
nsresult SetValueInternal(const nsAString& aValue,
const nsAString* aOldValue,
uint32_t aFlags);
nsresult SetValueInternal(const nsAString& aValue,
uint32_t aFlags)
{
return SetValueInternal(aValue, nullptr, aFlags);
}
// Generic getter for the value that doesn't do experimental control type
// sanitization.

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

@ -2492,7 +2492,8 @@ nsTextEditorState::GetValue(nsAString& aValue, bool aIgnoreWrap) const
}
bool
nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
nsTextEditorState::SetValue(const nsAString& aValue, const nsAString* aOldValue,
uint32_t aFlags)
{
nsAutoString newValue(aValue);
@ -2505,6 +2506,9 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
// mIsCommittingComposition is set false. See below.
if (mIsCommittingComposition) {
mValueBeingSet = aValue;
// GetValue doesn't return current text frame's content during committing.
// So we cannot trust this old value
aOldValue = nullptr;
}
// Note that if this may be called during reframe of the editor. In such
@ -2525,7 +2529,15 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
// If setting value won't change current value, we shouldn't commit
// composition for compatibility with the other browsers.
nsAutoString currentValue;
mBoundFrame->GetText(currentValue);
if (aOldValue) {
#ifdef DEBUG
mBoundFrame->GetText(currentValue);
MOZ_ASSERT(currentValue.Equals(*aOldValue));
#endif
currentValue.Assign(*aOldValue);
} else {
mBoundFrame->GetText(currentValue);
}
if (newValue == currentValue) {
// Note that in this case, we shouldn't fire any events with setting
// value because event handlers may try to set value recursively but
@ -2533,6 +2545,9 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
// script (see below).
return true;
}
// IME might commit composition, then change value, so we cannot
// trust old value from parameter.
aOldValue = nullptr;
}
// If there is composition, need to commit composition first because
// other browsers do that.
@ -2593,7 +2608,15 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
#endif
nsAutoString currentValue;
mBoundFrame->GetText(currentValue);
if (aOldValue) {
#ifdef DEBUG
mBoundFrame->GetText(currentValue);
MOZ_ASSERT(currentValue.Equals(*aOldValue));
#endif
currentValue.Assign(*aOldValue);
} else {
mBoundFrame->GetText(currentValue);
}
AutoWeakFrame weakFrame(mBoundFrame);

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

@ -179,7 +179,14 @@ public:
// not changed the cursor won't move.
eSetValue_MoveCursorToEndIfValueChanged = 1 << 3,
};
MOZ_MUST_USE bool SetValue(const nsAString& aValue, uint32_t aFlags);
MOZ_MUST_USE bool SetValue(const nsAString& aValue,
const nsAString* aOldValue,
uint32_t aFlags);
MOZ_MUST_USE bool SetValue(const nsAString& aValue,
uint32_t aFlags)
{
return SetValue(aValue, nullptr, aFlags);
}
void GetValue(nsAString& aValue, bool aIgnoreWrap) const;
bool HasNonEmptyValue();
// The following methods are for textarea element to use whether default