diff options
-rw-r--r-- | cli/tools/bench/mod.rs | 7 | ||||
-rw-r--r-- | cli/tools/test/mod.rs | 6 | ||||
-rw-r--r-- | cli/worker.rs | 31 | ||||
-rw-r--r-- | runtime/js/99_main.js | 17 | ||||
-rw-r--r-- | runtime/worker.rs | 122 |
5 files changed, 112 insertions, 71 deletions
diff --git a/cli/tools/bench/mod.rs b/cli/tools/bench/mod.rs index 8663fbbc8..88bff479c 100644 --- a/cli/tools/bench/mod.rs +++ b/cli/tools/bench/mod.rs @@ -26,7 +26,6 @@ use deno_core::error::JsError; use deno_core::futures::future; use deno_core::futures::stream; use deno_core::futures::StreamExt; -use deno_core::located_script_name; use deno_core::serde_v8; use deno_core::unsync::spawn; use deno_core::unsync::spawn_blocking; @@ -220,7 +219,7 @@ async fn bench_specifier_inner( // Ensure that there are no pending exceptions before we start running tests worker.run_up_to_duration(Duration::from_millis(0)).await?; - worker.dispatch_load_event(located_script_name!())?; + worker.dispatch_load_event()?; let benchmarks = { let state_rc = worker.js_runtime.op_state(); @@ -269,8 +268,8 @@ async fn bench_specifier_inner( // Ignore `defaultPrevented` of the `beforeunload` event. We don't allow the // event loop to continue beyond what's needed to await results. - worker.dispatch_beforeunload_event(located_script_name!())?; - worker.dispatch_unload_event(located_script_name!())?; + worker.dispatch_beforeunload_event()?; + worker.dispatch_unload_event()?; // Ensure the worker has settled so we can catch any remaining unhandled rejections. We don't // want to wait forever here. diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs index 2c7241de1..2a406e560 100644 --- a/cli/tools/test/mod.rs +++ b/cli/tools/test/mod.rs @@ -654,15 +654,15 @@ async fn test_specifier_inner( // Ensure that there are no pending exceptions before we start running tests worker.run_up_to_duration(Duration::from_millis(0)).await?; - worker.dispatch_load_event(located_script_name!())?; + worker.dispatch_load_event()?; run_tests_for_worker(&mut worker, &specifier, &options, &fail_fast_tracker) .await?; // Ignore `defaultPrevented` of the `beforeunload` event. We don't allow the // event loop to continue beyond what's needed to await results. - worker.dispatch_beforeunload_event(located_script_name!())?; - worker.dispatch_unload_event(located_script_name!())?; + worker.dispatch_beforeunload_event()?; + worker.dispatch_unload_event()?; // Ensure all output has been flushed _ = sender.flush(); diff --git a/cli/worker.rs b/cli/worker.rs index ed82f4872..74ae1ef8f 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -10,7 +10,6 @@ use deno_core::anyhow::bail; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::futures::FutureExt; -use deno_core::located_script_name; use deno_core::parking_lot::Mutex; use deno_core::url::Url; use deno_core::v8; @@ -182,7 +181,7 @@ impl CliMainWorker { self.execute_main_module_possibly_with_npm().await?; } - self.worker.dispatch_load_event(located_script_name!())?; + self.worker.dispatch_load_event()?; loop { if let Some(hmr_runner) = maybe_hmr_runner.as_mut() { @@ -213,15 +212,12 @@ impl CliMainWorker { .await?; } - if !self - .worker - .dispatch_beforeunload_event(located_script_name!())? - { + if !self.worker.dispatch_beforeunload_event()? { break; } } - self.worker.dispatch_unload_event(located_script_name!())?; + self.worker.dispatch_unload_event()?; if let Some(coverage_collector) = maybe_coverage_collector.as_mut() { self @@ -268,10 +264,7 @@ impl CliMainWorker { /// respectively. pub async fn execute(&mut self) -> Result<(), AnyError> { self.inner.execute_main_module_possibly_with_npm().await?; - self - .inner - .worker - .dispatch_load_event(located_script_name!())?; + self.inner.worker.dispatch_load_event()?; self.pending_unload = true; let result = loop { @@ -279,11 +272,7 @@ impl CliMainWorker { Ok(()) => {} Err(error) => break Err(error), } - match self - .inner - .worker - .dispatch_beforeunload_event(located_script_name!()) - { + match self.inner.worker.dispatch_beforeunload_event() { Ok(default_prevented) if default_prevented => {} // continue loop Ok(_) => break Ok(()), Err(error) => break Err(error), @@ -293,10 +282,7 @@ impl CliMainWorker { result?; - self - .inner - .worker - .dispatch_unload_event(located_script_name!())?; + self.inner.worker.dispatch_unload_event()?; Ok(()) } @@ -305,10 +291,7 @@ impl CliMainWorker { impl Drop for FileWatcherModuleExecutor { fn drop(&mut self) { if self.pending_unload { - let _ = self - .inner - .worker - .dispatch_unload_event(located_script_name!()); + let _ = self.inner.worker.dispatch_unload_event(); } } } diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index e5b9b9778..0241a1936 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -528,6 +528,20 @@ function processRejectionHandled(promise, reason) { } } +function dispatchLoadEvent() { + globalThis_.dispatchEvent(new Event("load")); +} + +function dispatchBeforeUnloadEvent() { + return globalThis_.dispatchEvent( + new Event("beforeunload", { cancelable: true }), + ); +} + +function dispatchUnloadEvent() { + globalThis_.dispatchEvent(new Event("unload")); +} + let hasBootstrapped = false; // Delete the `console` object that V8 automaticaly adds onto the global wrapper // object on context creation. We don't want this console object to shadow the @@ -995,6 +1009,9 @@ delete globalThis.nodeBootstrap; globalThis.bootstrap = { mainRuntime: bootstrapMainRuntime, workerRuntime: bootstrapWorkerRuntime, + dispatchLoadEvent, + dispatchUnloadEvent, + dispatchBeforeUnloadEvent, }; event.setEventTargetData(globalThis); diff --git a/runtime/worker.rs b/runtime/worker.rs index 2fb32c766..236777335 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -11,7 +11,6 @@ use std::time::Instant; use deno_broadcast_channel::InMemoryBroadcastChannel; use deno_cache::CreateCache; use deno_cache::SqliteBackedCache; -use deno_core::ascii_str; use deno_core::error::AnyError; use deno_core::error::JsError; use deno_core::merge_op_metrics; @@ -115,6 +114,9 @@ pub struct MainWorker { should_wait_for_inspector_session: bool, exit_code: ExitCode, bootstrap_fn_global: Option<v8::Global<v8::Function>>, + dispatch_load_event_fn_global: v8::Global<v8::Function>, + dispatch_beforeunload_event_fn_global: v8::Global<v8::Function>, + dispatch_unload_event_fn_global: v8::Global<v8::Function>, } pub struct WorkerOptions { @@ -523,7 +525,12 @@ impl MainWorker { let inspector = js_runtime.inspector(); op_state.borrow_mut().put(inspector); } - let bootstrap_fn_global = { + let ( + bootstrap_fn_global, + dispatch_load_event_fn_global, + dispatch_beforeunload_event_fn_global, + dispatch_unload_event_fn_global, + ) = { let context = js_runtime.main_context(); let scope = &mut js_runtime.handle_scope(); let context_local = v8::Local::new(scope, context); @@ -541,7 +548,40 @@ impl MainWorker { bootstrap_ns.get(scope, main_runtime_str.into()).unwrap(); let bootstrap_fn = v8::Local::<v8::Function>::try_from(bootstrap_fn).unwrap(); - v8::Global::new(scope, bootstrap_fn) + let dispatch_load_event_fn_str = + v8::String::new_external_onebyte_static(scope, b"dispatchLoadEvent") + .unwrap(); + let dispatch_load_event_fn = bootstrap_ns + .get(scope, dispatch_load_event_fn_str.into()) + .unwrap(); + let dispatch_load_event_fn = + v8::Local::<v8::Function>::try_from(dispatch_load_event_fn).unwrap(); + let dispatch_beforeunload_event_fn_str = + v8::String::new_external_onebyte_static( + scope, + b"dispatchBeforeUnloadEvent", + ) + .unwrap(); + let dispatch_beforeunload_event_fn = bootstrap_ns + .get(scope, dispatch_beforeunload_event_fn_str.into()) + .unwrap(); + let dispatch_beforeunload_event_fn = + v8::Local::<v8::Function>::try_from(dispatch_beforeunload_event_fn) + .unwrap(); + let dispatch_unload_event_fn_str = + v8::String::new_external_onebyte_static(scope, b"dispatchUnloadEvent") + .unwrap(); + let dispatch_unload_event_fn = bootstrap_ns + .get(scope, dispatch_unload_event_fn_str.into()) + .unwrap(); + let dispatch_unload_event_fn = + v8::Local::<v8::Function>::try_from(dispatch_unload_event_fn).unwrap(); + ( + v8::Global::new(scope, bootstrap_fn), + v8::Global::new(scope, dispatch_load_event_fn), + v8::Global::new(scope, dispatch_beforeunload_event_fn), + v8::Global::new(scope, dispatch_unload_event_fn), + ) }; Self { @@ -551,6 +591,9 @@ impl MainWorker { .should_wait_for_inspector_session, exit_code, bootstrap_fn_global: Some(bootstrap_fn_global), + dispatch_load_event_fn_global, + dispatch_beforeunload_event_fn_global, + dispatch_unload_event_fn_global, } } @@ -708,54 +751,53 @@ impl MainWorker { /// Dispatches "load" event to the JavaScript runtime. /// /// Does not poll event loop, and thus not await any of the "load" event handlers. - pub fn dispatch_load_event( - &mut self, - script_name: &'static str, - ) -> Result<(), AnyError> { - self.js_runtime.execute_script( - script_name, - // NOTE(@bartlomieju): not using `globalThis` here, because user might delete - // it. Instead we're using global `dispatchEvent` function which will - // used a saved reference to global scope. - ascii_str!("dispatchEvent(new Event('load'))"), - )?; + pub fn dispatch_load_event(&mut self) -> Result<(), AnyError> { + let scope = &mut self.js_runtime.handle_scope(); + let tc_scope = &mut v8::TryCatch::new(scope); + let dispatch_load_event_fn = + v8::Local::new(tc_scope, &self.dispatch_load_event_fn_global); + let undefined = v8::undefined(tc_scope); + dispatch_load_event_fn.call(tc_scope, undefined.into(), &[]); + if let Some(exception) = tc_scope.exception() { + let error = JsError::from_v8_exception(tc_scope, exception); + return Err(error.into()); + } Ok(()) } /// Dispatches "unload" event to the JavaScript runtime. /// /// Does not poll event loop, and thus not await any of the "unload" event handlers. - pub fn dispatch_unload_event( - &mut self, - script_name: &'static str, - ) -> Result<(), AnyError> { - self.js_runtime.execute_script( - script_name, - // NOTE(@bartlomieju): not using `globalThis` here, because user might delete - // it. Instead we're using global `dispatchEvent` function which will - // used a saved reference to global scope. - ascii_str!("dispatchEvent(new Event('unload'))"), - )?; + pub fn dispatch_unload_event(&mut self) -> Result<(), AnyError> { + let scope = &mut self.js_runtime.handle_scope(); + let tc_scope = &mut v8::TryCatch::new(scope); + let dispatch_unload_event_fn = + v8::Local::new(tc_scope, &self.dispatch_unload_event_fn_global); + let undefined = v8::undefined(tc_scope); + dispatch_unload_event_fn.call(tc_scope, undefined.into(), &[]); + if let Some(exception) = tc_scope.exception() { + let error = JsError::from_v8_exception(tc_scope, exception); + return Err(error.into()); + } Ok(()) } /// Dispatches "beforeunload" event to the JavaScript runtime. Returns a boolean /// indicating if the event was prevented and thus event loop should continue /// running. - pub fn dispatch_beforeunload_event( - &mut self, - script_name: &'static str, - ) -> Result<bool, AnyError> { - let value = self.js_runtime.execute_script( - script_name, - // NOTE(@bartlomieju): not using `globalThis` here, because user might delete - // it. Instead we're using global `dispatchEvent` function which will - // used a saved reference to global scope. - ascii_str!( - "dispatchEvent(new Event('beforeunload', { cancelable: true }));" - ), - )?; - let local_value = value.open(&mut self.js_runtime.handle_scope()); - Ok(local_value.is_false()) + pub fn dispatch_beforeunload_event(&mut self) -> Result<bool, AnyError> { + let scope = &mut self.js_runtime.handle_scope(); + let tc_scope = &mut v8::TryCatch::new(scope); + let dispatch_beforeunload_event_fn = + v8::Local::new(tc_scope, &self.dispatch_beforeunload_event_fn_global); + let undefined = v8::undefined(tc_scope); + let ret_val = + dispatch_beforeunload_event_fn.call(tc_scope, undefined.into(), &[]); + if let Some(exception) = tc_scope.exception() { + let error = JsError::from_v8_exception(tc_scope, exception); + return Err(error.into()); + } + let ret_val = ret_val.unwrap(); + Ok(ret_val.is_false()) } } |