script/dom/file/
filelist.rs1use std::slice::Iter;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use script_bindings::reflector::{Reflector, reflect_dom_object};
10use servo_base::id::{FileListId, FileListIndex};
11use servo_constellation_traits::SerializableFileList;
12
13use crate::dom::bindings::codegen::Bindings::FileListBinding::FileListMethods;
14use crate::dom::bindings::root::{Dom, DomRoot};
15use crate::dom::bindings::serializable::Serializable;
16use crate::dom::bindings::structuredclone::StructuredData;
17use crate::dom::file::File;
18use crate::dom::globalscope::GlobalScope;
19use crate::dom::window::Window;
20use crate::script_runtime::CanGc;
21
22#[dom_struct]
24pub(crate) struct FileList {
25 reflector_: Reflector,
26 list: Vec<Dom<File>>,
27}
28
29impl FileList {
30 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
31 fn new_inherited(files: Vec<Dom<File>>) -> FileList {
32 FileList {
33 reflector_: Reflector::new(),
34 list: files,
35 }
36 }
37
38 pub(crate) fn new(
39 window: &Window,
40 files: Vec<DomRoot<File>>,
41 can_gc: CanGc,
42 ) -> DomRoot<FileList> {
43 reflect_dom_object(
44 Box::new(FileList::new_inherited(
45 files.iter().map(|r| Dom::from_ref(&**r)).collect(),
46 )),
47 window,
48 can_gc,
49 )
50 }
51
52 pub(crate) fn new_in_global(
53 global: &GlobalScope,
54 files: Vec<DomRoot<File>>,
55 can_gc: CanGc,
56 ) -> DomRoot<FileList> {
57 reflect_dom_object(
58 Box::new(FileList::new_inherited(
59 files.iter().map(|r| Dom::from_ref(&**r)).collect(),
60 )),
61 global,
62 can_gc,
63 )
64 }
65
66 pub(crate) fn iter_files(&self) -> Iter<'_, Dom<File>> {
67 self.list.iter()
68 }
69}
70
71impl Serializable for FileList {
72 type Index = FileListIndex;
73 type Data = SerializableFileList;
74
75 fn serialize(&self) -> Result<(FileListId, SerializableFileList), ()> {
77 let files = self
78 .list
79 .iter()
80 .map(|file| file.serialized_data())
81 .collect::<Result<Vec<_>, _>>()?;
82 Ok((FileListId::new(), SerializableFileList { files }))
83 }
84
85 fn deserialize(
87 cx: &mut JSContext,
88 owner: &GlobalScope,
89 serialized: SerializableFileList,
90 ) -> Result<DomRoot<Self>, ()> {
91 let files = serialized
92 .files
93 .into_iter()
94 .map(|file| File::deserialize(cx, owner, file))
95 .collect::<Result<Vec<_>, _>>()?;
96 Ok(FileList::new_in_global(owner, files, CanGc::from_cx(cx)))
97 }
98
99 fn serialized_storage<'a>(
100 reader: StructuredData<'a, '_>,
101 ) -> &'a mut Option<rustc_hash::FxHashMap<FileListId, Self::Data>> {
102 match reader {
103 StructuredData::Reader(r) => &mut r.file_lists,
104 StructuredData::Writer(w) => &mut w.file_lists,
105 }
106 }
107}
108
109impl FileListMethods<crate::DomTypeHolder> for FileList {
110 fn Length(&self) -> u32 {
112 self.list.len() as u32
113 }
114
115 fn Item(&self, index: u32) -> Option<DomRoot<File>> {
117 if (index as usize) < self.list.len() {
118 Some(DomRoot::from_ref(&*(self.list[index as usize])))
119 } else {
120 None
121 }
122 }
123
124 fn IndexedGetter(&self, index: u32) -> Option<DomRoot<File>> {
126 self.Item(index)
127 }
128}