/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
libs/core_testing/checkin/runner/mod.rs
174 строки
4 KB
Haruto Tanaka
fix(lsp): fix CPU busy loop by creating tokio runtime before JsRuntime in TSC thread (#35595)
06 июл 2026, 16:58
Не верифицирован
06 июл 2026, 16:58
ac8677d
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. use std::any::Any; use std::any::TypeId; use std::collections::HashMap; use std::future::Future; use std::rc::Rc; use std::sync::Arc; use std::sync::Mutex; use std::sync::mpsc::RecvTimeoutError; use std::sync::mpsc::channel; use std::time::Duration; use deno_core::CrossIsolateStore; use deno_core::Extension; use deno_core::JsRuntime; use deno_core::RuntimeOptions; use self::ops_worker::WorkerCloseWatcher; use self::ops_worker::WorkerHostSide; use self::ops_worker::worker_create; use self::ts_module_loader::maybe_transpile_source; mod extensions; mod ops; mod ops_async; mod ops_buffer; mod ops_error; mod ops_io; mod ops_worker; pub mod snapshot; #[cfg(test)] pub mod testing; mod ts_module_loader; #[derive(Clone, Default)] pub struct Output { pub lines: Arc<Mutex<Vec<String>>>, } impl Output { pub fn line(&self, line: String) { self.lines.lock().unwrap().push(line) } #[cfg(test)] pub fn take(&self) -> Vec<String> { std::mem::take(&mut self.lines.lock().unwrap()) } } #[derive(Default)] pub struct TestData { pub data: HashMap<(String, TypeId), Box<dyn Any>>, } impl TestData { pub fn insert<T: 'static + Any>(&mut self, name: String, data: T) { self.data.insert((name, TypeId::of::<T>()), Box::new(data)); } pub fn get<T: 'static + Any>(&self, name: String) -> &T { let key = (name, TypeId::of::<T>()); self .data .get(&key) .unwrap_or_else(|| { panic!( "Unable to locate '{}' of type {}", key.0, std::any::type_name::<T>() ) }) .downcast_ref() .unwrap() } pub fn take<T: 'static + Any>(&mut self, name: String) -> T { let key = (name, TypeId::of::<T>()); let Some(res) = self.data.remove(&key) else { panic!( "Failed to remove '{}' of type {}", key.0, std::any::type_name::<T>() ); }; *res.downcast().unwrap() } } pub fn create_runtime_from_snapshot( snapshot: &'static [u8], inspector: bool, parent: Option<WorkerCloseWatcher>, additional_extensions: Vec<Extension>, ) -> (JsRuntime, WorkerHostSide) { create_runtime_from_snapshot_with_options( snapshot, inspector, parent, additional_extensions, RuntimeOptions::default(), ) } pub struct Snapshot(&'static [u8]); pub fn create_runtime_from_snapshot_with_options( snapshot: &'static [u8], inspector: bool, parent: Option<WorkerCloseWatcher>, additional_extensions: Vec<Extension>, options: RuntimeOptions, ) -> (JsRuntime, WorkerHostSide) { let (worker, worker_host_side) = worker_create(parent); let mut extensions = vec![extensions::checkin_runtime::init::<()>()]; extensions.extend(additional_extensions); let module_loader = Rc::new(ts_module_loader::TypescriptModuleLoader::default()); let runtime = JsRuntime::new(RuntimeOptions { extensions, startup_snapshot: Some(snapshot), module_loader: Some(module_loader.clone()), extension_transpiler: Some(Rc::new(|specifier, source| { maybe_transpile_source(specifier, source) })), shared_array_buffer_store: Some(CrossIsolateStore::default()), inspector, ..options }); let stats = runtime.runtime_activity_stats_factory(); runtime.op_state().borrow_mut().put(stats); runtime.op_state().borrow_mut().put(worker); runtime.op_state().borrow_mut().put(Snapshot(snapshot)); (runtime, worker_host_side) } /// Create the tokio runtime that a checkin `JsRuntime` runs on. It must /// exist and be entered before the `JsRuntime` is created, so that delayed /// V8 tasks can be scheduled on it. fn create_tokio_runtime() -> tokio::runtime::Runtime { tokio::runtime::Builder::new_current_thread() .enable_all() .build() .expect("Failed to build a runtime") } fn run_async( tokio: tokio::runtime::Runtime, f: impl Future<Output = Result<(), anyhow::Error>>, ) { tokio.block_on(f).expect("Failed to run the given task"); // We don't have a good way to wait for tokio to go idle here, but we'd like tokio // to poll any remaining tasks to shake out any errors. let handle = tokio.spawn(async { tokio::task::yield_now().await; }); _ = tokio.block_on(handle); let (tx, rx) = channel::<()>(); let timeout = std::thread::spawn(move || { if rx.recv_timeout(Duration::from_secs(10)) == Err(RecvTimeoutError::Timeout) { panic!("Failed to shut down the runtime in time"); } }); drop(tokio); drop(tx); _ = timeout.join(); }