Bug 1658302 - Don't reframe for changes to the placeholder attribute value. r=masayuki

We still reframe for additions / removals of the attribute because that
makes us create the placeholder <div>. We could avoid it if we created
it independently of the presence of the attribute but that seems like it
could regress perf for the case where there's no placeholder attribute,
which is probably common enough.

Differential Revision: https://phabricator.services.mozilla.com/D88724
This commit is contained in:
Emilio Cobos Álvarez
2020-08-31 07:46:56 +00:00
parent 22775b90d7
commit 82e2600f9b
6 changed files with 139 additions and 31 deletions

View File

@@ -361,11 +361,11 @@ already_AddRefed<Element> nsTextControlFrame::MakeAnonElement(
already_AddRefed<Element> nsTextControlFrame::MakeAnonDivWithTextNode(
PseudoStyleType aPseudoType) const {
RefPtr<Element> divElement = MakeAnonElement(aPseudoType);
RefPtr<Element> div = MakeAnonElement(aPseudoType);
// Create the text node for the anonymous <div> element.
RefPtr<nsTextNode> textNode = new (divElement->OwnerDoc()->NodeInfoManager())
nsTextNode(divElement->OwnerDoc()->NodeInfoManager());
nsNodeInfoManager* nim = div->OwnerDoc()->NodeInfoManager();
RefPtr<nsTextNode> textNode = new (nim) nsTextNode(nim);
// If the anonymous div element is not for the placeholder, we should
// mark the text node as "maybe modified frequently" for avoiding ASCII
// range checks at every input.
@@ -377,8 +377,8 @@ already_AddRefed<Element> nsTextControlFrame::MakeAnonDivWithTextNode(
textNode->MarkAsMaybeMasked();
}
}
divElement->AppendChildTo(textNode, false);
return divElement.forget();
div->AppendChildTo(textNode, false);
return div.forget();
}
nsresult nsTextControlFrame::CreateAnonymousContent(
@@ -476,21 +476,38 @@ void nsTextControlFrame::CreatePlaceholderIfNeeded() {
MOZ_ASSERT(!mPlaceholderDiv);
// Do we need a placeholder node?
nsAutoString placeholderTxt;
mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder,
placeholderTxt);
if (IsTextArea()) { // <textarea>s preserve newlines...
nsContentUtils::PlatformToDOMLineBreaks(placeholderTxt);
} else { // ...<input>s don't
nsContentUtils::RemoveNewlines(placeholderTxt);
}
if (placeholderTxt.IsEmpty()) {
nsAutoString placeholder;
if (!mContent->AsElement()->GetAttr(nsGkAtoms::placeholder, placeholder)) {
return;
}
mPlaceholderDiv = MakeAnonDivWithTextNode(PseudoStyleType::placeholder);
mPlaceholderDiv->GetFirstChild()->AsText()->SetText(placeholderTxt, false);
UpdatePlaceholderText(placeholder, false);
}
void nsTextControlFrame::PlaceholderChanged(const nsAttrValue* aOld,
const nsAttrValue* aNew) {
if (!aOld || !aNew) {
return; // This should be handled by GetAttributeChangeHint.
}
nsAutoString placeholder;
aNew->ToString(placeholder);
UpdatePlaceholderText(placeholder, true);
}
void nsTextControlFrame::UpdatePlaceholderText(nsString& aPlaceholder,
bool aNotify) {
MOZ_ASSERT(mPlaceholderDiv);
MOZ_ASSERT(mPlaceholderDiv->GetFirstChild());
if (IsTextArea()) { // <textarea>s preserve newlines...
nsContentUtils::PlatformToDOMLineBreaks(aPlaceholder);
} else { // ...<input>s don't
nsContentUtils::RemoveNewlines(aPlaceholder);
}
mPlaceholderDiv->GetFirstChild()->AsText()->SetText(aPlaceholder, aNotify);
}
void nsTextControlFrame::CreatePreviewIfNeeded() {