/**
 * @license
 * Copyright 2025 ReverseCraft
 * SPDX-License-Identifier: Apache-2.0
 */
import { clearScriptCache } from './smart-breakpoint-utils.js';
/**
 * Shared CDP session management utilities.
 * Used by debugger tools and network initiator tracking.
 */
const cdpSessions = new WeakMap();
/**
 * Get or create a CDP session for a page.
 */
export async function getCdpSession(page) {
    let session = cdpSessions.get(page);
    if (!session) {
        session = await page.createCDPSession();
        cdpSessions.set(page, session);
    }
    return session;
}
/**
 * Dispose CDP session for a page.
 * Cleans up associated script caches and temporary files.
 */
export async function disposeCdpSession(page) {
    const session = cdpSessions.get(page);
    if (session) {
        // Clear in-memory script cache
        clearScriptCache(session);
        // Detach the CDP session
        session.detach().catch(() => {
            // Ignore detach errors
        });
        cdpSessions.delete(page);
    }
}
/**
 * Check if a CDP session exists for a page.
 */
export function hasCdpSession(page) {
    return cdpSessions.has(page);
}
/**
 * Format a stack trace for human-readable output.
 */
export function formatStackTrace(stack, indent = '') {
    const lines = [];
    if (stack.description) {
        lines.push(`${indent}${stack.description}`);
    }
    for (const frame of stack.callFrames) {
        const funcName = frame.functionName || '(anonymous)';
        const location = `${frame.url}:${frame.lineNumber + 1}:${frame.columnNumber}`;
        lines.push(`${indent}  at ${funcName} (${location})`);
    }
    if (stack.parent) {
        lines.push(`${indent}--- async ---`);
        lines.push(...formatStackTrace(stack.parent, indent));
    }
    return lines;
}
/**
 * Format initiator information for human-readable output.
 */
export function formatInitiator(initiator) {
    const lines = [];
    lines.push(`Type: ${initiator.type}`);
    if (initiator.url) {
        const location = initiator.lineNumber !== undefined
            ? `${initiator.url}:${initiator.lineNumber + 1}${initiator.columnNumber !== undefined ? `:${initiator.columnNumber}` : ''}`
            : initiator.url;
        lines.push(`URL: ${location}`);
    }
    if (initiator.stack) {
        lines.push('');
        lines.push('Call Stack:');
        lines.push(...formatStackTrace(initiator.stack, '  '));
    }
    return lines;
}
// ============================================================================
// Network Initiator Tracking
// ============================================================================
/**
 * Store requestId -> NetworkInitiator mapping per page.
 */
const networkInitiators = new WeakMap();
/**
 * Track which pages have network initiator tracking enabled.
 */
const networkTrackingEnabled = new WeakSet();
/**
 * Enable network initiator tracking for a page.
 * This enables the CDP Network domain and listens for requestWillBeSent events
 * to capture the initiator (including call stack) for each request.
 */
export async function enableNetworkInitiatorTracking(page) {
    if (networkTrackingEnabled.has(page)) {
        return;
    }
    const session = await getCdpSession(page);
    // Initialize the initiator map for this page
    networkInitiators.set(page, new Map());
    // Listen for Network.requestWillBeSent events
    session.on('Network.requestWillBeSent', (params) => {
        if (params.initiator) {
            const initiatorMap = networkInitiators.get(page);
            if (initiatorMap) {
                initiatorMap.set(params.requestId, params.initiator);
            }
        }
    });
    // Enable the Network domain to receive events
    await session.send('Network.enable');
    networkTrackingEnabled.add(page);
}
/**
 * Get the initiator information for a network request.
 * @param page The page the request belongs to
 * @param requestId The CDP request ID
 * @returns The initiator information, or undefined if not found
 */
export function getNetworkInitiator(page, requestId) {
    const initiatorMap = networkInitiators.get(page);
    return initiatorMap?.get(requestId);
}
/**
 * Clear all stored initiator data for a page.
 * Call this on navigation to free memory from old requests.
 */
export function clearNetworkInitiators(page) {
    const initiatorMap = networkInitiators.get(page);
    if (initiatorMap) {
        initiatorMap.clear();
    }
}
/**
 * Check if network initiator tracking is enabled for a page.
 */
export function isNetworkTrackingEnabled(page) {
    return networkTrackingEnabled.has(page);
}
//# sourceMappingURL=cdp.js.map