Skip to content

Commit

Permalink
[wasm][debugger] Fix loading a non wasm page and then returning to a …
Browse files Browse the repository at this point in the history
…wasm page. (#60688)

* Fix loading a non wasm page and then returning to a wasm page.

* Adding non-wasm-page.html

* fixing other method

* addressing @radical comments

* adding last empty line
  • Loading branch information
thaystg authored Oct 22, 2021
1 parent abcee57 commit 3cc122b
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 43 deletions.
8 changes: 2 additions & 6 deletions src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1217,11 +1217,7 @@ private async Task<DebugStore> RuntimeReady(SessionId sessionId, CancellationTok
return await context.ready.Task;

var commandParams = new MemoryStream();
var retDebuggerCmdReader = await SdbHelper.SendDebuggerAgentCommand<CmdEventRequest>(sessionId, CmdEventRequest.ClearAllBreakpoints, commandParams, token);
if (retDebuggerCmdReader == null)
{
Log("verbose", $"Failed to clear breakpoints");
}
await SdbHelper.SendDebuggerAgentCommand<CmdEventRequest>(sessionId, CmdEventRequest.ClearAllBreakpoints, commandParams, token);

if (context.PauseOnExceptions != PauseOnExceptionsKind.None && context.PauseOnExceptions != PauseOnExceptionsKind.Unset)
await SdbHelper.EnableExceptions(sessionId, context.PauseOnExceptions, token);
Expand All @@ -1234,7 +1230,7 @@ private async Task<DebugStore> RuntimeReady(SessionId sessionId, CancellationTok
DebugStore store = await LoadStore(sessionId, token);
context.ready.SetResult(store);
SendEvent(sessionId, "Mono.runtimeReady", new JObject(), token);
SdbHelper.SetStore(store);
SdbHelper.ResetStore(store);
return store;
}

Expand Down
46 changes: 24 additions & 22 deletions src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,11 @@ public TypeInfoWithDebugInformation(TypeInfo typeInfo, int debugId, string name)

internal class MonoBinaryReader : BinaryReader
{
public MonoBinaryReader(Stream stream) : base(stream) {}
public bool HasError { get; }
public MonoBinaryReader(Stream stream, bool hasError = false) : base(stream)
{
HasError = hasError;
}

internal static unsafe void PutBytesBE (byte *dest, byte *src, int count)
{
Expand Down Expand Up @@ -656,9 +660,9 @@ internal class MonoSDBHelper
private static int MINOR_VERSION = 61;
private static int MAJOR_VERSION = 2;

private Dictionary<int, MethodInfoWithDebugInformation> methods = new();
private Dictionary<int, AssemblyInfo> assemblies = new();
private Dictionary<int, TypeInfoWithDebugInformation> types = new();
private Dictionary<int, MethodInfoWithDebugInformation> methods;
private Dictionary<int, AssemblyInfo> assemblies;
private Dictionary<int, TypeInfoWithDebugInformation> types;

internal Dictionary<int, ValueTypeClass> valueTypes = new Dictionary<int, ValueTypeClass>();
internal Dictionary<int, PointerValue> pointerValues = new Dictionary<int, PointerValue>();
Expand All @@ -673,12 +677,16 @@ public MonoSDBHelper(MonoProxy proxy, ILogger logger)
{
this.proxy = proxy;
this.logger = logger;
this.store = null;
ResetStore(null);
}

public void SetStore(DebugStore store)
public void ResetStore(DebugStore store)
{
this.store = store;
this.methods = new();
this.assemblies = new();
this.types = new();
ClearCache();
}

public async Task<AssemblyInfo> GetAssemblyInfo(SessionId sessionId, int assemblyId, CancellationToken token)
Expand Down Expand Up @@ -816,12 +824,12 @@ public async Task<bool> EnableReceiveRequests(SessionId sessionId, EventKind eve
internal async Task<MonoBinaryReader> SendDebuggerAgentCommandInternal(SessionId sessionId, int command_set, int command, MemoryStream parms, CancellationToken token)
{
Result res = await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommand(GetId(), command_set, command, Convert.ToBase64String(parms.ToArray())), token);
if (res.IsErr) {
throw new Exception($"SendDebuggerAgentCommand Error - {(CommandSet)command_set} - {command}");
byte[] newBytes = Array.Empty<byte>();
if (!res.IsErr) {
newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value<string>());
}
byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value<string>());
var retDebuggerCmd = new MemoryStream(newBytes);
var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd);
var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd, res.IsErr);
return retDebuggerCmdReader;
}

Expand Down Expand Up @@ -854,12 +862,12 @@ internal Task<MonoBinaryReader> SendDebuggerAgentCommandWithParms<T>(SessionId s
internal async Task<MonoBinaryReader> SendDebuggerAgentCommandWithParmsInternal(SessionId sessionId, int command_set, int command, MemoryStream parms, int type, string extraParm, CancellationToken token)
{
Result res = await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommandWithParms(GetId(), command_set, command, Convert.ToBase64String(parms.ToArray()), parms.ToArray().Length, type, extraParm), token);
if (res.IsErr) {
throw new Exception("SendDebuggerAgentCommandWithParms Error");
byte[] newBytes = Array.Empty<byte>();
if (!res.IsErr) {
newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value<string>());
}
byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value<string>());
var retDebuggerCmd = new MemoryStream(newBytes);
var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd);
var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd, res.IsErr);
return retDebuggerCmdReader;
}

Expand Down Expand Up @@ -2530,15 +2538,9 @@ public async Task<bool> SetVariableValue(SessionId sessionId, int thread_id, int
JArray locals = new JArray();
retDebuggerCmdReader = await SendDebuggerAgentCommand<CmdFrame>(sessionId, CmdFrame.GetValues, commandParams, token);
int etype = retDebuggerCmdReader.ReadByte();
try
{
retDebuggerCmdReader = await SendDebuggerAgentCommandWithParms<CmdFrame>(sessionId, CmdFrame.SetValues, commandParams, etype, newValue, token);
}
catch (Exception)
{
retDebuggerCmdReader = await SendDebuggerAgentCommandWithParms<CmdFrame>(sessionId, CmdFrame.SetValues, commandParams, etype, newValue, token);
if (retDebuggerCmdReader.HasError)
return false;
}

return true;
}
}
Expand Down
75 changes: 70 additions & 5 deletions src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Newtonsoft.Json.Linq;
using System.IO;
using Xunit;
using System.Threading;

namespace DebuggerTests
{
Expand Down Expand Up @@ -131,11 +132,6 @@ public async Task CreateGoodBreakpointAndHit()
{
var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8);

var eval_req = JObject.FromObject(new
{
expression = "window.setTimeout(function() { invoke_add(); }, 1);",
});

await EvaluateAndCheck(
"window.setTimeout(function() { invoke_add(); }, 1);",
"dotnet://debugger-test.dll/debugger-test.cs", 10, 8,
Expand Down Expand Up @@ -577,5 +573,74 @@ await SendCommandAndCheck(null, "Debugger.resume",
CheckNumber(locals, "i", 2);
});
}

[Fact]
public async Task CreateGoodBreakpointAndHitGoToNonWasmPageComeBackAndHitAgain()
{
var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8);
var pause_location = await EvaluateAndCheck(
"window.setTimeout(function() { invoke_add(); }, 1);",
"dotnet://debugger-test.dll/debugger-test.cs", 10, 8,
"IntAdd");
Assert.Equal("other", pause_location["reason"]?.Value<string>());
Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value<string>());

var top_frame = pause_location["callFrames"][0];
Assert.Equal("IntAdd", top_frame["functionName"].Value<string>());
Assert.Contains("debugger-test.cs", top_frame["url"].Value<string>());

CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]);

//now check the scope
var scope = top_frame["scopeChain"][0];
Assert.Equal("local", scope["type"]);
Assert.Equal("IntAdd", scope["name"]);

Assert.Equal("object", scope["object"]["type"]);
CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, scope["startLocation"]);
CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 14, 4, scripts, scope["endLocation"]);

await cli.SendCommand("Debugger.resume", null, token);

var run_method = JObject.FromObject(new
{
expression = "window.setTimeout(function() { load_non_wasm_page(); }, 1);"
});
await cli.SendCommand("Runtime.evaluate", run_method, token);
await Task.Delay(1000, token);

run_method = JObject.FromObject(new
{
expression = "window.setTimeout(function() { reload_wasm_page(); }, 1);"
});
await cli.SendCommand("Runtime.evaluate", run_method, token);
await insp.WaitFor(Inspector.READY);
await EvaluateAndCheck(
"window.setTimeout(function() { invoke_add(); }, 1);",
"dotnet://debugger-test.dll/debugger-test.cs", 10, 8,
"IntAdd",
wait_for_event_fn: (pause_location) =>
{
Assert.Equal("other", pause_location["reason"]?.Value<string>());
Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value<string>());
var top_frame = pause_location["callFrames"][0];
Assert.Equal("IntAdd", top_frame["functionName"].Value<string>());
Assert.Contains("debugger-test.cs", top_frame["url"].Value<string>());
CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]);
//now check the scope
var scope = top_frame["scopeChain"][0];
Assert.Equal("local", scope["type"]);
Assert.Equal("IntAdd", scope["name"]);
Assert.Equal("object", scope["object"]["type"]);
CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, scope["startLocation"]);
CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 14, 4, scripts, scope["endLocation"]);
return Task.CompletedTask;
}
);
}
}
}
25 changes: 15 additions & 10 deletions src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<!doctype html>
<html lang="en-us">
<head>
</head>
<body>
<head>
</head>
<body>
<script type='text/javascript'>
var App = {
init: function () {
Expand Down Expand Up @@ -82,10 +82,15 @@
function invoke_add_with_parms (a, b) {
return App.int_add (a, b);
}
</script>
<script type="text/javascript" src="runtime-debugger.js"></script>
<script type="text/javascript" src="other.js"></script>
<script async type="text/javascript" src="dotnet.js"></script>
Stuff goes here
</body>
</html>

function load_non_wasm_page () {
console.log("load_non_wasm_page")
window.location.replace("http://localhost:9400/non-wasm-page.html");
}
</script>
<script type="text/javascript" src="runtime-debugger.js"></script>
<script type="text/javascript" src="other.js"></script>
<script async type="text/javascript" src="dotnet.js"></script>
Stuff goes here
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

<ItemGroup>
<WasmExtraFilesToDeploy Include="debugger-driver.html" />
<WasmExtraFilesToDeploy Include="non-wasm-page.html" />
<WasmExtraFilesToDeploy Include="other.js" />
<WasmExtraFilesToDeploy Include="runtime-debugger.js" />
<WasmExtraFilesToDeploy Include="weather.json" />
Expand Down
12 changes: 12 additions & 0 deletions src/mono/wasm/debugger/tests/debugger-test/non-wasm-page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en-us">
<head>
</head>
<body>
<script type='text/javascript'>
function reload_wasm_page () {
window.location.replace("http://localhost:9400/debugger-driver.html");
}
</script>
</body>
</html>

0 comments on commit 3cc122b

Please sign in to comment.