script: Modify and copy the contents of <textarea> placeholder less (#43452)

Instead of always doing the newline fixup on the `<textarea>`
placeholder, only do it when the placeholder attribute itself changes.
This avoids doing string replacements when they are not necessary (such
as when a `<textarea>` switches from having text to only having the
placeholder and viceversa).

In addition make it so that `DOMString::clear` preserves the string
allocation when called.

Testing: This is just a small optimization so testing should not be
necessary. Existing behavior is verified via WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson
2026-03-19 16:57:28 +01:00
committed by GitHub
parent e2aa1c8c06
commit 56e79459f2
2 changed files with 16 additions and 12 deletions

View File

@@ -58,7 +58,7 @@ pub(crate) struct HTMLTextAreaElement {
htmlelement: HTMLElement,
#[no_trace]
textinput: DomRefCell<TextInput<EmbedderClipboardProvider>>,
placeholder: RefCell<String>,
placeholder: RefCell<DOMString>,
// https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
value_dirty: Cell<bool>,
form_owner: MutNullableDom<HTMLFormElement>,
@@ -232,13 +232,7 @@ impl HTMLTextAreaElement {
}
let content = if placeholder_shown {
// FIXME(nox): Would be cool to not allocate a new string if the
// placeholder is single line, but that's an unimportant detail.
self.placeholder
.borrow()
.replace("\r\n", "\n")
.replace('\r', "\n")
.into()
self.placeholder.borrow().clone()
} else if textinput_content.is_empty() {
// The addition of zero-width space here forces the text input to have an inline formatting
// context that might otherwise be trimmed if there's no text. This is important to ensure
@@ -662,9 +656,14 @@ impl VirtualMethods for HTMLTextAreaElement {
local_name!("placeholder") => {
{
let mut placeholder = self.placeholder.borrow_mut();
placeholder.clear();
if let AttributeMutation::Set(..) = mutation {
placeholder.push_str(attr.value().as_ref());
match mutation {
AttributeMutation::Set(..) => {
let value = attr.value();
let value_str: &str = value.as_ref();
*placeholder =
value_str.replace("\r\n", "\n").replace('\r', "\n").into();
},
AttributeMutation::Removed => placeholder.clear(),
}
}
self.handle_text_content_changed(CanGc::from_cx(cx));