refactor: unify CDP types in a single module (#21094)

This commit moves all Chrome Devtools Protocol messages to `cli/cdp.rs`
and refactors all places using these types to pull them from a common
place.

No functional changes.
This commit is contained in:
Bartek Iwańczuk 2023-11-05 23:58:59 +01:00 committed by GitHub
parent 68a964346d
commit fdb4953ea4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 225 additions and 240 deletions

View file

@ -424,3 +424,81 @@ pub type UnserializableValue = String;
/// <https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-UniqueDebuggerId> /// <https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-UniqueDebuggerId>
pub type UniqueDebuggerId = String; pub type UniqueDebuggerId = String;
/// <https://chromedevtools.github.io/devtools-protocol/tot/Debugger/#method-setScriptSource>
#[derive(Debug, Deserialize)]
pub struct SetScriptSourceResponse {
pub status: Status,
}
#[derive(Debug, Deserialize)]
pub enum Status {
Ok,
CompileError,
BlockedByActiveGenerator,
BlockedByActiveFunction,
BlockedByTopLevelEsModuleChange,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Debugger/#event-scriptParsed>
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ScriptParsed {
pub script_id: String,
pub url: String,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-CoverageRange>
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CoverageRange {
/// Start character index.
#[serde(rename = "startOffset")]
pub start_char_offset: usize,
/// End character index.
#[serde(rename = "endOffset")]
pub end_char_offset: usize,
pub count: i64,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-FunctionCoverage>
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FunctionCoverage {
pub function_name: String,
pub ranges: Vec<CoverageRange>,
pub is_block_coverage: bool,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-ScriptCoverage>
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ScriptCoverage {
pub script_id: String,
pub url: String,
pub functions: Vec<FunctionCoverage>,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#method-startPreciseCoverage>
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StartPreciseCoverageArgs {
pub call_count: bool,
pub detailed: bool,
pub allow_triggered_updates: bool,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#method-startPreciseCoverage>
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StartPreciseCoverageResponse {
pub timestamp: f64,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#method-takePreciseCoverage>
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TakePreciseCoverageResponse {
pub result: Vec<ScriptCoverage>,
pub timestamp: f64,
}

View file

@ -3,6 +3,7 @@
mod args; mod args;
mod auth_tokens; mod auth_tokens;
mod cache; mod cache;
mod cdp;
mod deno_std; mod deno_std;
mod emit; mod emit;
mod errors; mod errors;

View file

@ -1,60 +0,0 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use serde::Deserialize;
use serde::Serialize;
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CoverageRange {
/// Start character index.
#[serde(rename = "startOffset")]
pub start_char_offset: usize,
/// End character index.
#[serde(rename = "endOffset")]
pub end_char_offset: usize,
pub count: i64,
}
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FunctionCoverage {
pub function_name: String,
pub ranges: Vec<CoverageRange>,
pub is_block_coverage: bool,
}
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ScriptCoverage {
pub script_id: String,
pub url: String,
pub functions: Vec<FunctionCoverage>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StartPreciseCoverageParameters {
pub call_count: bool,
pub detailed: bool,
pub allow_triggered_updates: bool,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct StartPreciseCoverageReturnObject {
pub timestamp: f64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TakePreciseCoverageReturnObject {
pub result: Vec<ScriptCoverage>,
pub timestamp: f64,
}
// TODO(bartlomieju): remove me
#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ProcessCoverage {
pub result: Vec<ScriptCoverage>,
}

View file

@ -3,24 +3,26 @@
// Forked from https://github.com/demurgos/v8-coverage/tree/d0ca18da8740198681e0bc68971b0a6cdb11db3e/rust // Forked from https://github.com/demurgos/v8-coverage/tree/d0ca18da8740198681e0bc68971b0a6cdb11db3e/rust
// Copyright 2021 Charles Samborski. All rights reserved. MIT license. // Copyright 2021 Charles Samborski. All rights reserved. MIT license.
use super::json_types::CoverageRange;
use super::json_types::FunctionCoverage;
use super::json_types::ProcessCoverage;
use super::json_types::ScriptCoverage;
use super::range_tree::RangeTree; use super::range_tree::RangeTree;
use super::range_tree::RangeTreeArena; use super::range_tree::RangeTreeArena;
use crate::cdp;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::collections::HashMap; use std::collections::HashMap;
use std::iter::Peekable; use std::iter::Peekable;
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct ProcessCoverage {
pub result: Vec<cdp::ScriptCoverage>,
}
pub fn merge_processes( pub fn merge_processes(
mut processes: Vec<ProcessCoverage>, mut processes: Vec<ProcessCoverage>,
) -> Option<ProcessCoverage> { ) -> Option<ProcessCoverage> {
if processes.len() <= 1 { if processes.len() <= 1 {
return processes.pop(); return processes.pop();
} }
let mut url_to_scripts: BTreeMap<String, Vec<ScriptCoverage>> = let mut url_to_scripts: BTreeMap<String, Vec<cdp::ScriptCoverage>> =
BTreeMap::new(); BTreeMap::new();
for process_cov in processes { for process_cov in processes {
for script_cov in process_cov.result { for script_cov in process_cov.result {
@ -31,12 +33,13 @@ pub fn merge_processes(
} }
} }
let result: Vec<ScriptCoverage> = url_to_scripts let result: Vec<cdp::ScriptCoverage> = url_to_scripts
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(script_id, (_, scripts))| (script_id, scripts)) .map(|(script_id, (_, scripts))| (script_id, scripts))
.map(|(script_id, scripts)| { .map(|(script_id, scripts)| {
let mut merged: ScriptCoverage = merge_scripts(scripts.to_vec()).unwrap(); let mut merged: cdp::ScriptCoverage =
merge_scripts(scripts.to_vec()).unwrap();
merged.script_id = script_id.to_string(); merged.script_id = script_id.to_string();
merged merged
}) })
@ -46,21 +49,21 @@ pub fn merge_processes(
} }
pub fn merge_scripts( pub fn merge_scripts(
mut scripts: Vec<ScriptCoverage>, mut scripts: Vec<cdp::ScriptCoverage>,
) -> Option<ScriptCoverage> { ) -> Option<cdp::ScriptCoverage> {
if scripts.len() <= 1 { if scripts.len() <= 1 {
return scripts.pop(); return scripts.pop();
} }
let (script_id, url) = { let (script_id, url) = {
let first: &ScriptCoverage = &scripts[0]; let first: &cdp::ScriptCoverage = &scripts[0];
(first.script_id.clone(), first.url.clone()) (first.script_id.clone(), first.url.clone())
}; };
let mut range_to_funcs: BTreeMap<CharRange, Vec<FunctionCoverage>> = let mut range_to_funcs: BTreeMap<CharRange, Vec<cdp::FunctionCoverage>> =
BTreeMap::new(); BTreeMap::new();
for script_cov in scripts { for script_cov in scripts {
for func_cov in script_cov.functions { for func_cov in script_cov.functions {
let root_range = { let root_range = {
let root_range_cov: &CoverageRange = &func_cov.ranges[0]; let root_range_cov: &cdp::CoverageRange = &func_cov.ranges[0];
CharRange { CharRange {
start: root_range_cov.start_char_offset, start: root_range_cov.start_char_offset,
end: root_range_cov.end_char_offset, end: root_range_cov.end_char_offset,
@ -70,12 +73,12 @@ pub fn merge_scripts(
} }
} }
let functions: Vec<FunctionCoverage> = range_to_funcs let functions: Vec<cdp::FunctionCoverage> = range_to_funcs
.into_values() .into_values()
.map(|funcs| merge_functions(funcs).unwrap()) .map(|funcs| merge_functions(funcs).unwrap())
.collect(); .collect();
Some(ScriptCoverage { Some(cdp::ScriptCoverage {
script_id, script_id,
url, url,
functions, functions,
@ -105,8 +108,8 @@ impl PartialOrd for CharRange {
} }
pub fn merge_functions( pub fn merge_functions(
mut funcs: Vec<FunctionCoverage>, mut funcs: Vec<cdp::FunctionCoverage>,
) -> Option<FunctionCoverage> { ) -> Option<cdp::FunctionCoverage> {
if funcs.len() <= 1 { if funcs.len() <= 1 {
return funcs.pop(); return funcs.pop();
} }
@ -124,7 +127,7 @@ pub fn merge_functions(
let ranges = merged.to_ranges(); let ranges = merged.to_ranges();
let is_block_coverage: bool = !(ranges.len() == 1 && ranges[0].count == 0); let is_block_coverage: bool = !(ranges.len() == 1 && ranges[0].count == 0);
Some(FunctionCoverage { Some(cdp::FunctionCoverage {
function_name, function_name,
ranges, ranges,
is_block_coverage, is_block_coverage,
@ -439,13 +442,13 @@ mod tests {
fn two_flat_trees() { fn two_flat_trees() {
let inputs: Vec<ProcessCoverage> = vec![ let inputs: Vec<ProcessCoverage> = vec![
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![CoverageRange { ranges: vec![cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 1, count: 1,
@ -454,13 +457,13 @@ mod tests {
}], }],
}, },
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![CoverageRange { ranges: vec![cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 2, count: 2,
@ -470,13 +473,13 @@ mod tests {
}, },
]; ];
let expected: Option<ProcessCoverage> = Some(ProcessCoverage { let expected: Option<ProcessCoverage> = Some(ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![CoverageRange { ranges: vec![cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 3, count: 3,
@ -492,19 +495,19 @@ mod tests {
fn two_trees_with_matching_children() { fn two_trees_with_matching_children() {
let inputs: Vec<ProcessCoverage> = vec![ let inputs: Vec<ProcessCoverage> = vec![
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 10, count: 10,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 3, start_char_offset: 3,
end_char_offset: 6, end_char_offset: 6,
count: 1, count: 1,
@ -514,19 +517,19 @@ mod tests {
}], }],
}, },
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 20, count: 20,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 3, start_char_offset: 3,
end_char_offset: 6, end_char_offset: 6,
count: 2, count: 2,
@ -537,19 +540,19 @@ mod tests {
}, },
]; ];
let expected: Option<ProcessCoverage> = Some(ProcessCoverage { let expected: Option<ProcessCoverage> = Some(ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 30, count: 30,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 3, start_char_offset: 3,
end_char_offset: 6, end_char_offset: 6,
count: 3, count: 3,
@ -566,19 +569,19 @@ mod tests {
fn two_trees_with_partially_overlapping_children() { fn two_trees_with_partially_overlapping_children() {
let inputs: Vec<ProcessCoverage> = vec![ let inputs: Vec<ProcessCoverage> = vec![
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 10, count: 10,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 2, start_char_offset: 2,
end_char_offset: 5, end_char_offset: 5,
count: 1, count: 1,
@ -588,19 +591,19 @@ mod tests {
}], }],
}, },
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 20, count: 20,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 4, start_char_offset: 4,
end_char_offset: 7, end_char_offset: 7,
count: 2, count: 2,
@ -611,29 +614,29 @@ mod tests {
}, },
]; ];
let expected: Option<ProcessCoverage> = Some(ProcessCoverage { let expected: Option<ProcessCoverage> = Some(ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 30, count: 30,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 2, start_char_offset: 2,
end_char_offset: 5, end_char_offset: 5,
count: 21, count: 21,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 4, start_char_offset: 4,
end_char_offset: 5, end_char_offset: 5,
count: 3, count: 3,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 5, start_char_offset: 5,
end_char_offset: 7, end_char_offset: 7,
count: 12, count: 12,
@ -650,29 +653,29 @@ mod tests {
fn two_trees_with_with_complementary_children_summing_to_the_same_count() { fn two_trees_with_with_complementary_children_summing_to_the_same_count() {
let inputs: Vec<ProcessCoverage> = vec![ let inputs: Vec<ProcessCoverage> = vec![
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 1, count: 1,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 1, start_char_offset: 1,
end_char_offset: 8, end_char_offset: 8,
count: 6, count: 6,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 1, start_char_offset: 1,
end_char_offset: 5, end_char_offset: 5,
count: 5, count: 5,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 5, start_char_offset: 5,
end_char_offset: 8, end_char_offset: 8,
count: 7, count: 7,
@ -682,29 +685,29 @@ mod tests {
}], }],
}, },
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 4, count: 4,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 1, start_char_offset: 1,
end_char_offset: 8, end_char_offset: 8,
count: 8, count: 8,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 1, start_char_offset: 1,
end_char_offset: 5, end_char_offset: 5,
count: 9, count: 9,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 5, start_char_offset: 5,
end_char_offset: 8, end_char_offset: 8,
count: 7, count: 7,
@ -715,19 +718,19 @@ mod tests {
}, },
]; ];
let expected: Option<ProcessCoverage> = Some(ProcessCoverage { let expected: Option<ProcessCoverage> = Some(ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 5, count: 5,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 1, start_char_offset: 1,
end_char_offset: 8, end_char_offset: 8,
count: 14, count: 14,
@ -744,19 +747,19 @@ mod tests {
fn merges_a_similar_sliding_chain_a_bc() { fn merges_a_similar_sliding_chain_a_bc() {
let inputs: Vec<ProcessCoverage> = vec![ let inputs: Vec<ProcessCoverage> = vec![
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 7, end_char_offset: 7,
count: 10, count: 10,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 4, end_char_offset: 4,
count: 1, count: 1,
@ -766,24 +769,24 @@ mod tests {
}], }],
}, },
ProcessCoverage { ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 7, end_char_offset: 7,
count: 20, count: 20,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 1, start_char_offset: 1,
end_char_offset: 6, end_char_offset: 6,
count: 11, count: 11,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 2, start_char_offset: 2,
end_char_offset: 5, end_char_offset: 5,
count: 2, count: 2,
@ -794,29 +797,29 @@ mod tests {
}, },
]; ];
let expected: Option<ProcessCoverage> = Some(ProcessCoverage { let expected: Option<ProcessCoverage> = Some(ProcessCoverage {
result: vec![ScriptCoverage { result: vec![cdp::ScriptCoverage {
script_id: String::from("0"), script_id: String::from("0"),
url: String::from("/lib.js"), url: String::from("/lib.js"),
functions: vec![FunctionCoverage { functions: vec![cdp::FunctionCoverage {
function_name: String::from("lib"), function_name: String::from("lib"),
is_block_coverage: true, is_block_coverage: true,
ranges: vec![ ranges: vec![
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 7, end_char_offset: 7,
count: 30, count: 30,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 6, end_char_offset: 6,
count: 21, count: 21,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 1, start_char_offset: 1,
end_char_offset: 5, end_char_offset: 5,
count: 12, count: 12,
}, },
CoverageRange { cdp::CoverageRange {
start_char_offset: 2, start_char_offset: 2,
end_char_offset: 4, end_char_offset: 4,
count: 3, count: 3,

View file

@ -3,6 +3,7 @@
use crate::args::CoverageFlags; use crate::args::CoverageFlags;
use crate::args::FileFlags; use crate::args::FileFlags;
use crate::args::Flags; use crate::args::Flags;
use crate::cdp;
use crate::colors; use crate::colors;
use crate::factory::CliFactory; use crate::factory::CliFactory;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
@ -34,11 +35,9 @@ use std::path::PathBuf;
use text_lines::TextLines; use text_lines::TextLines;
use uuid::Uuid; use uuid::Uuid;
mod json_types;
mod merge; mod merge;
mod range_tree; mod range_tree;
use merge::ProcessCoverage;
use json_types::*;
pub struct CoverageCollector { pub struct CoverageCollector {
pub dir: PathBuf, pub dir: PathBuf,
@ -84,8 +83,8 @@ impl CoverageCollector {
async fn start_precise_coverage( async fn start_precise_coverage(
&mut self, &mut self,
parameters: StartPreciseCoverageParameters, parameters: cdp::StartPreciseCoverageArgs,
) -> Result<StartPreciseCoverageReturnObject, AnyError> { ) -> Result<cdp::StartPreciseCoverageResponse, AnyError> {
let return_value = self let return_value = self
.session .session
.post_message("Profiler.startPreciseCoverage", Some(parameters)) .post_message("Profiler.startPreciseCoverage", Some(parameters))
@ -98,7 +97,7 @@ impl CoverageCollector {
async fn take_precise_coverage( async fn take_precise_coverage(
&mut self, &mut self,
) -> Result<TakePreciseCoverageReturnObject, AnyError> { ) -> Result<cdp::TakePreciseCoverageResponse, AnyError> {
let return_value = self let return_value = self
.session .session
.post_message::<()>("Profiler.takePreciseCoverage", None) .post_message::<()>("Profiler.takePreciseCoverage", None)
@ -113,7 +112,7 @@ impl CoverageCollector {
self.enable_debugger().await?; self.enable_debugger().await?;
self.enable_profiler().await?; self.enable_profiler().await?;
self self
.start_precise_coverage(StartPreciseCoverageParameters { .start_precise_coverage(cdp::StartPreciseCoverageArgs {
call_count: true, call_count: true,
detailed: true, detailed: true,
allow_triggered_updates: false, allow_triggered_updates: false,
@ -180,7 +179,7 @@ struct CoverageReport {
} }
fn generate_coverage_report( fn generate_coverage_report(
script_coverage: &ScriptCoverage, script_coverage: &cdp::ScriptCoverage,
script_source: String, script_source: String,
maybe_source_map: &Option<Vec<u8>>, maybe_source_map: &Option<Vec<u8>>,
output: &Option<PathBuf>, output: &Option<PathBuf>,
@ -570,8 +569,8 @@ impl CoverageReporter for PrettyCoverageReporter {
fn collect_coverages( fn collect_coverages(
files: FileFlags, files: FileFlags,
) -> Result<Vec<ScriptCoverage>, AnyError> { ) -> Result<Vec<cdp::ScriptCoverage>, AnyError> {
let mut coverages: Vec<ScriptCoverage> = Vec::new(); let mut coverages: Vec<cdp::ScriptCoverage> = Vec::new();
let file_paths = FileCollector::new(|file_path| { let file_paths = FileCollector::new(|file_path| {
file_path file_path
.extension() .extension()
@ -590,7 +589,7 @@ fn collect_coverages(
for file_path in file_paths { for file_path in file_paths {
let json = fs::read_to_string(file_path.as_path())?; let json = fs::read_to_string(file_path.as_path())?;
let new_coverage: ScriptCoverage = serde_json::from_str(&json)?; let new_coverage: cdp::ScriptCoverage = serde_json::from_str(&json)?;
coverages.push(new_coverage); coverages.push(new_coverage);
} }
@ -600,11 +599,11 @@ fn collect_coverages(
} }
fn filter_coverages( fn filter_coverages(
coverages: Vec<ScriptCoverage>, coverages: Vec<cdp::ScriptCoverage>,
include: Vec<String>, include: Vec<String>,
exclude: Vec<String>, exclude: Vec<String>,
npm_resolver: &dyn CliNpmResolver, npm_resolver: &dyn CliNpmResolver,
) -> Vec<ScriptCoverage> { ) -> Vec<cdp::ScriptCoverage> {
let include: Vec<Regex> = let include: Vec<Regex> =
include.iter().map(|e| Regex::new(e).unwrap()).collect(); include.iter().map(|e| Regex::new(e).unwrap()).collect();
@ -629,7 +628,7 @@ fn filter_coverages(
(include.is_empty() || is_included) && !is_excluded && !is_internal (include.is_empty() || is_included) && !is_excluded && !is_internal
}) })
.collect::<Vec<ScriptCoverage>>() .collect::<Vec<cdp::ScriptCoverage>>()
} }
pub async fn cover_files( pub async fn cover_files(

View file

@ -3,7 +3,7 @@
// Forked from https://github.com/demurgos/v8-coverage/tree/d0ca18da8740198681e0bc68971b0a6cdb11db3e/rust // Forked from https://github.com/demurgos/v8-coverage/tree/d0ca18da8740198681e0bc68971b0a6cdb11db3e/rust
// Copyright 2021 Charles Samborski. All rights reserved. MIT license. // Copyright 2021 Charles Samborski. All rights reserved. MIT license.
use super::json_types::CoverageRange; use crate::cdp;
use std::iter::Peekable; use std::iter::Peekable;
use typed_arena::Arena; use typed_arena::Arena;
@ -126,12 +126,12 @@ impl<'rt> RangeTree<'rt> {
tree tree
} }
pub fn to_ranges(&self) -> Vec<CoverageRange> { pub fn to_ranges(&self) -> Vec<cdp::CoverageRange> {
let mut ranges: Vec<CoverageRange> = Vec::new(); let mut ranges: Vec<cdp::CoverageRange> = Vec::new();
let mut stack: Vec<(&RangeTree, i64)> = vec![(self, 0)]; let mut stack: Vec<(&RangeTree, i64)> = vec![(self, 0)];
while let Some((cur, parent_count)) = stack.pop() { while let Some((cur, parent_count)) = stack.pop() {
let count: i64 = parent_count + cur.delta; let count: i64 = parent_count + cur.delta;
ranges.push(CoverageRange { ranges.push(cdp::CoverageRange {
start_char_offset: cur.start, start_char_offset: cur.start,
end_char_offset: cur.end, end_char_offset: cur.end,
count, count,
@ -145,7 +145,7 @@ impl<'rt> RangeTree<'rt> {
pub fn from_sorted_ranges<'a>( pub fn from_sorted_ranges<'a>(
rta: &'a RangeTreeArena<'a>, rta: &'a RangeTreeArena<'a>,
ranges: &[CoverageRange], ranges: &[cdp::CoverageRange],
) -> Option<&'a mut RangeTree<'a>> { ) -> Option<&'a mut RangeTree<'a>> {
Self::from_sorted_ranges_inner( Self::from_sorted_ranges_inner(
rta, rta,
@ -157,7 +157,7 @@ impl<'rt> RangeTree<'rt> {
fn from_sorted_ranges_inner<'a, 'b, 'c: 'b>( fn from_sorted_ranges_inner<'a, 'b, 'c: 'b>(
rta: &'a RangeTreeArena<'a>, rta: &'a RangeTreeArena<'a>,
ranges: &'b mut Peekable<impl Iterator<Item = &'c CoverageRange>>, ranges: &'b mut Peekable<impl Iterator<Item = &'c cdp::CoverageRange>>,
parent_end: usize, parent_end: usize,
parent_count: i64, parent_count: i64,
) -> Option<&'a mut RangeTree<'a>> { ) -> Option<&'a mut RangeTree<'a>> {
@ -190,7 +190,7 @@ mod tests {
#[test] #[test]
fn from_sorted_ranges_empty() { fn from_sorted_ranges_empty() {
let rta = RangeTreeArena::new(); let rta = RangeTreeArena::new();
let inputs: Vec<CoverageRange> = vec![CoverageRange { let inputs: Vec<cdp::CoverageRange> = vec![cdp::CoverageRange {
start_char_offset: 0, start_char_offset: 0,
end_char_offset: 9, end_char_offset: 9,
count: 1, count: 1,

View file

@ -8,8 +8,8 @@ use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use crate::cdp;
use crate::tools::repl; use crate::tools::repl;
use crate::tools::repl::cdp;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures; use deno_core::futures;
use deno_core::serde_json; use deno_core::serde_json;
@ -382,7 +382,7 @@ impl JupyterServer {
} }
}; };
let repl::cdp::EvaluateResponse { let cdp::EvaluateResponse {
result, result,
exception_details, exception_details,
} = evaluate_response.value; } = evaluate_response.value;

View file

@ -1,5 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use crate::cdp;
use crate::colors; use crate::colors;
use deno_ast::swc::parser::error::SyntaxError; use deno_ast::swc::parser::error::SyntaxError;
use deno_ast::swc::parser::token::BinOpToken; use deno_ast::swc::parser::token::BinOpToken;
@ -37,7 +38,6 @@ use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::Relaxed; use std::sync::atomic::Ordering::Relaxed;
use std::sync::Arc; use std::sync::Arc;
use super::cdp;
use super::channel::RustylineSyncMessageSender; use super::channel::RustylineSyncMessageSender;
use super::session::REPL_INTERNALS_NAME; use super::session::REPL_INTERNALS_NAME;

View file

@ -14,7 +14,6 @@ use deno_runtime::permissions::PermissionsContainer;
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
use tokio::sync::mpsc::unbounded_channel; use tokio::sync::mpsc::unbounded_channel;
pub(crate) mod cdp;
mod channel; mod channel;
mod editor; mod editor;
mod session; mod session;

View file

@ -5,6 +5,7 @@ use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use crate::args::CliOptions; use crate::args::CliOptions;
use crate::cdp;
use crate::colors; use crate::colors;
use crate::lsp::ReplLanguageServer; use crate::lsp::ReplLanguageServer;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
@ -48,8 +49,6 @@ use once_cell::sync::Lazy;
use regex::Match; use regex::Match;
use regex::Regex; use regex::Regex;
use super::cdp;
fn comment_source_to_position_range( fn comment_source_to_position_range(
comment_start: SourcePos, comment_start: SourcePos,
m: &Match, m: &Match,

View file

@ -1,5 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use crate::cdp;
use crate::emit::Emitter; use crate::emit::Emitter;
use crate::util::file_watcher::WatcherCommunicator; use crate::util::file_watcher::WatcherCommunicator;
use crate::util::file_watcher::WatcherRestartMode; use crate::util::file_watcher::WatcherRestartMode;
@ -7,21 +8,45 @@ use deno_core::error::generic_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::StreamExt; use deno_core::futures::StreamExt;
use deno_core::serde_json::json; use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::serde_json::{self}; use deno_core::serde_json::{self};
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::LocalInspectorSession; use deno_core::LocalInspectorSession;
use deno_runtime::colors; use deno_runtime::colors;
use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use tokio::select; use tokio::select;
mod json_types; // TODO(bartlomieju): the same thing is used in the REPL. Deduplicate.
#[derive(Debug, Deserialize)]
pub struct RpcNotification {
pub method: String,
pub params: Value,
}
use json_types::RpcNotification; fn explain(status: &cdp::Status) -> &'static str {
use json_types::ScriptParsed; match status {
use json_types::SetScriptSourceReturnObject; cdp::Status::Ok => "OK",
use json_types::Status; cdp::Status::CompileError => "compile error",
cdp::Status::BlockedByActiveGenerator => "blocked by active generator",
cdp::Status::BlockedByActiveFunction => "blocked by active function",
cdp::Status::BlockedByTopLevelEsModuleChange => {
"blocked by top-level ES module change"
}
}
}
fn should_retry(status: &cdp::Status) -> bool {
match status {
cdp::Status::Ok => false,
cdp::Status::CompileError => false,
cdp::Status::BlockedByActiveGenerator => true,
cdp::Status::BlockedByActiveFunction => true,
cdp::Status::BlockedByTopLevelEsModuleChange => false,
}
}
/// This structure is responsible for providing Hot Module Replacement /// This structure is responsible for providing Hot Module Replacement
/// functionality. /// functionality.
@ -102,7 +127,7 @@ impl HmrRunner {
&mut self, &mut self,
script_id: &str, script_id: &str,
source: &str, source: &str,
) -> Result<SetScriptSourceReturnObject, AnyError> { ) -> Result<cdp::SetScriptSourceResponse, AnyError> {
let result = self let result = self
.session .session
.post_message( .post_message(
@ -115,7 +140,7 @@ impl HmrRunner {
) )
.await?; .await?;
Ok(serde_json::from_value::<SetScriptSourceReturnObject>( Ok(serde_json::from_value::<cdp::SetScriptSourceResponse>(
result, result,
)?) )?)
} }
@ -162,7 +187,7 @@ impl HmrRunner {
let description = exception.get("description").and_then(|d| d.as_str()).unwrap_or("undefined"); let description = exception.get("description").and_then(|d| d.as_str()).unwrap_or("undefined");
break Err(generic_error(format!("{text} {description}"))); break Err(generic_error(format!("{text} {description}")));
} else if notification.method == "Debugger.scriptParsed" { } else if notification.method == "Debugger.scriptParsed" {
let params = serde_json::from_value::<ScriptParsed>(notification.params)?; let params = serde_json::from_value::<cdp::ScriptParsed>(notification.params)?;
if params.url.starts_with("file://") { if params.url.starts_with("file://") {
let file_url = Url::parse(&params.url).unwrap(); let file_url = Url::parse(&params.url).unwrap();
let file_path = file_url.to_file_path().unwrap(); let file_path = file_url.to_file_path().unwrap();
@ -217,14 +242,14 @@ impl HmrRunner {
loop { loop {
let result = self.set_script_source(&id, source_code.as_str()).await?; let result = self.set_script_source(&id, source_code.as_str()).await?;
if matches!(result.status, Status::Ok) { if matches!(result.status, cdp::Status::Ok) {
self.dispatch_hmr_event(module_url.as_str()).await?; self.dispatch_hmr_event(module_url.as_str()).await?;
self.watcher_communicator.print(format!("Replaced changed module {}", module_url.as_str())); self.watcher_communicator.print(format!("Replaced changed module {}", module_url.as_str()));
break; break;
} }
self.watcher_communicator.print(format!("Failed to reload module {}: {}.", module_url, colors::gray(result.status.explain()))); self.watcher_communicator.print(format!("Failed to reload module {}: {}.", module_url, colors::gray(explain(&result.status))));
if result.status.should_retry() && tries <= 2 { if should_retry(&result.status) && tries <= 2 {
tries += 1; tries += 1;
tokio::time::sleep(std::time::Duration::from_millis(100)).await; tokio::time::sleep(std::time::Duration::from_millis(100)).await;
continue; continue;

View file

@ -1,59 +0,0 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
// TODO(bartlomieju): this code should be factored out to `cli/cdp.rs` along
// with code in `cli/tools/repl/` and `cli/tools/coverage/`. These are all
// Chrome Devtools Protocol message types.
use deno_core::serde_json::Value;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct RpcNotification {
pub method: String,
pub params: Value,
}
#[derive(Debug, Deserialize)]
pub struct SetScriptSourceReturnObject {
pub status: Status,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ScriptParsed {
pub script_id: String,
pub url: String,
}
#[derive(Debug, Deserialize)]
pub enum Status {
Ok,
CompileError,
BlockedByActiveGenerator,
BlockedByActiveFunction,
BlockedByTopLevelEsModuleChange,
}
impl Status {
pub(crate) fn explain(&self) -> &'static str {
match self {
Status::Ok => "OK",
Status::CompileError => "compile error",
Status::BlockedByActiveGenerator => "blocked by active generator",
Status::BlockedByActiveFunction => "blocked by active function",
Status::BlockedByTopLevelEsModuleChange => {
"blocked by top-level ES module change"
}
}
}
pub(crate) fn should_retry(&self) -> bool {
match self {
Status::Ok => false,
Status::CompileError => false,
Status::BlockedByActiveGenerator => true,
Status::BlockedByActiveFunction => true,
Status::BlockedByTopLevelEsModuleChange => false,
}
}
}