如何用Rust的headless_chrome crate检测JavaScript错误
解决headless_chrome捕获JS错误/console.assert的问题
原代码的问题在于console.assert(false)不会触发DebuggerPaused事件——这个事件仅在调试器断点触发或未捕获异常导致暂停时才会触发,而console.assert只是在控制台输出一条错误日志,不会主动暂停调试器。
下面提供两种可行的捕获方式:
方式一:捕获console错误(包括console.assert)
通过监听Log.entryAdded事件,可以捕获所有控制台输出的日志,包括console.assert产生的错误:
use headless_chrome::{protocol::cdp::{Log::Event::EntryAdded as LogEntryAdded, types::Event}, Browser, LaunchOptions}; use std::{error::Error, sync::Arc}; fn main() -> Result<(), Box<dyn Error>> { let browser = Browser::new( LaunchOptions::default_builder() .window_size(Some((2000, 2000))) .build() .expect("Could not find chrome-executable"), )?; let tab = browser.new_tab()?; tab.enable_log().unwrap(); // 必须启用Log域 // 监听Log.entryAdded事件 let _events = tab.add_event_listener(Arc::new(move |event: &Event| { if let Event::LogEntryAdded(added_event) = event { let entry = &added_event.entry; // 筛选Error级别的日志,console.assert属于此类 if entry.level == "error" { dbg!("捕获到console错误:", entry.message); if entry.message.contains("Assertion failed") { println!("检测到console.assert失败"); } } } }))?; // 执行console.assert let _remote_object = tab.evaluate("console.assert(false, '自定义断言消息');", true).unwrap(); std::thread::sleep(std::time::Duration::from_secs(1)); Ok(()) }
方式二:捕获未捕获的JS异常
如果需要捕获主动抛出的JS异常(比如throw new Error()),可以监听Debugger.exceptionThrown事件,并设置调试器在异常时暂停:
use headless_chrome::{protocol::cdp::{Debugger::Event::ExceptionThrown, types::Event}, Browser, LaunchOptions}; use std::{error::Error, sync::Arc}; fn main() -> Result<(), Box<dyn Error>> { let browser = Browser::new( LaunchOptions::default_builder() .window_size(Some((2000, 2000))) .build() .expect("Could not find chrome-executable"), )?; let tab = browser.new_tab()?; tab.enable_debugger().unwrap(); // 启用Debugger域 // 设置调试器在未捕获异常时暂停 tab.debugger_set_pause_on_exceptions(Some(true)).unwrap(); // 监听异常抛出事件 let _events = tab.add_event_listener(Arc::new(move |event: &Event| { if let Event::DebuggerExceptionThrown(thrown_event) = event { dbg!("捕获到JS异常:", thrown_event.exception_details); } }))?; // 执行抛出异常的JS代码 let _remote_object = tab.evaluate("throw new Error('测试异常');", true).unwrap(); std::thread::sleep(std::time::Duration::from_secs(1)); Ok(()) }
关键说明
- 不同的CDP事件对应不同的场景:
Log.entryAdded负责控制台日志,Debugger.exceptionThrown负责未捕获的JS异常。 - 使用前必须启用对应的域(
enable_log()或enable_debugger()),否则无法收到事件。 console.assert本质是输出错误日志,不属于未捕获异常,所以只能通过Log.entryAdded捕获。
内容的提问来源于stack exchange,提问作者Max888
相关产品推荐
相关产品推荐

