DevTools: Display console messages and errors (#32727)

* feat: add streams to browsing context

* feat: console now works!

* feat: order console messages

* feat: add streams to new browsing contexts

* fix: apply suggestions

Co-authored-by: Martin Robinson <mrobinson@igalia.com>

---------

Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
eri 2024-07-09 20:27:47 +02:00 committed by GitHub
parent 34d9be70f9
commit 33f3c34d28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 141 additions and 119 deletions

View file

@ -16,7 +16,7 @@ use devtools_traits::EvaluateJSReply::{
ActorValue, BooleanValue, NullValue, NumberValue, StringValue, VoidValue,
};
use devtools_traits::{
CachedConsoleMessage, CachedConsoleMessageTypes, ConsoleAPI, ConsoleMessage,
CachedConsoleMessage, CachedConsoleMessageTypes, ConsoleLog, ConsoleMessage,
DevtoolScriptControlMsg, LogLevel, PageError,
};
use ipc_channel::ipc::{self, IpcSender};
@ -40,7 +40,7 @@ impl EncodableConsoleMessage for CachedConsoleMessage {
fn encode(&self) -> serde_json::Result<String> {
match *self {
CachedConsoleMessage::PageError(ref a) => serde_json::to_string(a),
CachedConsoleMessage::ConsoleAPI(ref a) => serde_json::to_string(a),
CachedConsoleMessage::ConsoleLog(ref a) => serde_json::to_string(a),
}
}
}
@ -141,23 +141,6 @@ impl ConsoleActor {
}
}
fn streams_mut(&self, registry: &ActorRegistry, cb: impl Fn(&mut TcpStream)) {
match &self.root {
Root::BrowsingContext(bc) => registry
.find::<BrowsingContextActor>(bc)
.streams
.borrow_mut()
.values_mut()
.for_each(cb),
Root::DedicatedWorker(worker) => registry
.find::<WorkerActor>(worker)
.streams
.borrow_mut()
.values_mut()
.for_each(cb),
}
}
fn current_unique_id(&self, registry: &ActorRegistry) -> UniqueId {
match &self.root {
Root::BrowsingContext(bc) => UniqueId::Pipeline(
@ -177,7 +160,7 @@ impl ConsoleActor {
) -> Result<EvaluateJSReply, ()> {
let input = msg.get("text").unwrap().as_str().unwrap().to_owned();
let (chan, port) = ipc::channel().unwrap();
// FIXME: redesign messages so we don't have to fake pipeline ids when
// FIXME: Redesign messages so we don't have to fake pipeline ids when
// communicating with workers.
let pipeline = match self.current_unique_id(registry) {
UniqueId::Pipeline(p) => p,
@ -191,7 +174,7 @@ impl ConsoleActor {
))
.unwrap();
//TODO: extract conversion into protocol module or some other useful place
// TODO: Extract conversion into protocol module or some other useful place
let result = match port.recv().map_err(|_| ())? {
VoidValue => {
let mut m = Map::new();
@ -227,7 +210,7 @@ impl ConsoleActor {
},
StringValue(s) => Value::String(s),
ActorValue { class, uuid } => {
//TODO: make initial ActorValue message include these properties?
// TODO: Make initial ActorValue message include these properties?
let mut m = Map::new();
let actor = ObjectActor::register(registry, uuid);
@ -241,12 +224,15 @@ impl ConsoleActor {
},
};
//TODO: catch and return exception values from JS evaluation
// TODO: Catch and return exception values from JS evaluation
let reply = EvaluateJSReply {
from: self.name(),
input,
result,
timestamp: 0,
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64,
exception: Value::Null,
exception_message: Value::Null,
helper_result: Value::Null,
@ -266,14 +252,11 @@ impl ConsoleActor {
.or_default()
.push(CachedConsoleMessage::PageError(page_error.clone()));
if id == self.current_unique_id(registry) {
let msg = PageErrorMsg {
from: self.name(),
type_: "pageError".to_owned(),
page_error,
if let Root::BrowsingContext(bc) = &self.root {
registry
.find::<BrowsingContextActor>(bc)
.page_error(page_error)
};
self.streams_mut(registry, |stream| {
let _ = stream.write_json_packet(&msg);
});
}
}
@ -292,42 +275,30 @@ impl ConsoleActor {
_ => "log",
}
.to_owned();
let console_api = ConsoleLog {
level: level.clone(),
filename: console_message.filename.clone(),
line_number: console_message.line_number as u32,
column_number: console_message.column_number as u32,
time_stamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64,
arguments: vec![console_message.message.clone()],
};
self.cached_events
.borrow_mut()
.entry(id.clone())
.or_default()
.push(CachedConsoleMessage::ConsoleAPI(ConsoleAPI {
type_: "ConsoleAPI".to_owned(),
level: level.clone(),
filename: console_message.filename.clone(),
line_number: console_message.line_number as u32,
function_name: "".to_string(), //TODO
time_stamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64,
private: false,
arguments: vec![console_message.message.clone()],
}));
.push(CachedConsoleMessage::ConsoleLog(console_api.clone()));
if id == self.current_unique_id(registry) {
let msg = ConsoleAPICall {
from: self.name(),
type_: "consoleAPICall".to_owned(),
message: ConsoleMsg {
level,
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64,
arguments: vec![console_message.message],
filename: console_message.filename,
line_number: console_message.line_number,
column_number: console_message.column_number,
},
if let Root::BrowsingContext(bc) = &self.root {
registry
.find::<BrowsingContextActor>(bc)
.console_message(console_api)
};
self.streams_mut(registry, |stream| {
let _ = stream.write_json_packet(&msg);
});
}
}
}
@ -385,7 +356,7 @@ impl Actor for ConsoleActor {
{
true
},
CachedConsoleMessage::ConsoleAPI(_)
CachedConsoleMessage::ConsoleLog(_)
if message_types.contains(CachedConsoleMessageTypes::CONSOLE_API) =>
{
true
@ -506,31 +477,3 @@ impl Actor for ConsoleActor {
})
}
}
#[derive(Serialize)]
struct ConsoleAPICall {
from: String,
#[serde(rename = "type")]
type_: String,
message: ConsoleMsg,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct ConsoleMsg {
level: String,
timestamp: u64,
arguments: Vec<String>,
filename: String,
line_number: usize,
column_number: usize,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct PageErrorMsg {
from: String,
#[serde(rename = "type")]
type_: String,
page_error: PageError,
}