Skip to content

Commit ec80503

Browse files
author
Paul van Brenk
committed
Support WebKit debugger.
This needs matching changes in the webkit debugger component.
1 parent 101ed9b commit ec80503

14 files changed

+417
-328
lines changed

Common/Product/SharedProject/ProjectNode.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4496,7 +4496,6 @@ public virtual int IsDocumentInProject(string mkDoc, out int found, VSDOCUMENTPR
44964496
}
44974497

44984498
return VSConstants.S_OK;
4499-
45004499
}
45014500

45024501
protected virtual bool IncludeNonMemberItemInProject(HierarchyNode node) {
@@ -5597,6 +5596,10 @@ public virtual int GetBuildSystemKind(out uint kind) {
55975596
internal HierarchyNode FindNodeByFullPath(string name) {
55985597
Site.GetUIThread().MustBeCalledFromUIThread();
55995598

5599+
if (name.StartsWith("mdha:", StringComparison.OrdinalIgnoreCase)) {
5600+
return default(HierarchyNode);
5601+
}
5602+
56005603
Debug.Assert(Path.IsPathRooted(name));
56015604

56025605
HierarchyNode node;

Nodejs/Product/Nodejs/Debugger/DebugEngine/AD7Engine.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -565,9 +565,10 @@ int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, stri
565565

566566
AttachEvents(_process);
567567

568-
var adProcessId = new AD_PROCESS_ID();
569-
adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM;
570-
adProcessId.dwProcessId = (uint)_process.Id;
568+
var adProcessId = new AD_PROCESS_ID() {
569+
ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM,
570+
dwProcessId = (uint)_process.Id
571+
};
571572

572573
EngineUtils.RequireOk(port.GetProcess(adProcessId, out process));
573574
LiveLogger.WriteLine("AD7Engine LaunchSuspended returning S_OK");

Nodejs/Product/Nodejs/Debugger/NodeConstants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//*********************************************************//
1616

1717
namespace Microsoft.NodejsTools.Debugger {
18-
sealed class NodeConstants {
18+
internal sealed class NodeConstants {
1919
public const string ScriptWrapBegin = "(function (exports, require, module, __filename, __dirname) { ";
2020
public const string ScriptWrapEnd = "\n});";
2121
}

Nodejs/Product/Nodejs/Debugger/NodeDebugOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
namespace Microsoft.NodejsTools.Debugger {
2020
[Flags]
21-
enum NodeDebugOptions {
21+
internal enum NodeDebugOptions {
2222
None,
2323
/// <summary>
2424
/// Passing this flag to the debugger will cause it to wait for input on an abnormal (non-zero)

Nodejs/Product/Nodejs/Debugger/NodeDebugger.cs

Lines changed: 65 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -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() {

Nodejs/Product/Nodejs/Debugger/NodeEvaluationResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace Microsoft.NodejsTools.Debugger {
2424
/// <summary>
2525
/// Represents the result of an evaluation of an expression against a given stack frame.
2626
/// </summary>
27-
class NodeEvaluationResult {
27+
internal class NodeEvaluationResult {
2828
private readonly Regex _stringLengthExpression = new Regex(@"\.\.\. \(length: ([0-9]+)\)$", RegexOptions.Compiled);
2929

3030
/// <summary>

Nodejs/Product/Nodejs/Debugger/NodeEventEventArgs.cs

Lines changed: 0 additions & 28 deletions
This file was deleted.

Nodejs/Product/Nodejs/Debugger/NodeProcess.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ namespace Microsoft.NodejsTools.Debugger {
2929
sealed class NodeProcess : IDisposable {
3030
private readonly ProcessStartInfo _psi;
3131
private readonly bool _waitOnAbnormal, _waitOnNormal, _enableRaisingEvents;
32-
private Process _process, _pressAnyKeyProcess;
32+
private Process _process;
33+
private Process _pressAnyKeyProcess;
3334

34-
public NodeProcess(ProcessStartInfo psi, bool waitOnAbnormal, bool waitOnNormal, bool enableRaisingEvents) {
35+
public ushort DebuggerPort { get; }
36+
37+
public NodeProcess(ProcessStartInfo psi, bool waitOnAbnormal, bool waitOnNormal, bool enableRaisingEvents, ushort debuggerPort = 0) {
3538
_psi = psi;
3639
_waitOnAbnormal = waitOnAbnormal;
3740
_waitOnNormal = waitOnNormal;
3841
_enableRaisingEvents = enableRaisingEvents;
42+
DebuggerPort = debuggerPort;
3943
}
4044

4145
public static NodeProcess Start(ProcessStartInfo psi, bool waitOnAbnormal, bool waitOnNormal) {

0 commit comments

Comments
 (0)