script/dom/
datatransferitemlist.rs1use std::cell::RefCell;
6use std::rc::Rc;
7
8use dom_struct::dom_struct;
9use js::rust::MutableHandleValue;
10
11use crate::dom::bindings::codegen::Bindings::DataTransferItemListBinding::DataTransferItemListMethods;
12use crate::dom::bindings::error::{Error, Fallible};
13use crate::dom::bindings::frozenarray::CachedFrozenArray;
14use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
15use crate::dom::bindings::root::DomRoot;
16use crate::dom::bindings::str::DOMString;
17use crate::dom::datatransferitem::DataTransferItem;
18use crate::dom::file::File;
19use crate::dom::window::Window;
20use crate::drag_data_store::{DragDataStore, Kind, Mode};
21use crate::script_runtime::{CanGc, JSContext};
22
23#[dom_struct]
24pub(crate) struct DataTransferItemList {
25 reflector_: Reflector,
26 #[ignore_malloc_size_of = "Rc"]
27 #[no_trace]
28 data_store: Rc<RefCell<Option<DragDataStore>>>,
29 #[ignore_malloc_size_of = "mozjs"]
30 frozen_types: CachedFrozenArray,
31}
32
33impl DataTransferItemList {
34 fn new_inherited(data_store: Rc<RefCell<Option<DragDataStore>>>) -> DataTransferItemList {
35 DataTransferItemList {
36 reflector_: Reflector::new(),
37 frozen_types: CachedFrozenArray::new(),
38 data_store,
39 }
40 }
41
42 pub(crate) fn new(
43 window: &Window,
44 data_store: Rc<RefCell<Option<DragDataStore>>>,
45 can_gc: CanGc,
46 ) -> DomRoot<DataTransferItemList> {
47 reflect_dom_object(
48 Box::new(DataTransferItemList::new_inherited(data_store)),
49 window,
50 can_gc,
51 )
52 }
53
54 pub(crate) fn frozen_types(&self, cx: JSContext, retval: MutableHandleValue, can_gc: CanGc) {
55 self.frozen_types.get_or_init(
56 || {
57 self.data_store
58 .borrow()
59 .as_ref()
60 .map_or(Vec::new(), |data_store| data_store.types())
61 },
62 cx,
63 retval,
64 can_gc,
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(&self, index: u32, can_gc: CanGc) -> Option<DomRoot<DataTransferItem>> {
86 let option = self.data_store.borrow();
88 let data_store = match option.as_ref() {
89 Some(value) => value,
90 _ => return None,
91 };
92
93 data_store.get_by_index(index as usize).map(|(id, _)| {
95 DataTransferItem::new(&self.global(), Rc::clone(&self.data_store), *id, can_gc)
96 })
97 }
98
99 fn Add(
101 &self,
102 data: DOMString,
103 mut type_: DOMString,
104 can_gc: CanGc,
105 ) -> Fallible<Option<DomRoot<DataTransferItem>>> {
106 let mut option = self.data_store.borrow_mut();
108 let data_store = match option.as_mut() {
109 Some(value) if value.mode() == Mode::ReadWrite => value,
110 _ => return Ok(None),
111 };
112
113 type_.make_ascii_lowercase();
117 data_store.add(Kind::Text { data, type_ }).map(|id| {
118 self.frozen_types.clear();
119
120 Some(DataTransferItem::new(
123 &self.global(),
124 Rc::clone(&self.data_store),
125 id,
126 can_gc,
127 ))
128 })
129 }
130
131 fn Add_(&self, data: &File, can_gc: CanGc) -> Fallible<Option<DomRoot<DataTransferItem>>> {
133 let mut option = self.data_store.borrow_mut();
135 let data_store = match option.as_mut() {
136 Some(value) if value.mode() == Mode::ReadWrite => value,
137 _ => return Ok(None),
138 };
139
140 let mut type_ = data.file_type();
144 type_.make_ascii_lowercase();
145 let bytes = data.file_bytes().unwrap_or_default();
146 let name = data.name().clone();
147
148 data_store.add(Kind::File { bytes, name, type_ }).map(|id| {
149 self.frozen_types.clear();
150
151 Some(DataTransferItem::new(
154 &self.global(),
155 Rc::clone(&self.data_store),
156 id,
157 can_gc,
158 ))
159 })
160 }
161
162 fn Remove(&self, index: u32) -> Fallible<()> {
164 let mut option = self.data_store.borrow_mut();
167 let data_store = match option.as_mut() {
168 Some(value) if value.mode() == Mode::ReadWrite => value,
169 _ => return Err(Error::InvalidState),
170 };
171
172 let index = index as usize;
173
174 if index < data_store.list_len() {
176 data_store.remove(index);
178 self.frozen_types.clear();
179 }
180
181 Ok(())
182 }
183
184 fn Clear(&self) {
186 let mut option = self.data_store.borrow_mut();
189 let data_store = match option.as_mut() {
190 Some(value) if value.mode() == Mode::ReadWrite => value,
191 _ => return,
192 };
193
194 if data_store.list_len() > 0 {
196 data_store.clear_list();
197 self.frozen_types.clear();
198 }
199 }
200}