import * as utils from '../utils' ; import { CrdpScript } from './chromeDebugAdapter' ; import { Protocol as Crdp } from 'devtools-protocol' ; import * as ChromeUtils from './chromeUtils' ; import { DebugProtocol } from 'vscode-debugprotocol' ; import { ChromeDebugAdapter } from './chromeDebugAdapter' ; import { BasePathTransformer , BaseSourceMapTransformer } from '..' ; import * as path from 'path' ; import { mapInternalSourceToRemoteClient } from '../remoteMapper' ; /**
 * Represents a reference to a source/script. `contents` is set if there are inlined sources.
 * Otherwise, scriptId can be used to retrieve the contents from the runtime.
 */ export interface ISourceContainer { /** The runtime-side scriptId of this script */ scriptId ? : Crdp . Runtime . ScriptId ; /** The contents of this script, if they are inlined in the sourcemap */ contents ? : string ; /** The authored path to this script (only set if the contents are inlined) */ mappedPath ? : string ; } /**
 * A container class for loaded script files
 */ export class ScriptContainer { private _scriptsById = new Map < Crdp . Runtime . ScriptId , CrdpScript > ( ) ; private _scriptsByUrl = new Map < string , CrdpScript > ( ) ; private _sourceHandles = new utils . ReverseHandles < ISourceContainer > ( ) ; deprecated public get scriptsByIdMap ( ) { return this . _scriptsById ; } /**
     * Get a list of all currently loaded scripts
     */ public get loadedScripts ( ) { return this . _scriptsById . values ( ) ; } /**
     * Get a script by its url
     */ public getScriptByUrl ( url ) { const canonUrl = utils . canonicalizeUrl ( url ) ; return this . _scriptsByUrl . get ( canonUrl ) || this . _scriptsByUrl . get ( utils . fixDriveLetter ( canonUrl ) ) ; } /**
     * Clear this container of all loaded scripts
     */ public reset ( ) { this . _scriptsById = new Map < Crdp . Runtime . ScriptId , Crdp . Debugger . ScriptParsedEvent > ( ) ; this . _scriptsByUrl = new Map < string , Crdp . Debugger . ScriptParsedEvent > ( ) ; } param script public add ( script ) { this . _scriptsById . set ( script . scriptId , script ) ; this . _scriptsByUrl . set ( utils . canonicalizeUrl ( script . url ) , script ) ; } param id public getScriptById ( id ) { return this . _scriptsById . get ( id ) ; } /**
     * Get a list of all loaded script urls (as a string)
     */ public getAllScriptsString ( pathTransformer , sourceMapTransformer ) { const runtimeScripts = Array . from ( this . _scriptsByUrl . keys ( ) ) . sort ( ) ; return Promise . all ( runtimeScripts . map ( script => this . getOneScriptString ( script , pathTransformer , sourceMapTransformer ) ) ) . then ( strs => { return strs . join ( '\n' ) ; } ) ; } /**
     * Get a script string?
     */ public getOneScriptString ( runtimeScriptPath , pathTransformer , sourceMapTransformer ) { let result = '› ' + runtimeScriptPath ; const clientPath = pathTransformer . getClientPathFromTargetPath ( runtimeScriptPath ) ; if ( clientPath && clientPath !== runtimeScriptPath ) result += ` (${ clientPath })` ; return sourceMapTransformer . allSourcePathDetails ( clientPath || runtimeScriptPath ) . then ( sourcePathDetails => { let mappedSourcesStr = sourcePathDetails . map ( details => `    - ${ details . originalPath } (${ details . inferredPath })` ) . join ( '\n' ) ; if ( sourcePathDetails . length ) mappedSourcesStr = '\n' + mappedSourcesStr ; return result + mappedSourcesStr ; } ) ; } /**
     * Get the existing handle for this script, identified by runtime scriptId, or create a new one
     */ public getSourceReferenceForScriptId ( scriptId ) { return this . _sourceHandles . lookupF ( container => container . scriptId === scriptId ) || this . _sourceHandles . create ( { scriptId } ) ; } /**
     * Get the existing handle for this script, identified by the on-disk path it was mapped to, or create a new one
     */ public getSourceReferenceForScriptPath ( mappedPath , contents ) { return this . _sourceHandles . lookupF ( container => container . mappedPath === mappedPath ) || this . _sourceHandles . create ( { contents , mappedPath } ) ; } param script param origin public async scriptToSource ( script , origin , remoteAuthority ? ) { const sourceReference = this . getSourceReferenceForScriptId ( script . scriptId ) ; const properlyCasedScriptUrl = utils . canonicalizeUrl ( script . url ) ; const displayPath = this . realPathToDisplayPath ( properlyCasedScriptUrl ) ; const exists = await utils . existsAsync ( properlyCasedScriptUrl ) ; const source = < DebugProtocol . Source > { name : path . basename ( displayPath ) , path : displayPath , sourceReference : exists ? undefined : sourceReference , origin } ; if ( remoteAuthority ) { return mapInternalSourceToRemoteClient ( source , remoteAuthority ) ; } else { return source ; } } param ref public getSource ( ref ) { return this . _sourceHandles . get ( ref ) ; } public fakeUrlForSourceReference ( sourceReference ) { const handle = this . _sourceHandles . get ( sourceReference ) ; return `${ ChromeUtils . EVAL_NAME_PREFIX }${ handle . scriptId }` ; } public displayNameForSourceReference ( sourceReference ) { const handle = this . _sourceHandles . get ( sourceReference ) ; return ( handle && this . displayNameForScriptId ( handle . scriptId ) ) || sourceReference + '' ; } public displayNameForScriptId ( scriptId ) { return `${ ChromeUtils . EVAL_NAME_PREFIX }${ scriptId }` ; } /**
     * Called when returning a stack trace, for the path for Sources that have a sourceReference, so consumers can
     * tweak it, since it's only for display.
     */ public realPathToDisplayPath ( realPath ) { if ( ChromeUtils . isEvalScript ( realPath ) ) { return `${ ChromeDebugAdapter . EVAL_ROOT }/${ realPath }` ; } return realPath ; } /**
     * Get the original path back from a displayPath created from `realPathToDisplayPath`
     */ public displayPathToRealPath ( displayPath ) { if ( displayPath . startsWith ( ChromeDebugAdapter . EVAL_ROOT ) ) { return displayPath . substr ( ChromeDebugAdapter . EVAL_ROOT . length + 1 ) ; } return displayPath ; } }