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