import type { Protocol , SessionConnection , SessionID , SessionIdentifier , TargetID , TargetInfo , } from "../types" ; const CONNECTION = Symbol ( "connection" ) ; export type NewConnection = ( session : Session ) => SessionConnection ; export type DestroyConnection = ( sessionId : SessionID ) => void ; export type EventHook = ( event : string , params ? : object ) => void ; export interface GetConnection { ( session , throwIfNotAttached ? ) : SessionConnection ; ( session , throwIfNotAttached ) : SessionConnection | undefined ; } export type ClearSessions = ( ) => void ; export interface Session { sessionId : SessionID ; targetId : TargetID ; targetInfo : TargetInfo ; } interface Attachment { sessionId : SessionID ; targetId : TargetID ; targetInfo : TargetInfo ; [ CONNECTION ] : SessionConnection | undefined ; } export default function newEventHook ( newConnection , detachConnection ) { let attachments ; let sessionIds ; return [ eventHook , getConnection , clearSessions ] ; function eventHook ( event , params ? ) { if ( params ) { switch ( event ) { case "Target.attachedToTarget" : attachedToTarget ( params as Protocol . Target . AttachedToTargetEvent ) ; break ; case "Target.detachedFromTarget" : detachedFromTarget ( params as Protocol . Target . DetachedFromTargetEvent ) ; break ; case "Target.targetInfoChanged" : targetInfoChanged ( params as Protocol . Target . TargetInfoChangedEvent ) ; break ; } } } function getSessionId ( session , throwIfNotAttached = true ) { let sessionId ; if ( typeof session === "string" ) { sessionId = session ; } else if ( sessionIds !== undefined && session !== null && typeof session === "object" ) { if ( "sessionId" in session ) { sessionId = session . sessionId ; } else if ( "targetId" in session ) { const { targetId } = session ; sessionId = sessionIds . get ( session . targetId ) ; if ( ! sessionId && throwIfNotAttached ) { throw new Error ( `Target ${ targetId } is not attached.` ) ; } } } return sessionId ; } function getSession ( session , throwIfNotAttached = true ) { const sessionId = getSessionId ( session , throwIfNotAttached ) ; if ( sessionId === undefined ) { return ; } if ( attachments !== undefined ) { const attachment = attachments . get ( sessionId ) ; if ( attachment !== undefined ) { return attachment ; } } if ( throwIfNotAttached ) { throw new Error ( `Session ${ sessionId } is no longer attached.` ) ; } } function attachedToTarget ( { sessionId , targetInfo , } ) { const { targetId } = targetInfo ; if ( attachments === undefined ) { attachments = new Map ( ) ; } attachments . set ( sessionId , { [ CONNECTION ] : undefined , sessionId , targetId , targetInfo , } ) ; if ( sessionIds === undefined ) { sessionIds = new Map ( ) ; } sessionIds . set ( targetId , sessionId ) ; } function detachedFromTarget ( { sessionId , } ) { if ( attachments === undefined ) { return ; } const attachment = attachments . get ( sessionId ) ; if ( attachment !== undefined ) { attachments . delete ( sessionId ) ; if ( sessionIds !== undefined ) { sessionIds . delete ( attachment . targetId ) ; } if ( attachment [ CONNECTION ] !== undefined ) { attachment [ CONNECTION ] = undefined ; detachConnection ( sessionId ) ; } } } function targetInfoChanged ( { targetInfo , } ) { const attachment = getSession ( targetInfo , false ) ; if ( attachment !== undefined ) { attachment . targetInfo = targetInfo ; } } function getConnection ( session ) ; function getConnection ( session , throwIfNotAttached ? ) ; function getConnection ( session , throwIfNotAttached ) ; function getConnection ( session , throwIfNotAttached = true ) { const attachment = getSession ( session , throwIfNotAttached ) ; if ( attachment === undefined ) { return ; } let connection = attachment [ CONNECTION ] ; if ( connection === undefined ) { connection = newConnection ( attachment ) ; attachment [ CONNECTION ] = connection ; } return connection ; } function clearSessions ( ) { if ( attachments !== undefined ) { for ( const attachment of attachments . values ( ) ) { if ( attachment [ CONNECTION ] !== undefined ) { attachment [ CONNECTION ] = undefined ; detachConnection ( attachment . sessionId ) ; } } attachments . clear ( ) ; } if ( sessionIds !== undefined ) { sessionIds . clear ( ) ; } } }