@@ -36,8 +36,8 @@ namespace Microsoft.NodejsTools.Debugger {
3636 /// <summary>
3737 /// Handles all interactions with a Node process which is being debugged.
3838 /// </summary>
39- sealed class NodeDebugger : IDisposable {
40- public readonly int MainThreadId = 1 ;
39+ internal sealed class NodeDebugger : IDisposable {
40+ public const int MainThreadId = 1 ;
4141 private readonly Dictionary < int , NodeBreakpointBinding > _breakpointBindings = new Dictionary < int , NodeBreakpointBinding > ( ) ;
4242 private readonly IDebuggerClient _client ;
4343 private readonly IDebuggerConnection _connection ;
@@ -76,82 +76,90 @@ private NodeDebugger() {
7676 _fileNameMapper = new LocalFileNameMapper ( ) ;
7777 }
7878
79- public NodeDebugger (
80- string exe ,
81- string script ,
82- string dir ,
83- string env ,
84- string interpreterOptions ,
85- NodeDebugOptions debugOptions ,
86- ushort ? debuggerPort = null ,
87- bool createNodeWindow = true )
79+ public NodeDebugger ( Uri debuggerEndpointUri , int id )
80+ : this ( ) {
81+ _debuggerEndpointUri = debuggerEndpointUri ;
82+ _id = id ;
83+ _attached = true ;
84+ }
85+
86+ public NodeDebugger ( string exe , string script , string dir , string env , string interpreterOptions , NodeDebugOptions debugOptions , ushort ? debuggerPort = null , bool createNodeWindow = true )
8887 : this ( ) {
8988 // Select debugger port for a local connection
90- ushort debuggerPortOrDefault = NodejsConstants . DefaultDebuggerPort ;
91- if ( debuggerPort != null ) {
92- debuggerPortOrDefault = debuggerPort . Value ;
93- } else {
94- List < int > activeConnections =
95- ( from listener in IPGlobalProperties . GetIPGlobalProperties ( ) . GetActiveTcpListeners ( )
96- select listener . Port ) . ToList ( ) ;
97- if ( activeConnections . Contains ( debuggerPortOrDefault ) ) {
98- debuggerPortOrDefault = ( ushort ) Enumerable . Range ( new Random ( ) . Next ( 5859 , 6000 ) , 60000 ) . Except ( activeConnections ) . First ( ) ;
99- }
89+ var debuggerPortOrDefault = debuggerPort ?? GetDebuggerPort ( ) ;
90+ _debuggerEndpointUri = new UriBuilder { Scheme = "tcp" , Host = "localhost" , Port = debuggerPortOrDefault } . Uri ;
91+
92+ _process = StartNodeProcessWithDebug ( exe , script , dir , env , interpreterOptions , debugOptions , debuggerPortOrDefault , createNodeWindow ) ;
93+ }
94+
95+ private static ushort GetDebuggerPort ( ) {
96+ var debuggerPortOrDefault = NodejsConstants . DefaultDebuggerPort ;
97+
98+ var activeConnections = ( from listener in IPGlobalProperties . GetIPGlobalProperties ( ) . GetActiveTcpListeners ( )
99+ select listener . Port ) . ToList ( ) ;
100+
101+ if ( activeConnections . Contains ( debuggerPortOrDefault ) ) {
102+ debuggerPortOrDefault = ( ushort ) Enumerable . Range ( new Random ( ) . Next ( 5859 , 6000 ) , 60000 ) . Except ( activeConnections ) . First ( ) ;
100103 }
101104
102- _debuggerEndpointUri = new UriBuilder { Scheme = "tcp" , Host = "localhost" , Port = debuggerPortOrDefault } . Uri ;
105+ return debuggerPortOrDefault ;
106+ }
107+
108+ public static NodeProcess StartNodeProcessWithDebug ( string exe , string script , string dir , string env , string interpreterOptions , NodeDebugOptions debugOptions , ushort ? debuggerPort = null , bool createNodeWindow = true ) {
109+ // Select debugger port for a local connection
110+ var debuggerPortOrDefault = debuggerPort ?? GetDebuggerPort ( ) ;
103111
104112 // Node usage: node [options] [ -e script | script.js ] [arguments]
105- string allArgs = string . Format ( CultureInfo . InvariantCulture ,
106- "--debug-brk={0} --nolazy {1} {2}" ,
107- debuggerPortOrDefault ,
108- interpreterOptions ,
109- script
110- ) ;
113+ var allArgs = $ "--debug-brk={ debuggerPortOrDefault } --nolazy { interpreterOptions } \" { script } \" ";
114+
115+ return StartNodeProcess ( exe , dir , env , debugOptions , debuggerPortOrDefault , allArgs , createNodeWindow ) ;
116+ }
111117
118+ public static NodeProcess StartNodeProcessWithInspect ( string exe , string script , string dir , string env , string interpreterOptions , NodeDebugOptions debugOptions , ushort ? debuggerPort = null , bool createNodeWindow = true ) {
119+ // Select debugger port for a local connection
120+ var debuggerPortOrDefault = debuggerPort ?? GetDebuggerPort ( ) ;
121+
122+ // Node usage: node [options] [ -e script | script.js ] [arguments]
123+ string allArgs = $ "--debug-brk={ debuggerPortOrDefault } --nolazy { interpreterOptions } { script } ";
124+
125+ return StartNodeProcess ( exe , dir , env , debugOptions , debuggerPortOrDefault , allArgs , createNodeWindow ) ;
126+ }
127+
128+ // starts the nodeprocess in debug mode without hooking up our debugger, this way we can attach the WebKit debugger as a next step.
129+ private static NodeProcess StartNodeProcess ( string exe , string dir , string env , NodeDebugOptions debugOptions , ushort debuggerPortOrDefault , string allArgs , bool createNodeWindow ) {
112130 var psi = new ProcessStartInfo ( exe , allArgs ) {
113131 CreateNoWindow = ! createNodeWindow ,
114132 WorkingDirectory = dir ,
115133 UseShellExecute = false
116134 } ;
117135
118136 if ( env != null ) {
119- string [ ] envValues = env . Split ( '\0 ' ) ;
120- foreach ( string curValue in envValues ) {
121- string [ ] nameValue = curValue . Split ( new [ ] { '=' } , 2 ) ;
137+ var envValues = env . Split ( '\0 ' ) ;
138+ foreach ( var curValue in envValues ) {
139+ var nameValue = curValue . Split ( new [ ] { '=' } , 2 ) ;
122140 if ( nameValue . Length == 2 && ! String . IsNullOrWhiteSpace ( nameValue [ 0 ] ) ) {
123141 psi . EnvironmentVariables [ nameValue [ 0 ] ] = nameValue [ 1 ] ;
124142 }
125143 }
126144 }
127145
128- _process = new NodeProcess (
146+ return new NodeProcess (
129147 psi ,
130- debugOptions . HasFlag ( NodeDebugOptions . WaitOnAbnormalExit ) ,
131- debugOptions . HasFlag ( NodeDebugOptions . WaitOnNormalExit ) ,
132- true ) ;
148+ waitOnAbnormal : debugOptions . HasFlag ( NodeDebugOptions . WaitOnAbnormalExit ) ,
149+ waitOnNormal : debugOptions . HasFlag ( NodeDebugOptions . WaitOnNormalExit ) ,
150+ enableRaisingEvents : true ,
151+ debuggerPort : debuggerPortOrDefault ) ;
133152 }
134153
135- public NodeDebugger ( Uri debuggerEndpointUri , int id )
136- : this ( ) {
137- _debuggerEndpointUri = debuggerEndpointUri ;
138- _id = id ;
139- _attached = true ;
140- }
154+
141155
142156 #region Public Process API
143157
144- public int Id {
145- get { return _id != null ? _id . Value : _process . Id ; }
146- }
158+ public int Id => _id != null ? _id . Value : _process . Id ;
147159
148- private NodeThread MainThread {
149- get { return _threads [ MainThreadId ] ; }
150- }
160+ private NodeThread MainThread => _threads [ MainThreadId ] ;
151161
152- public bool HasExited {
153- get { return ! _connection . Connected ; }
154- }
162+ public bool HasExited => ! _connection . Connected ;
155163
156164 /// <summary>
157165 /// Gets or sets a value indicating whether executed remote debugging process.
@@ -424,16 +432,12 @@ public void ClearExceptionTreatment() {
424432 /// <summary>
425433 /// Gets a next command identifier.
426434 /// </summary>
427- private int CommandId {
428- get { return Interlocked . Increment ( ref _commandId ) ; }
429- }
435+ private int CommandId => Interlocked . Increment ( ref _commandId ) ;
430436
431437 /// <summary>
432438 /// Gets a source mapper.
433439 /// </summary>
434- public SourceMapper SourceMapper {
435- get { return _sourceMapper ; }
436- }
440+ public SourceMapper SourceMapper => _sourceMapper ;
437441
438442 /// <summary>
439443 /// Gets or sets a file name mapper.
@@ -650,7 +654,7 @@ private async Task<bool> ProcessBreakpointBreakAsync(
650654 }
651655
652656 SetBreakpointCommand result = await SetBreakpointAsync ( breakpoint , cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
653-
657+
654658 // Treat rebound breakpoint binding as fully bound
655659 NodeBreakpointBinding reboundbreakpointBinding = CreateBreakpointBinding ( breakpoint , result . BreakpointId , result . ScriptId , breakpoint . GetPosition ( SourceMapper ) . FileName , result . Line , result . Column , true ) ;
656660 HandleBindBreakpointSuccess ( reboundbreakpointBinding , breakpoint ) ;
@@ -712,7 +716,7 @@ private void OnExceptionEvent(object sender, ExceptionEventArgs args) {
712716
713717 var lookupCommand = new LookupCommand ( CommandId , _resultFactory , new [ ] { exception . ErrorNumber . Value } ) ;
714718 string errorCodeFromLookup = null ;
715-
719+
716720 if ( await TrySendRequestAsync ( lookupCommand ) . ConfigureAwait ( false ) ) {
717721 errorCodeFromLookup = lookupCommand . Results [ errorNumber ] [ 0 ] . StringValue ;
718722 _errorCodes [ errorNumber ] = errorCodeFromLookup ;
@@ -848,10 +852,6 @@ private IEnumerable<NodeStackFrame> GetLocalFrames(IEnumerable<NodeStackFrame> s
848852 return backtraceCommand . Running ;
849853 }
850854
851- internal IList < NodeThread > GetThreads ( ) {
852- return _threads . Values . ToList ( ) ;
853- }
854-
855855 internal void SendStepOver ( int identity ) {
856856 DebugWriteCommand ( "StepOver" ) ;
857857 DebuggerClient . RunWithRequestExceptionsHandled ( async ( ) => {
@@ -1049,7 +1049,7 @@ internal async Task UpdateBreakpointBindingAsync(
10491049
10501050 internal async Task < int ? > GetBreakpointHitCountAsync ( int breakpointId , CancellationToken cancellationToken = new CancellationToken ( ) ) {
10511051 var listBreakpointsCommand = new ListBreakpointsCommand ( CommandId ) ;
1052-
1052+
10531053 int hitCount ;
10541054 if ( await TrySendRequestAsync ( listBreakpointsCommand , cancellationToken ) . ConfigureAwait ( false ) &&
10551055 listBreakpointsCommand . Breakpoints . TryGetValue ( breakpointId , out hitCount ) ) {
@@ -1160,7 +1160,7 @@ internal async Task<NodeEvaluationResult> SetVariableValueAsync(
11601160 return false ;
11611161 }
11621162 }
1163-
1163+
11641164 #endregion
11651165
11661166 #region Debugging Events
@@ -1211,7 +1211,7 @@ private bool GetOrAddModule(NodeModule module, out NodeModule value, NodeStackFr
12111211 javaScriptFileName = FileNameMapper . GetLocalFileName ( javaScriptFileName ) ;
12121212
12131213 // Try to get mapping for JS file
1214- if ( stackFrame != null ) {
1214+ if ( stackFrame != null ) {
12151215 line = stackFrame . Line ;
12161216 column = stackFrame . Column ;
12171217 }
@@ -1255,8 +1255,6 @@ public NodeModule GetModuleForFilePath(string filePath) {
12551255 internal void Close ( ) {
12561256 }
12571257
1258-
1259-
12601258 #region IDisposable
12611259
12621260 public void Dispose ( ) {
0 commit comments