script/dom/datatransfer/
datatransferitemlist.rs1use std::cell::RefCell;
6use std::rc::Rc;
7
8use dom_struct::dom_struct;
9use js::context::JSContext;
10use js::rust::MutableHandleValue;
11use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
12
13use crate::dom::bindings::codegen::Bindings::DataTransferItemListBinding::DataTransferItemListMethods;
14use crate::dom::bindings::error::{Error, Fallible};
15use crate::dom::bindings::frozenarray::CachedFrozenArray;
16use crate::dom::bindings::reflector::DomGlobal;
17use crate::dom::bindings::root::DomRoot;
18use crate::dom::bindings::str::DOMString;
19use crate::dom::datatransferitem::DataTransferItem;
20use crate::dom::file::File;
21use crate::dom::window::Window;
22use crate::drag_data_store::{DragDataStore, Kind, Mode};
23
24#[dom_struct]
25pub(crate) struct DataTransferItemList {
26 reflector_: Reflector,
27 #[conditional_malloc_size_of]
28 #[no_trace]
29 data_store: Rc<RefCell<Option<DragDataStore>>>,
30 #[ignore_malloc_size_of = "mozjs"]
31 frozen_types: CachedFrozenArray,
32}
33
34impl DataTransferItemList {
35 fn new_inherited(data_store: Rc<RefCell<Option<DragDataStore>>>) -> DataTransferItemList {
36 DataTransferItemList {
37 reflector_: Reflector::new(),
38 frozen_types: CachedFrozenArray::new(),
39 data_store,
40 }
41 }
42
43 pub(crate) fn new(
44 cx: &mut JSContext,
45 window: &Window,
46 data_store: Rc<RefCell<Option<DragDataStore>>>,
47 ) -> DomRoot<DataTransferItemList> {
48 reflect_dom_object_with_cx(
49 Box::new(DataTransferItemList::new_inherited(data_store)),
50 window,
51 cx,
52 )
53 }
54
55 pub(crate) fn frozen_types(&self, cx: &mut js::context::JSContext, retval: MutableHandleValue) {
56 self.frozen_types.get_or_init(
57 cx,
58 || {
59 self.data_store
60 .borrow()
61 .as_ref()
62 .map_or(Vec::new(), |data_store| data_store.types())
63 },
64 retval,
65 );
66 }
67
68 pub(crate) fn invalidate_frozen_types(&self) {
69 self.frozen_types.clear();
70 }
71}
72
73impl DataTransferItemListMethods<crate::DomTypeHolder> for DataTransferItemList {
74 fn Length(&self) -> u32 {
76 self.data_store
79 .borrow()
80 .as_ref()
81 .map_or(0, |data_store| data_store.list_len() as u32)
82 }
83
84 fn IndexedGetter(
86 &self,
87 cx: &mut js::context::JSContext,
88 index: u32,
89 ) -> Option<DomRoot<DataTransferItem>> {
90 let option = self.data_store.borrow();
92 let data_store = match option.as_ref() {
93 Some(value) => value,
94 _ => return None,
95 };
96
97 data_store.get_by_index(index as usize).map(|(id, _)| {
99 DataTransferItem::new(cx, &self.global(), Rc::clone(&self.data_store), *id)
100 })
101 }
102
103 fn Add(
105 &self,
106 cx: &mut js::context::JSContext,
107 data: DOMString,
108 mut type_: DOMString,
109 ) -> Fallible<Option<DomRoot<DataTransferItem>>> {
110 let index = {
112 let mut option = self.data_store.borrow_mut();
113 let data_store = match option.as_mut() {
114 Some(value) if value.mode() == Mode::ReadWrite => value,
115 _ => return Ok(None),
116 };
117
118 type_.make_ascii_lowercase();
122 data_store.add(Kind::Text { data, type_ })
123 };
124
125 index.map(|id| {
126 self.frozen_types.clear();
127
128 Some(DataTransferItem::new(
131 cx,
132 &self.global(),
133 Rc::clone(&self.data_store),
134 id,
135 ))
136 })
137 }
138
139 fn Add_(
141 &self,
142 cx: &mut js::context::JSContext,
143 data: &File,
144 ) -> Fallible<Option<DomRoot<DataTransferItem>>> {
145 let index = {
146 let mut option = self.data_store.borrow_mut();
148 let data_store = match option.as_mut() {
149 Some(value) if value.mode() == Mode::ReadWrite => value,
150 _ => return Ok(None),
151 };
152
153 let mut type_ = data.file_type();
157 type_.make_ascii_lowercase();
158 let bytes = data.file_bytes().unwrap_or_default();
159 let name = data.name().clone();
160 data_store.add(Kind::File { bytes, name, type_ })
161 };
162 index.map(|id| {
163 self.frozen_types.clear();
164
165 Some(DataTransferItem::new(
168 cx,
169 &self.global(),
170 Rc::clone(&self.data_store),
171 id,
172 ))
173 })
174 }
175
176 fn Remove(&self, index: u32) -> Fallible<()> {
178 let mut option = self.data_store.borrow_mut();
181 let data_store = match option.as_mut() {
182 Some(value) if value.mode() == Mode::ReadWrite => value,
183 _ => return Err(Error::InvalidState(None)),
184 };
185
186 let index = index as usize;
187
188 if index < data_store.list_len() {
190 data_store.remove(index);
192 self.frozen_types.clear();
193 }
194
195 Ok(())
196 }
197
198 fn Clear(&self) {
200 let mut option = self.data_store.borrow_mut();
203 let data_store = match option.as_mut() {
204 Some(value) if value.mode() == Mode::ReadWrite => value,
205 _ => return,
206 };
207
208 if data_store.list_len() > 0 {
210 data_store.clear_list();
211 self.frozen_types.clear();
212 }
213 }
214}