mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
fix(cli): dispatch unload event on watch drop (#11696)
This commit is contained in:
parent
85a56e7144
commit
a3fd4bb998
2 changed files with 141 additions and 14 deletions
80
cli/main.rs
80
cli/main.rs
|
@ -892,29 +892,81 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> {
|
|||
})
|
||||
};
|
||||
|
||||
/// The FileWatcherModuleExecutor provides module execution with safe dispatching of life-cycle events by tracking the
|
||||
/// state of any pending events and emitting accordingly on drop in the case of a future
|
||||
/// cancellation.
|
||||
struct FileWatcherModuleExecutor {
|
||||
worker: MainWorker,
|
||||
pending_unload: bool,
|
||||
}
|
||||
|
||||
impl FileWatcherModuleExecutor {
|
||||
pub fn new(worker: MainWorker) -> FileWatcherModuleExecutor {
|
||||
FileWatcherModuleExecutor {
|
||||
worker,
|
||||
pending_unload: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute the given main module emitting load and unload events before and after execution
|
||||
/// respectively.
|
||||
pub async fn execute(
|
||||
&mut self,
|
||||
main_module: &ModuleSpecifier,
|
||||
) -> Result<(), AnyError> {
|
||||
self.worker.execute_module(main_module).await?;
|
||||
self.worker.execute_script(
|
||||
&located_script_name!(),
|
||||
"window.dispatchEvent(new Event('load'))",
|
||||
)?;
|
||||
self.pending_unload = true;
|
||||
|
||||
let result = self.worker.run_event_loop(false).await;
|
||||
self.pending_unload = false;
|
||||
|
||||
if let Err(err) = result {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
self.worker.execute_script(
|
||||
&located_script_name!(),
|
||||
"window.dispatchEvent(new Event('unload'))",
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FileWatcherModuleExecutor {
|
||||
fn drop(&mut self) {
|
||||
if self.pending_unload {
|
||||
self
|
||||
.worker
|
||||
.execute_script(
|
||||
&located_script_name!(),
|
||||
"window.dispatchEvent(new Event('unload'))",
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let operation =
|
||||
|(program_state, main_module): (Arc<ProgramState>, ModuleSpecifier)| {
|
||||
let flags = flags.clone();
|
||||
let permissions = Permissions::from_options(&flags.into());
|
||||
async move {
|
||||
let main_module = main_module.clone();
|
||||
let mut worker = create_main_worker(
|
||||
// We make use an module executor guard to ensure that unload is always fired when an
|
||||
// operation is called.
|
||||
let mut executor = FileWatcherModuleExecutor::new(create_main_worker(
|
||||
&program_state,
|
||||
main_module.clone(),
|
||||
permissions,
|
||||
None,
|
||||
);
|
||||
debug!("main_module {}", main_module);
|
||||
worker.execute_module(&main_module).await?;
|
||||
worker.execute_script(
|
||||
&located_script_name!(),
|
||||
"window.dispatchEvent(new Event('load'))",
|
||||
)?;
|
||||
worker.run_event_loop(false).await?;
|
||||
worker.execute_script(
|
||||
&located_script_name!(),
|
||||
"window.dispatchEvent(new Event('unload'))",
|
||||
)?;
|
||||
));
|
||||
|
||||
executor.execute(&main_module).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue