diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 2756152f190..ddcee472674 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -1556,12 +1556,12 @@ impl Document {
return;
}
- // For a node within a text input UA shadow DOM, redirect the focus target into its shadow host.
+ // For a node within a text input UA shadow DOM, delegate the focus target into its shadow host.
+ // TODO: This focus delegation should be done with shadow DOM delegateFocus attribute.
let target_el = el.find_focusable_shadow_host_if_necessary();
self.begin_focus_transaction();
// Try to focus `el`. If it's not focusable, focus the document
- // instead.
self.request_focus(None, FocusInitiator::Local, can_gc);
self.request_focus(target_el.as_deref(), FocusInitiator::Local, can_gc);
}
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index 95748a185ce..8999d7d9e4f 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -116,7 +116,7 @@ const DEFAULT_FILE_INPUT_VALUE: &str = "No file chosen";
///
/// ```
// TODO(stevennovaryo): We are trying to use CSS to mimic Chrome and Firefox's layout for the element.
-// But this does have some discrepencies. For example, they would try to vertically align
+// But this does have some discrepancies. For example, they would try to vertically align
// text baseline with the baseline of other TextNode within an inline flow.
struct InputTypeTextShadowTree {
text_container: Dom,
@@ -135,7 +135,7 @@ struct InputTypeColorShadowTree {
// FIXME: These styles should be inside UA stylesheet, but it is not possible without internal pseudo element support.
const TEXT_TREE_STYLE: &str = "
-#input-editor::selection, #input-placeholder::selection {
+#input-editor::selection {
background: rgba(176, 214, 255, 1.0);
color: black;
}
@@ -144,14 +144,14 @@ const TEXT_TREE_STYLE: &str = "
visibility: hidden !important
}
-#input-container {
- position: relative !important;
- height: 100% !important;
- pointer-events: none !important;
+#input-editor {
+ pointer-events: auto;
}
-#input-editor {
- pointer-events: auto !important;
+#input-container {
+ position: relative;
+ height: 100%;
+ pointer-events: none;
}
#input-editor, #input-placeholder {
@@ -1131,7 +1131,7 @@ impl HTMLInputElement {
ShadowRootMode::Closed,
false,
false,
- false,
+ true,
SlotAssignmentMode::Manual,
can_gc,
)
@@ -1309,11 +1309,6 @@ impl HTMLInputElement {
true => "\u{200B}".into(),
};
- // TODO(stevennovaryo): Introduce caching to prevent costly update.
- text_shadow_tree
- .placeholder_container
- .upcast::()
- .SetTextContent(Some(self.placeholder.to_owned().take()), can_gc);
text_shadow_tree
.text_container
.upcast::()
@@ -2909,11 +2904,21 @@ impl VirtualMethods for HTMLInputElement {
local_name!("placeholder") => {
{
let mut placeholder = self.placeholder.borrow_mut();
+ let old_placeholder = placeholder.clone();
placeholder.clear();
if let AttributeMutation::Set(_) = mutation {
placeholder
.extend(attr.value().chars().filter(|&c| c != '\n' && c != '\r'));
}
+
+ // If old placeholder is not the same as the new one,
+ // we need to update the shadow tree.
+ if old_placeholder != *placeholder {
+ self.text_shadow_tree(can_gc)
+ .placeholder_container
+ .upcast::()
+ .SetTextContent(Some(placeholder.clone()), can_gc);
+ }
}
self.update_placeholder_shown_state();
},
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 5f9a955f4ab..0d66a80afee 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -233,7 +233,7 @@ bitflags! {
/// Whether this node has a serve as the text container for editable content of
/// or