script/dom/filesystem/
filesystemfileentry.rs1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use script_bindings::cell::DomRefCell;
10use script_bindings::reflector::reflect_dom_object;
11
12use crate::dom::bindings::callback::{ExceptionHandling, RootedCallback, TracedCallback};
13use crate::dom::bindings::codegen::Bindings::FileSystemEntryBinding::ErrorCallback;
14use crate::dom::bindings::codegen::Bindings::FileSystemFileEntryBinding::{
15 FileCallback, FileSystemFileEntryMethods,
16};
17use crate::dom::bindings::refcounted::Trusted;
18use crate::dom::bindings::reflector::DomGlobal;
19use crate::dom::bindings::root::{Dom, DomRoot};
20use crate::dom::bindings::str::USVString;
21use crate::dom::file::File;
22use crate::dom::filesystem::FileSystem;
23use crate::dom::filesystementry::FileSystemEntry;
24use crate::dom::globalscope::GlobalScope;
25
26#[dom_struct]
27pub(crate) struct FileSystemFileEntry {
28 filesystementry: FileSystemEntry,
29 file: Dom<File>,
30 pending_callbacks: DomRefCell<Vec<PendingFileCallback>>,
31 next_callback: Cell<usize>,
32}
33
34#[derive(JSTraceable, MallocSizeOf)]
35#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
36struct PendingFileCallback {
37 id: usize,
38 callback: TracedCallback<FileCallback>,
39}
40
41impl FileSystemFileEntry {
42 fn new_inherited(name: USVString, full_path: USVString, file: &File) -> FileSystemFileEntry {
43 FileSystemFileEntry {
44 filesystementry: FileSystemEntry::new_inherited(name, full_path, true),
45 file: Dom::from_ref(file),
46 pending_callbacks: Default::default(),
47 next_callback: Cell::new(0),
48 }
49 }
50
51 pub(crate) fn new(
52 cx: &mut JSContext,
53 global: &GlobalScope,
54 name: USVString,
55 full_path: USVString,
56 file: &File,
57 ) -> DomRoot<FileSystemFileEntry> {
58 reflect_dom_object(
59 cx,
60 Box::new(FileSystemFileEntry::new_inherited(name, full_path, file)),
61 global,
62 )
63 }
64
65 pub(crate) fn set_filesystem(&self, fs: &FileSystem) {
66 self.filesystementry.set_filesystem(fs);
67 }
68}
69
70impl FileSystemFileEntryMethods<crate::DomTypeHolder> for FileSystemFileEntry {
71 fn File(
73 &self,
74 success_callback: RootedCallback<FileCallback>,
75 _error_callback: Option<RootedCallback<ErrorCallback>>,
76 ) {
77 let id = self.next_callback.get();
89 self.pending_callbacks
90 .borrow_mut()
91 .push(PendingFileCallback {
92 id,
93 callback: success_callback.to_traced(),
94 });
95 self.next_callback.set(id + 1);
96
97 let this = Trusted::new(self);
98 self.global()
99 .task_manager()
100 .dom_manipulation_task_source()
101 .queue(task!(invoke_file_callback: move |cx| {
102 let this = this.root();
103 let maybe_index = this
104 .pending_callbacks
105 .borrow()
106 .iter()
107 .position(|val| val.id == id);
108 if let Some(index) = maybe_index {
109 rooted!(&in(cx) let callback = this
110 .pending_callbacks
111 .safe_borrow_mut(cx.no_gc())
112 .swap_remove(index)
113 .callback);
114 let file = DomRoot::from_ref(&*this.file);
115 let _ = callback.Call__(cx, &file, ExceptionHandling::Report);
116 }
117 }));
118 }
119}