use std::cell::Cell;
use std::rc::Rc;
use dom_struct::dom_struct;
use script_bindings::cell::DomRefCell;
use script_bindings::reflector::Reflector;
use crate::dom::bindings::callback::ExceptionHandling;
use crate::dom::bindings::codegen::Bindings::FileSystemBinding::FileSystemMethods;
use crate::dom::bindings::codegen::Bindings::FileSystemEntryBinding::{
ErrorCallback, FileSystemEntryCallback, FileSystemEntryMethods,
};
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomGlobal;
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::USVString;
use crate::dom::filesystem::FileSystem;
#[dom_struct]
pub(crate) struct FileSystemEntry {
reflector_: Reflector,
name: USVString,
full_path: USVString,
is_file: bool,
filesystem: MutNullableDom<FileSystem>,
pending_callbacks: DomRefCell<Vec<PendingEntryCallback>>,
next_callback: Cell<usize>,
}
#[derive(JSTraceable, MallocSizeOf)]
struct PendingEntryCallback {
id: usize,
#[conditional_malloc_size_of]
callback: Rc<FileSystemEntryCallback>,
}
impl FileSystemEntry {
pub(crate) fn new_inherited(
name: USVString,
full_path: USVString,
is_file: bool,
) -> FileSystemEntry {
FileSystemEntry {
reflector_: Reflector::new(),
name,
full_path,
is_file,
filesystem: MutNullableDom::new(None),
pending_callbacks: Default::default(),
next_callback: Cell::new(0),
}
}
pub(crate) fn set_filesystem(&self, fs: &FileSystem) {
self.filesystem.set(Some(fs));
}
}
impl FileSystemEntryMethods<crate::DomTypeHolder> for FileSystemEntry {
fn IsFile(&self) -> bool {
self.is_file
}
fn IsDirectory(&self) -> bool {
!self.is_file
}
fn Name(&self) -> USVString {
self.name.clone()
}
fn FullPath(&self) -> USVString {
self.full_path.clone()
}
fn Filesystem(&self) -> DomRoot<FileSystem> {
self.filesystem
.get()
.expect("FileSystemEntry must be associated with a FileSystem")
}
fn GetParent(
&self,
success_callback: Option<Rc<FileSystemEntryCallback>>,
_error_callback: Option<Rc<ErrorCallback>>,
) {
let Some(callback) = success_callback else {
return;
};
let id = self.next_callback.get();
let pending_callback = PendingEntryCallback { id, callback };
self.pending_callbacks.borrow_mut().push(pending_callback);
self.next_callback.set(id + 1);
let this = Trusted::new(self);
self.global()
.task_manager()
.dom_manipulation_task_source()
.queue(task!(invoke_get_parent: 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 {
let callback = this
.pending_callbacks
.safe_borrow_mut(cx.no_gc())
.swap_remove(index)
.callback;
let entry = DomRoot::upcast::<FileSystemEntry>(this.Filesystem().Root());
let _ = callback.Call__(cx, &entry, ExceptionHandling::Report);
}
}));
}
}