@@ -34,32 +34,6 @@ import * as utils from '../util/utils';
3434import * as debugapi from './debugapi' ;
3535import { V8Inspector } from './v8inspector' ;
3636
37- /**
38- * An interface that describes options that set behavior when interacting with
39- * the V8 Inspector API.
40- */
41- interface InspectorOptions {
42- /**
43- * Whether to add a 'file://' prefix to a URL when setting breakpoints.
44- */
45- useWellFormattedUrl : boolean ;
46- }
47-
48- /** Data related to the v8 inspector. */
49- interface V8Data {
50- session : inspector . Session ;
51- // Options for behavior when interfacing with the Inspector API.
52- inspectorOptions : InspectorOptions ;
53- inspector : V8Inspector ;
54- // Store the v8 setBreakpoint parameters for each v8 breakpoint so that later
55- // the recorded parameters can be used to reset the breakpoints.
56- setBreakpointsParams : {
57- [
58- v8BreakpointId : string
59- ] : inspector . Debugger . SetBreakpointByUrlParameterType ;
60- } ;
61- }
62-
6337/**
6438 * In older versions of Node, the script source as seen by the Inspector
6539 * backend is wrapped in `require('module').wrapper`, and in new versions
@@ -99,8 +73,9 @@ export class InspectorDebugApi implements debugapi.DebugApi {
9973 // stackdriver breakpoint id.
10074 breakpointMapper : { [ id : string ] : stackdriver . BreakpointId [ ] } = { } ;
10175 numBreakpoints = 0 ;
102- numBreakpointHitsBeforeReset = 0 ;
103- v8 : V8Data ;
76+
77+ // The wrapper class that interacts with the V8 debugger.
78+ inspector : V8Inspector ;
10479
10580 constructor (
10681 logger : consoleLogLevel . Logger ,
@@ -112,36 +87,28 @@ export class InspectorDebugApi implements debugapi.DebugApi {
11287 this . config = config ;
11388 this . fileStats = jsFiles ;
11489 this . sourcemapper = sourcemapper ;
115- this . scriptMapper = { } ;
116- this . v8 = this . createV8Data ( ) ;
117- }
118-
119- /** Creates a new V8 Debugging session and the related data. */
120- private createV8Data ( ) : V8Data {
121- const session = new inspector . Session ( ) ;
122- session . connect ( ) ;
123- session . on ( 'Debugger.scriptParsed' , script => {
124- this . scriptMapper [ script . params . scriptId ] = script . params ;
125- } ) ;
126- session . post ( 'Debugger.enable' ) ;
127- session . post ( 'Debugger.setBreakpointsActive' , { active : true } ) ;
128- session . on ( 'Debugger.paused' , message => {
129- try {
130- this . handleDebugPausedEvent ( message . params ) ;
131- } catch ( error ) {
132- this . logger . error ( error ) ;
90+ this . inspector = new V8Inspector (
91+ /* logger=*/ logger ,
92+ /*useWellFormattedUrl=*/ utils . satisfies ( process . version , '>10.11.0' ) ,
93+ /*resetV8DebuggerThreshold=*/ this . config . resetV8DebuggerThreshold ,
94+ /*onScriptParsed=*/
95+ scriptParams => {
96+ this . scriptMapper [ scriptParams . scriptId ] = scriptParams ;
97+ } ,
98+ /*onPaused=*/
99+ messageParams => {
100+ try {
101+ this . handleDebugPausedEvent ( messageParams ) ;
102+ } catch ( error ) {
103+ this . logger . error ( error ) ;
104+ }
133105 }
134- } ) ;
106+ ) ;
107+ }
135108
136- return {
137- session,
138- inspectorOptions : {
139- // Well-Formatted URL is required in Node 10.11.1+.
140- useWellFormattedUrl : utils . satisfies ( process . version , '>10.11.0' ) ,
141- } ,
142- inspector : new V8Inspector ( session ) ,
143- setBreakpointsParams : { } ,
144- } ;
109+ /** Disconnects and marks the current V8 data as not connected. */
110+ disconnect ( ) : void {
111+ this . inspector . detach ( ) ;
145112 }
146113
147114 set (
@@ -268,8 +235,7 @@ export class InspectorDebugApi implements debugapi.DebugApi {
268235 if ( ! this . breakpointMapper [ breakpointData . id ] ) {
269236 // When breakpointmapper does not countain current v8/inspector breakpoint
270237 // id, we should remove this breakpoint from v8.
271- result = this . v8 . inspector . removeBreakpoint ( breakpointData . id ) ;
272- delete this . v8 . setBreakpointsParams [ breakpointData . id ] ;
238+ result = this . inspector . removeBreakpoint ( breakpointData . id ) ;
273239 }
274240 delete this . breakpoints [ breakpoint . id ] ;
275241 delete this . listeners [ breakpoint . id ] ;
@@ -346,10 +312,6 @@ export class InspectorDebugApi implements debugapi.DebugApi {
346312 this . listeners [ breakpoint . id ] = { enabled : true , listener} ;
347313 }
348314
349- disconnect ( ) : void {
350- this . v8 . session . disconnect ( ) ;
351- }
352-
353315 numBreakpoints_ ( ) : number {
354316 // Tracks the number of stackdriver breakpoints.
355317 return Object . keys ( this . breakpoints ) . length ;
@@ -537,7 +499,7 @@ export class InspectorDebugApi implements debugapi.DebugApi {
537499 let v8BreakpointId ; // v8/inspector breakpoint id
538500 if ( ! this . locationMapper [ locationStr ] ) {
539501 // The first time when a breakpoint was set to this location.
540- const rawUrl = this . v8 . inspectorOptions . useWellFormattedUrl
502+ const rawUrl = this . inspector . shouldUseWellFormattedUrl ( )
541503 ? `file://${ matchingScript } `
542504 : matchingScript ;
543505 // on windows on Node 11+, the url must start with file:///
@@ -546,19 +508,17 @@ export class InspectorDebugApi implements debugapi.DebugApi {
546508 process . platform === 'win32' && utils . satisfies ( process . version , '>=11' )
547509 ? rawUrl . replace ( / ^ f i l e : \/ \/ / , 'file:///' ) . replace ( / \\ / g, '/' )
548510 : rawUrl ;
549- const params = {
511+ const res = this . inspector . setBreakpointByUrl ( {
550512 lineNumber : line - 1 ,
551513 url,
552514 columnNumber : column - 1 ,
553515 condition : breakpoint . condition || undefined ,
554- } ;
555- const res = this . v8 . inspector . setBreakpointByUrl ( params ) ;
516+ } ) ;
556517 if ( res . error || ! res . response ) {
557518 // Error case.
558519 return null ;
559520 }
560521 v8BreakpointId = res . response . breakpointId ;
561- this . v8 . setBreakpointsParams [ v8BreakpointId ] = params ;
562522
563523 this . locationMapper [ locationStr ] = [ ] ;
564524 this . breakpointMapper [ v8BreakpointId ] = [ ] ;
@@ -646,7 +606,7 @@ export class InspectorDebugApi implements debugapi.DebugApi {
646606 const evaluatedExpressions = breakpoint . expressions . map ( exp => {
647607 // returnByValue is set to true here so that the JSON string of the
648608 // value will be returned to log.
649- const result = state . evaluate ( exp , frame , that . v8 . inspector , true ) ;
609+ const result = state . evaluate ( exp , frame , that . inspector , true ) ;
650610 if ( result . error ) {
651611 return result . error ;
652612 } else {
@@ -661,7 +621,7 @@ export class InspectorDebugApi implements debugapi.DebugApi {
661621 breakpoint ,
662622 this . config ,
663623 this . scriptMapper ,
664- this . v8 . inspector
624+ this . inspector
665625 ) ;
666626 if (
667627 breakpoint . location &&
@@ -695,37 +655,5 @@ export class InspectorDebugApi implements debugapi.DebugApi {
695655 } catch ( e ) {
696656 this . logger . warn ( 'Internal V8 error on breakpoint event: ' + e ) ;
697657 }
698-
699- this . tryResetV8Debugger ( ) ;
700- }
701-
702- /**
703- * Periodically resets breakpoints to prevent memory leaks in V8 (for holding
704- * contexts of previous breakpoint hits).
705- */
706- private tryResetV8Debugger ( ) {
707- this . numBreakpointHitsBeforeReset += 1 ;
708- if (
709- this . numBreakpointHitsBeforeReset < this . config . resetV8DebuggerThreshold
710- ) {
711- return ;
712- }
713- this . numBreakpointHitsBeforeReset = 0 ;
714-
715- const storedParams = this . v8 . setBreakpointsParams ;
716-
717- // Re-connect the session to clean the memory usage.
718- this . disconnect ( ) ;
719- this . scriptMapper = { } ;
720- this . v8 = this . createV8Data ( ) ;
721- this . v8 . setBreakpointsParams = storedParams ;
722-
723- // Setting the v8 breakpoints again according to the stored parameters.
724- for ( const params of Object . values ( storedParams ) ) {
725- const res = this . v8 . inspector . setBreakpointByUrl ( params ) ;
726- if ( res . error || ! res . response ) {
727- this . logger . error ( 'Error upon re-setting breakpoint: ' + res ) ;
728- }
729- }
730658 }
731659}
0 commit comments