summaryrefslogtreecommitdiff
path: root/cli/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/main.rs')
-rw-r--r--cli/main.rs80
1 files changed, 66 insertions, 14 deletions
diff --git a/cli/main.rs b/cli/main.rs
index 9749496c6..650ab62a2 100644
--- a/cli/main.rs
+++ b/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(())
}
};