use std::cell::Cell;
use dom_struct::dom_struct;
use js::context::JSContext;
use script_bindings::cell::DomRefCell;
use script_bindings::reflector::reflect_dom_object;
use crate::dom::bindings::callback::{ExceptionHandling, RootedCallback, TracedCallback};
use crate::dom::bindings::codegen::Bindings::FileSystemEntryBinding::ErrorCallback;
use crate::dom::bindings::codegen::Bindings::FileSystemFileEntryBinding::{
FileCallback, FileSystemFileEntryMethods,
};
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::USVString;
use crate::dom::file::File;
use crate::dom::filesystem::FileSystem;
use crate::dom::filesystementry::FileSystemEntry;
use crate::dom::globalscope::GlobalScope;
#[dom_struct]
pub(crate) struct FileSystemFileEntry {
filesystementry: FileSystemEntry,
file: Dom<File>,
pending_callbacks: DomRefCell<Vec<PendingFileCallback>>,
next_callback: Cell<usize>,
}
#[derive(JSTraceable, MallocSizeOf)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
struct PendingFileCallback {
id: usize,
callback: TracedCallback<FileCallback>,
}
impl FileSystemFileEntry {
fn new_inherited(name: USVString, full_path: USVString, file: &File) -> FileSystemFileEntry {
FileSystemFileEntry {
filesystementry: FileSystemEntry::new_inherited(name, full_path, true),
file: Dom::from_ref(file),
pending_callbacks: Default::default(),
next_callback: Cell::new(0),
}
}
pub(crate) fn new(
cx: &mut JSContext,
global: &GlobalScope,
name: USVString,
full_path: USVString,
file: &File,
) -> DomRoot<FileSystemFileEntry> {
reflect_dom_object(
cx,
Box::new(FileSystemFileEntry::new_inherited(name, full_path, file)),
global,
)
}
pub(crate) fn set_filesystem(&self, fs: &FileSystem) {
self.filesystementry.set_filesystem(fs);
}
}
impl FileSystemFileEntryMethods<crate::DomTypeHolder> for FileSystemFileEntry {
fn File(
&self,
success_callback: RootedCallback<FileCallback>,
_error_callback: Option<RootedCallback<ErrorCallback>>,
) {
let id = self.next_callback.get();
self.pending_callbacks
.borrow_mut()
.push(PendingFileCallback {
id,
callback: success_callback.to_traced(),
});
self.next_callback.set(id + 1);
let this = Trusted::new(self);
self.global()
.task_manager()
.dom_manipulation_task_source()
.queue(task!(invoke_file_callback: move |cx| {
let this = this.root();
let maybe_index = this
.pending_callbacks
.borrow()
.iter()
.position(|val| val.id == id);
if let Some(index) = maybe_index {
rooted!(&in(cx) let callback = this
.pending_callbacks
.safe_borrow_mut(cx.no_gc())
.swap_remove(index)
.callback);
let file = DomRoot::from_ref(&*this.file);
let _ = callback.Call__(cx, &file, ExceptionHandling::Report);
}
}));
}
}