script/dom/filesystem/
filesystementry.rs1use std::cell::Cell;
6use std::rc::Rc;
7
8use dom_struct::dom_struct;
9use script_bindings::cell::DomRefCell;
10use script_bindings::reflector::Reflector;
11
12use crate::dom::bindings::callback::ExceptionHandling;
13use crate::dom::bindings::codegen::Bindings::FileSystemBinding::FileSystemMethods;
14use crate::dom::bindings::codegen::Bindings::FileSystemEntryBinding::{
15 ErrorCallback, FileSystemEntryCallback, FileSystemEntryMethods,
16};
17use crate::dom::bindings::refcounted::Trusted;
18use crate::dom::bindings::reflector::DomGlobal;
19use crate::dom::bindings::root::{DomRoot, MutNullableDom};
20use crate::dom::bindings::str::USVString;
21use crate::dom::filesystem::FileSystem;
22
23#[dom_struct]
24pub(crate) struct FileSystemEntry {
25 reflector_: Reflector,
26 name: USVString,
27 full_path: USVString,
28 is_file: bool,
29 filesystem: MutNullableDom<FileSystem>,
30 pending_callbacks: DomRefCell<Vec<PendingEntryCallback>>,
31 next_callback: Cell<usize>,
32}
33
34#[derive(JSTraceable, MallocSizeOf)]
35struct PendingEntryCallback {
36 id: usize,
37 #[conditional_malloc_size_of]
38 callback: Rc<FileSystemEntryCallback>,
39}
40
41impl FileSystemEntry {
42 pub(crate) fn new_inherited(
43 name: USVString,
44 full_path: USVString,
45 is_file: bool,
46 ) -> FileSystemEntry {
47 FileSystemEntry {
48 reflector_: Reflector::new(),
49 name,
50 full_path,
51 is_file,
52 filesystem: MutNullableDom::new(None),
53 pending_callbacks: Default::default(),
54 next_callback: Cell::new(0),
55 }
56 }
57
58 pub(crate) fn set_filesystem(&self, fs: &FileSystem) {
59 self.filesystem.set(Some(fs));
60 }
61}
62
63impl FileSystemEntryMethods<crate::DomTypeHolder> for FileSystemEntry {
64 fn IsFile(&self) -> bool {
66 self.is_file
67 }
68
69 fn IsDirectory(&self) -> bool {
71 !self.is_file
72 }
73
74 fn Name(&self) -> USVString {
76 self.name.clone()
77 }
78
79 fn FullPath(&self) -> USVString {
81 self.full_path.clone()
82 }
83
84 fn Filesystem(&self) -> DomRoot<FileSystem> {
86 self.filesystem
87 .get()
88 .expect("FileSystemEntry must be associated with a FileSystem")
89 }
90
91 fn GetParent(
93 &self,
94 success_callback: Option<Rc<FileSystemEntryCallback>>,
95 _error_callback: Option<Rc<ErrorCallback>>,
96 ) {
97 let Some(callback) = success_callback else {
98 return;
99 };
100 let id = self.next_callback.get();
112 let pending_callback = PendingEntryCallback { id, callback };
113 self.pending_callbacks.borrow_mut().push(pending_callback);
114 self.next_callback.set(id + 1);
115
116 let this = Trusted::new(self);
117 self.global()
118 .task_manager()
119 .dom_manipulation_task_source()
120 .queue(task!(invoke_get_parent: move |cx| {
121 let this = this.root();
122 let maybe_index = this
123 .pending_callbacks
124 .borrow()
125 .iter()
126 .position(|val| val.id == id);
127 if let Some(index) = maybe_index {
128 let callback = this
129 .pending_callbacks
130 .safe_borrow_mut(cx.no_gc())
131 .swap_remove(index)
132 .callback;
133 let entry = DomRoot::upcast::<FileSystemEntry>(this.Filesystem().Root());
134 let _ = callback.Call__(cx, &entry, ExceptionHandling::Report);
135 }
136 }));
137 }
138}