script/dom/html/input_element/
text_value_widget.rs1use std::cell::Ref;
6
7use js::context::JSContext;
8use script_bindings::codegen::GenericBindings::CharacterDataBinding::CharacterDataMethods;
9use script_bindings::root::Dom;
10
11use crate::dom::bindings::cell::DomRefCell;
12use crate::dom::bindings::inheritance::Castable;
13use crate::dom::characterdata::CharacterData;
14use crate::dom::element::Element;
15use crate::dom::htmlinputelement::HTMLInputElement;
16use crate::dom::node::{Node, NodeTraits};
17use crate::dom::text::Text;
18
19#[derive(Default, JSTraceable, MallocSizeOf, PartialEq)]
20#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
21pub(crate) struct TextValueWidget {
22 shadow_tree: DomRefCell<Option<TextValueShadowTree>>,
23}
24
25impl TextValueWidget {
26 fn get_or_create_shadow_tree(
29 &self,
30 cx: &mut JSContext,
31 input: &HTMLInputElement,
32 ) -> Ref<'_, TextValueShadowTree> {
33 {
34 if let Ok(shadow_tree) = Ref::filter_map(self.shadow_tree.borrow(), |shadow_tree| {
35 shadow_tree.as_ref()
36 }) {
37 return shadow_tree;
38 }
39 }
40
41 let element = input.upcast::<Element>();
42 let shadow_root = element
43 .shadow_root()
44 .unwrap_or_else(|| element.attach_ua_shadow_root(cx, true));
45 let shadow_root = shadow_root.upcast();
46 *self.shadow_tree.borrow_mut() = Some(TextValueShadowTree::new(cx, shadow_root));
47 self.get_or_create_shadow_tree(cx, input)
48 }
49
50 pub(crate) fn update_shadow_tree(&self, cx: &mut JSContext, input: &HTMLInputElement) {
51 self.get_or_create_shadow_tree(cx, input).update(input)
52 }
53}
54
55#[derive(Clone, JSTraceable, MallocSizeOf, PartialEq)]
56#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
57struct TextValueShadowTree {
58 value: Dom<Text>,
59}
60
61impl TextValueShadowTree {
62 fn new(cx: &mut JSContext, shadow_root: &Node) -> Self {
63 let value = Text::new(cx, Default::default(), &shadow_root.owner_document());
64 Node::replace_all(cx, Some(value.upcast()), shadow_root);
65 Self {
66 value: value.as_traced(),
67 }
68 }
69
70 fn update(&self, input_element: &HTMLInputElement) {
71 let character_data = self.value.upcast::<CharacterData>();
72 let value = input_element.value_for_shadow_dom();
73 if character_data.Data() != value {
74 character_data.SetData(value);
75 }
76 }
77}