Skip to content

Commit 5ee0357

Browse files
bartlomiejuTango992
authored andcommitted
refactor: Rewrite usages of V8 inspector to the new API (denoland#30743)
Based on denoland/deno_core#1193. This commit rewrites 3 parts of the system to use a new "sync" V8 inspector API exposed by `deno_core`: - REPL - coverage collection - hot module replacement Turns out the async abstraction over V8 inspector was unnecessary and actually greatly complicated usage of the inspector. Towards denoland#13572 Towards denoland#13206
1 parent fe320f4 commit 5ee0357

File tree

13 files changed

+503
-342
lines changed

13 files changed

+503
-342
lines changed

Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ repository = "https://github.com/denoland/deno"
6262

6363
[workspace.dependencies]
6464
deno_ast = { version = "=0.50.0", features = ["transpiling"] }
65-
deno_core = { version = "0.357.0" }
65+
deno_core = { version = "0.358.0" }
6666

6767
deno_cache_dir = "=0.25.0"
6868
deno_doc = "=0.183.0"

cli/factory.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ use crate::resolver::CliResolver;
9999
use crate::resolver::on_resolve_diagnostic;
100100
use crate::standalone::binary::DenoCompileBinaryWriter;
101101
use crate::sys::CliSys;
102-
use crate::tools::coverage::CoverageCollector;
102+
use crate::tools::coverage::CoverageCollectorState;
103103
use crate::tools::installer::BinNameResolver;
104104
use crate::tools::lint::LintRuleProvider;
105-
use crate::tools::run::hmr::HmrRunner;
105+
use crate::tools::run::hmr::HmrRunnerState;
106106
use crate::tsc::TypeCheckingCjsTracker;
107107
use crate::type_checker::TypeChecker;
108108
use crate::util::file_watcher::WatcherCommunicator;
@@ -1106,8 +1106,8 @@ impl CliFactory {
11061106
let create_hmr_runner = if cli_options.has_hmr() {
11071107
let watcher_communicator = self.watcher_communicator.clone().unwrap();
11081108
let emitter = self.emitter()?.clone();
1109-
let fn_: crate::worker::CreateHmrRunnerCb = Box::new(move |session| {
1110-
HmrRunner::new(emitter.clone(), session, watcher_communicator.clone())
1109+
let fn_: crate::worker::CreateHmrRunnerCb = Box::new(move || {
1110+
HmrRunnerState::new(emitter.clone(), watcher_communicator.clone())
11111111
});
11121112
Some(fn_)
11131113
} else {
@@ -1116,9 +1116,7 @@ impl CliFactory {
11161116
let create_coverage_collector =
11171117
if let Some(coverage_dir) = cli_options.coverage_dir() {
11181118
let fn_: crate::worker::CreateCoverageCollectorCb =
1119-
Box::new(move |session| {
1120-
CoverageCollector::new(coverage_dir.clone(), session)
1121-
});
1119+
Box::new(move || CoverageCollectorState::new(coverage_dir.clone()));
11221120
Some(fn_)
11231121
} else {
11241122
None

cli/lib/worker.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -816,8 +816,11 @@ impl LibMainWorker {
816816
}
817817

818818
#[inline]
819-
pub fn create_inspector_session(&mut self) -> LocalInspectorSession {
820-
self.worker.create_inspector_session()
819+
pub fn create_inspector_session(
820+
&mut self,
821+
cb: deno_core::InspectorSessionSend,
822+
) -> LocalInspectorSession {
823+
self.worker.create_inspector_session(cb)
821824
}
822825

823826
#[inline]

cli/tools/coverage/mod.rs

Lines changed: 99 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::io::Write;
77
use std::path::Path;
88
use std::path::PathBuf;
99
use std::sync::Arc;
10+
use std::sync::atomic::AtomicI32;
1011

1112
use deno_ast::MediaType;
1213
use deno_ast::ModuleKind;
@@ -15,17 +16,15 @@ use deno_config::glob::FileCollector;
1516
use deno_config::glob::FilePatterns;
1617
use deno_config::glob::PathOrPattern;
1718
use deno_config::glob::PathOrPatternSet;
18-
use deno_core::InspectorPostMessageError;
19-
use deno_core::InspectorPostMessageErrorKind;
2019
use deno_core::LocalInspectorSession;
2120
use deno_core::anyhow::Context;
2221
use deno_core::anyhow::anyhow;
2322
use deno_core::error::AnyError;
2423
use deno_core::error::CoreError;
24+
use deno_core::parking_lot::Mutex;
2525
use deno_core::serde_json;
2626
use deno_core::sourcemap::SourceMap;
2727
use deno_core::url::Url;
28-
use deno_error::JsErrorBox;
2928
use deno_resolver::npm::DenoInNpmPackageChecker;
3029
use node_resolver::InNpmPackageChecker;
3130
use regex::Regex;
@@ -55,36 +54,47 @@ pub mod reporter;
5554
mod util;
5655
use merge::ProcessCoverage;
5756

58-
pub struct CoverageCollector {
59-
pub dir: PathBuf,
60-
session: LocalInspectorSession,
57+
static NEXT_MSG_ID: AtomicI32 = AtomicI32::new(0);
58+
59+
fn next_msg_id() -> i32 {
60+
NEXT_MSG_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
6161
}
6262

63-
impl CoverageCollector {
64-
pub fn new(dir: PathBuf, session: LocalInspectorSession) -> Self {
65-
Self { dir, session }
66-
}
63+
#[derive(Debug)]
64+
pub struct CoverageCollectorInner {
65+
dir: PathBuf,
66+
coverage_msg_id: Option<i32>,
67+
}
6768

68-
pub async fn start_collecting(
69-
&mut self,
70-
) -> Result<(), InspectorPostMessageError> {
71-
self.enable_debugger().await?;
72-
self.enable_profiler().await?;
73-
self
74-
.start_precise_coverage(cdp::StartPreciseCoverageArgs {
75-
call_count: true,
76-
detailed: true,
77-
allow_triggered_updates: false,
78-
})
79-
.await?;
69+
#[derive(Clone, Debug)]
70+
pub struct CoverageCollectorState(Arc<Mutex<CoverageCollectorInner>>);
8071

81-
Ok(())
72+
impl CoverageCollectorState {
73+
pub fn new(dir: PathBuf) -> Self {
74+
Self(Arc::new(Mutex::new(CoverageCollectorInner {
75+
dir,
76+
coverage_msg_id: None,
77+
})))
8278
}
8379

84-
pub async fn stop_collecting(&mut self) -> Result<(), CoreError> {
85-
fs::create_dir_all(&self.dir)?;
80+
pub fn callback(&self, msg: deno_core::InspectorMsg) {
81+
let deno_core::InspectorMsgKind::Message(msg_id) = msg.kind else {
82+
return;
83+
};
84+
let maybe_coverage_msg_id = self.0.lock().coverage_msg_id.as_ref().cloned();
85+
86+
if let Some(coverage_msg_id) = maybe_coverage_msg_id
87+
&& coverage_msg_id == msg_id
88+
{
89+
let message: serde_json::Value =
90+
serde_json::from_str(&msg.content).unwrap();
91+
let coverages: cdp::TakePreciseCoverageResponse =
92+
serde_json::from_value(message["result"].clone()).unwrap();
93+
self.write_coverages(coverages.result);
94+
}
95+
}
8696

87-
let script_coverages = self.take_precise_coverage().await?.result;
97+
fn write_coverages(&self, script_coverages: Vec<cdp::ScriptCoverage>) {
8898
for script_coverage in script_coverages {
8999
// Filter out internal and http/https JS files, eval'd scripts,
90100
// and scripts with invalid urls from being included in coverage reports
@@ -100,92 +110,86 @@ impl CoverageCollector {
100110
}
101111

102112
let filename = format!("{}.json", Uuid::new_v4());
103-
let filepath = self.dir.join(filename);
104-
105-
let mut out = BufWriter::new(File::create(&filepath)?);
106-
let coverage = serde_json::to_string(&script_coverage)
107-
.map_err(JsErrorBox::from_err)?;
113+
let filepath = self.0.lock().dir.join(filename);
114+
115+
let file = match File::create(&filepath) {
116+
Ok(f) => f,
117+
Err(err) => {
118+
log::error!(
119+
"Failed to create coverage file at {:?}, reason: {:?}",
120+
filepath,
121+
err
122+
);
123+
continue;
124+
}
125+
};
126+
let mut out = BufWriter::new(file);
127+
let coverage = serde_json::to_string(&script_coverage).unwrap();
108128
let formatted_coverage =
109129
format_json(&filepath, &coverage, &Default::default())
110130
.ok()
111131
.flatten()
112132
.unwrap_or(coverage);
113133

114-
out.write_all(formatted_coverage.as_bytes())?;
115-
out.flush()?;
134+
if let Err(err) = out.write_all(formatted_coverage.as_bytes()) {
135+
log::error!(
136+
"Failed to write coverage file at {:?}, reason: {:?}",
137+
filepath,
138+
err
139+
);
140+
continue;
141+
}
142+
if let Err(err) = out.flush() {
143+
log::error!(
144+
"Failed to flush coverage file at {:?}, reason: {:?}",
145+
filepath,
146+
err
147+
);
148+
continue;
149+
}
116150
}
117-
118-
self.disable_debugger().await?;
119-
self.disable_profiler().await?;
120-
121-
Ok(())
122-
}
123-
124-
async fn enable_debugger(&mut self) -> Result<(), InspectorPostMessageError> {
125-
self
126-
.session
127-
.post_message::<()>("Debugger.enable", None)
128-
.await?;
129-
Ok(())
130151
}
152+
}
131153

132-
async fn enable_profiler(&mut self) -> Result<(), InspectorPostMessageError> {
133-
self
134-
.session
135-
.post_message::<()>("Profiler.enable", None)
136-
.await?;
137-
Ok(())
138-
}
154+
pub struct CoverageCollector {
155+
pub state: CoverageCollectorState,
156+
session: LocalInspectorSession,
157+
}
139158

140-
async fn disable_debugger(
141-
&mut self,
142-
) -> Result<(), InspectorPostMessageError> {
143-
self
144-
.session
145-
.post_message::<()>("Debugger.disable", None)
146-
.await?;
147-
Ok(())
159+
impl CoverageCollector {
160+
pub fn new(
161+
state: CoverageCollectorState,
162+
session: LocalInspectorSession,
163+
) -> Self {
164+
Self { state, session }
148165
}
149166

150-
async fn disable_profiler(
151-
&mut self,
152-
) -> Result<(), InspectorPostMessageError> {
167+
pub fn start_collecting(&mut self) {
153168
self
154169
.session
155-
.post_message::<()>("Profiler.disable", None)
156-
.await?;
157-
Ok(())
158-
}
159-
160-
async fn start_precise_coverage(
161-
&mut self,
162-
parameters: cdp::StartPreciseCoverageArgs,
163-
) -> Result<cdp::StartPreciseCoverageResponse, InspectorPostMessageError> {
164-
let return_value = self
165-
.session
166-
.post_message("Profiler.startPreciseCoverage", Some(parameters))
167-
.await?;
168-
169-
let return_object = serde_json::from_value(return_value).map_err(|e| {
170-
InspectorPostMessageErrorKind::JsBox(JsErrorBox::from_err(e)).into_box()
171-
})?;
172-
173-
Ok(return_object)
170+
.post_message::<()>(next_msg_id(), "Profiler.enable", None);
171+
self.session.post_message(
172+
next_msg_id(),
173+
"Profiler.startPreciseCoverage",
174+
Some(cdp::StartPreciseCoverageArgs {
175+
call_count: true,
176+
detailed: true,
177+
allow_triggered_updates: false,
178+
}),
179+
);
174180
}
175181

176-
async fn take_precise_coverage(
177-
&mut self,
178-
) -> Result<cdp::TakePreciseCoverageResponse, InspectorPostMessageError> {
179-
let return_value = self
180-
.session
181-
.post_message::<()>("Profiler.takePreciseCoverage", None)
182-
.await?;
182+
pub fn stop_collecting(&mut self) -> Result<(), CoreError> {
183+
fs::create_dir_all(&self.state.0.lock().dir)?;
184+
let msg_id = next_msg_id();
185+
self.state.0.lock().coverage_msg_id.replace(msg_id);
183186

184-
let return_object = serde_json::from_value(return_value).map_err(|e| {
185-
InspectorPostMessageErrorKind::JsBox(JsErrorBox::from_err(e)).into_box()
186-
})?;
187-
188-
Ok(return_object)
187+
self.session.post_message::<()>(
188+
msg_id,
189+
"Profiler.takePreciseCoverage",
190+
None,
191+
);
192+
Ok(())
189193
}
190194
}
191195

0 commit comments

Comments
 (0)