44 * SPDX-License-Identifier: Apache-2.0
55 */
66
7+ import type * as CdpProtocol from '../node_modules/chrome-devtools-frontend/front_end/generated/protocol-proxy-api.js' ;
8+ import { IssuesManager , Issue } from '../node_modules/chrome-devtools-frontend/mcp/mcp.js' ;
9+
710import {
811 type Browser ,
912 type Frame ,
1013 type Handler ,
1114 type HTTPRequest ,
1215 type Page ,
13- type PageEvents ,
16+ type PageEvents as PuppeteerPageEvents ,
1417} from './third_party/index.js' ;
1518
19+ interface PageEvents extends PuppeteerPageEvents {
20+ issue : Issue . Issue ;
21+ }
22+
1623export type ListenerMap < EventMap extends PageEvents = PageEvents > = {
1724 [ K in keyof EventMap ] ?: ( event : EventMap [ K ] ) => void ;
1825} ;
@@ -61,15 +68,15 @@ export class PageCollector<T> {
6168 async init ( ) {
6269 const pages = await this . #browser. pages ( this . #includeAllPages) ;
6370 for ( const page of pages ) {
64- this . #initializePage ( page ) ;
71+ await this . addPage ( page ) ;
6572 }
6673
6774 this . #browser. on ( 'targetcreated' , async target => {
6875 const page = await target . page ( ) ;
6976 if ( ! page ) {
7077 return ;
7178 }
72- this . #initializePage ( page ) ;
79+ await this . addPage ( page ) ;
7380 } ) ;
7481 this . #browser. on ( 'targetdestroyed' , async target => {
7582 const page = await target . page ( ) ;
@@ -80,15 +87,15 @@ export class PageCollector<T> {
8087 } ) ;
8188 }
8289
83- public addPage ( page : Page ) {
84- this . #initializePage( page ) ;
85- }
86-
87- #initializePage( page : Page ) {
90+ public async addPage ( page : Page ) {
8891 if ( this . storage . has ( page ) ) {
8992 return ;
9093 }
94+ await this . #initializePage( page ) ;
95+ }
9196
97+ async #initializePage( page : Page ) {
98+ await this . subscribeForIssues ( page ) ;
9299 const idGenerator = createIdGenerator ( ) ;
93100 const storedLists : Array < Array < WithSymbolId < T > > > = [ [ ] ] ;
94101 this . storage . set ( page , storedLists ) ;
@@ -116,6 +123,19 @@ export class PageCollector<T> {
116123 this . #listeners. set ( page , listeners ) ;
117124 }
118125
126+ protected async subscribeForIssues ( page : Page ) {
127+ const session = await page . createCDPSession ( ) ;
128+ session . on ( 'Audits.issueAdded' , ( data ) => { // TODO unsubscribe
129+ // @ts -expect-error Types of protocol from Puppeteer and CDP are incopatible for Issues
130+ const issue = IssuesManager . createIssuesFromProtocolIssue ( null , data . issue ) [ 0 ] ; // returns issue wrapped in array, need to get first element
131+ if ( ! issue ) {
132+ return ;
133+ }
134+ page . emit ( 'issue' , issue ) ;
135+ } ) ;
136+ await session . send ( 'Audits.enable' ) ;
137+ }
138+
119139 protected splitAfterNavigation ( page : Page ) {
120140 const navigations = this . storage . get ( page ) ;
121141 if ( ! navigations ) {
0 commit comments