Skip to content

Commit 481c056

Browse files
thaystgradical
andauthored
[wasm][debugger] Hide members from classes that don't have debug information (#73982)
* adding fields that are from non-user-code as private * Do not show members from types that doesn't have debug information if JMC is enabled. * Addressing @radical comments. * Apply suggestions from code review Co-authored-by: Ankit Jain <radical@gmail.com> * Adding more tests. Co-authored-by: Ankit Jain <radical@gmail.com>
1 parent ca0d04d commit 481c056

File tree

11 files changed

+241
-4
lines changed

11 files changed

+241
-4
lines changed

src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs

+11-2
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,9 @@ internal sealed class TypeInfo
701701
internal int Token { get; }
702702
internal string Namespace { get; }
703703
internal bool IsCompilerGenerated { get; }
704+
private bool NonUserCode { get; }
704705
public string FullName { get; }
706+
internal bool IsNonUserCode => assembly.pdbMetadataReader == null || NonUserCode;
705707
public List<MethodInfo> Methods { get; } = new();
706708
public Dictionary<string, DebuggerBrowsableState?> DebuggerBrowsableFields = new();
707709
public Dictionary<string, DebuggerBrowsableState?> DebuggerBrowsableProperties = new();
@@ -769,8 +771,15 @@ internal TypeInfo(AssemblyInfo assembly, TypeDefinitionHandle typeHandle, TypeDe
769771
continue;
770772
var container = metadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent;
771773
var attributeName = assembly.EnCGetString(metadataReader.GetTypeReference((TypeReferenceHandle)container).Name);
772-
if (attributeName == nameof(CompilerGeneratedAttribute))
773-
IsCompilerGenerated = true;
774+
switch (attributeName)
775+
{
776+
case nameof(CompilerGeneratedAttribute):
777+
IsCompilerGenerated = true;
778+
break;
779+
case nameof(DebuggerNonUserCodeAttribute):
780+
NonUserCode = true;
781+
break;
782+
}
774783
}
775784

776785
void AppendToBrowsable(Dictionary<string, DebuggerBrowsableState?> dict, CustomAttributeHandleCollection customAttrs, string fieldName)

src/mono/wasm/debugger/BrowserDebugProxy/MemberObjectsExplorer.cs

+8
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ private static async Task<JObject> ReadFieldValue(
7171
FieldAttributes.Public => "result",
7272
_ => "internal"
7373
};
74+
7475
if (field.IsBackingField)
7576
{
7677
fieldValue["__isBackingField"] = true;
@@ -567,13 +568,20 @@ public static async Task<GetMembersResult> GetObjectMemberValues(
567568
for (int i = 0; i < typeIdsCnt; i++)
568569
{
569570
int typeId = typeIdsIncludingParents[i];
571+
var typeInfo = await sdbHelper.GetTypeInfo(typeId, token);
572+
573+
if (typeInfo.Info.IsNonUserCode && getCommandType.HasFlag(GetObjectCommandOptions.JustMyCode))
574+
continue;
575+
570576
int parentTypeId = i + 1 < typeIdsCnt ? typeIdsIncludingParents[i + 1] : -1;
571577
string typeName = await sdbHelper.GetTypeName(typeId, token);
572578
// 0th id is for the object itself, and then its ancestors
573579
bool isOwn = i == 0;
580+
574581
IReadOnlyList<FieldTypeClass> thisTypeFields = await sdbHelper.GetTypeFields(typeId, token);
575582
if (!includeStatic)
576583
thisTypeFields = thisTypeFields.Where(f => !f.Attributes.HasFlag(FieldAttributes.Static)).ToList();
584+
577585
if (thisTypeFields.Count > 0)
578586
{
579587
var allFields = await ExpandFieldValues(

src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs

+2
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,8 @@ internal async Task<ValueOrError<GetMembersResult>> RuntimeGetObjectMembers(Sess
745745
if (args["forDebuggerDisplayAttribute"]?.Value<bool>() == true)
746746
getObjectOptions |= GetObjectCommandOptions.ForDebuggerDisplayAttribute;
747747
}
748+
if (JustMyCode)
749+
getObjectOptions |= GetObjectCommandOptions.JustMyCode;
748750
try
749751
{
750752
switch (objectId.Scheme)

src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ internal enum GetObjectCommandOptions
5959
OwnProperties = 4,
6060
ForDebuggerProxyAttribute = 8,
6161
ForDebuggerDisplayAttribute = 16,
62-
WithProperties = 32
62+
WithProperties = 32,
63+
JustMyCode = 64
6364
}
6465

6566
internal enum CommandSet {

src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs

+47
Original file line numberDiff line numberDiff line change
@@ -1039,5 +1039,52 @@ await EvaluateAndCheck(
10391039
}
10401040
);
10411041
}
1042+
1043+
[Theory]
1044+
[InlineData("ClassInheritsFromClassWithoutDebugSymbols", 1287, true)]
1045+
[InlineData("ClassInheritsFromClassWithoutDebugSymbols", 1287, false)]
1046+
[InlineData("ClassInheritsFromNonUserCodeClass", 1335, true)]
1047+
[InlineData("ClassInheritsFromNonUserCodeClass", 1335, false)]
1048+
[InlineData("ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1352, true)]
1049+
[InlineData("ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass", 1352, false)]
1050+
public async Task InspectThisThatInheritsFromClassNonUserCode(string class_name, int line, bool jmc)
1051+
{
1052+
await SetJustMyCode(jmc);
1053+
var expression = "{{ invoke_static_method('[debugger-test] " + class_name + ":Run'); }}";
1054+
1055+
await EvaluateAndCheck(
1056+
"window.setTimeout(function() {" + expression + "; }, 1);",
1057+
"dotnet://debugger-test.dll/debugger-test.cs", line, 8,
1058+
$"{class_name}.CallMethod",
1059+
locals_fn: async (locals) =>
1060+
{
1061+
var this_props = await GetObjectOnLocals(locals, "this");
1062+
if (jmc)
1063+
{
1064+
await CheckProps(this_props, new
1065+
{
1066+
myField = TNumber(0),
1067+
myField2 = TNumber(0),
1068+
}, "this_props", num_fields: 2);
1069+
}
1070+
else
1071+
{
1072+
await CheckProps(this_props, new
1073+
{
1074+
propA = TNumber(10),
1075+
propB = TNumber(20),
1076+
propC = TNumber(30),
1077+
d = TNumber(40),
1078+
e = TNumber(50),
1079+
f = TNumber(60),
1080+
G = TGetter("G"),
1081+
H = TGetter("H"),
1082+
myField = TNumber(0),
1083+
myField2 = TNumber(0),
1084+
}, "this_props", num_fields: 10);
1085+
}
1086+
}
1087+
);
1088+
}
10421089
}
10431090
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
</PropertyGroup>
4+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
3+
namespace DebuggerTests
4+
{
5+
public class NormalClass
6+
{
7+
public int myField2;
8+
}
9+
10+
[System.Diagnostics.DebuggerNonUserCode]
11+
public class ClassNonUserCodeToInheritThatInheritsFromNormalClass : NormalClass
12+
{
13+
private int propA {get;}
14+
public int propB {get;}
15+
protected int propC {get;}
16+
private int d;
17+
public int e;
18+
protected int f;
19+
public int G
20+
{
21+
get {return f + 1;}
22+
}
23+
public int H => f;
24+
25+
public ClassNonUserCodeToInheritThatInheritsFromNormalClass()
26+
{
27+
propA = 10;
28+
propB = 20;
29+
propC = 30;
30+
d = 40;
31+
e = 50;
32+
f = 60;
33+
Console.WriteLine(propA);
34+
Console.WriteLine(propB);
35+
Console.WriteLine(propC);
36+
Console.WriteLine(d);
37+
Console.WriteLine(e);
38+
Console.WriteLine(f);
39+
}
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<DebugType>none</DebugType>
4+
<DebugSymbols>false</DebugSymbols>
5+
</PropertyGroup>
6+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
3+
namespace DebuggerTests
4+
{
5+
public class ClassWithoutDebugSymbolsToInherit
6+
{
7+
private int propA {get;}
8+
public int propB {get;}
9+
protected int propC {get;}
10+
private int d;
11+
public int e;
12+
protected int f;
13+
public int G
14+
{
15+
get {return f + 1;}
16+
}
17+
public int H => f;
18+
19+
public ClassWithoutDebugSymbolsToInherit()
20+
{
21+
propA = 10;
22+
propB = 20;
23+
propC = 30;
24+
d = 40;
25+
e = 50;
26+
f = 60;
27+
Console.WriteLine(propA);
28+
Console.WriteLine(propB);
29+
Console.WriteLine(propC);
30+
Console.WriteLine(d);
31+
Console.WriteLine(e);
32+
Console.WriteLine(f);
33+
}
34+
}
35+
}

src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs

+80
Original file line numberDiff line numberDiff line change
@@ -1275,3 +1275,83 @@ public static void MethodWithHiddenLinesAtTheEnd3()
12751275
#line default
12761276
}
12771277

1278+
public class ClassInheritsFromClassWithoutDebugSymbols : DebuggerTests.ClassWithoutDebugSymbolsToInherit
1279+
{
1280+
public static void Run()
1281+
{
1282+
var myVar = new ClassInheritsFromClassWithoutDebugSymbols();
1283+
myVar.CallMethod();
1284+
}
1285+
1286+
public void CallMethod()
1287+
{
1288+
System.Diagnostics.Debugger.Break();
1289+
}
1290+
public int myField2;
1291+
public int myField;
1292+
}
1293+
1294+
[System.Diagnostics.DebuggerNonUserCode]
1295+
public class ClassNonUserCodeToInherit
1296+
{
1297+
private int propA {get;}
1298+
public int propB {get;}
1299+
protected int propC {get;}
1300+
private int d;
1301+
public int e;
1302+
protected int f;
1303+
public int G
1304+
{
1305+
get {return f + 1;}
1306+
}
1307+
public int H => f;
1308+
1309+
public ClassNonUserCodeToInherit()
1310+
{
1311+
propA = 10;
1312+
propB = 20;
1313+
propC = 30;
1314+
d = 40;
1315+
e = 50;
1316+
f = 60;
1317+
Console.WriteLine(propA);
1318+
Console.WriteLine(propB);
1319+
Console.WriteLine(propC);
1320+
Console.WriteLine(d);
1321+
Console.WriteLine(e);
1322+
Console.WriteLine(f);
1323+
}
1324+
}
1325+
1326+
public class ClassInheritsFromNonUserCodeClass : ClassNonUserCodeToInherit
1327+
{
1328+
public static void Run()
1329+
{
1330+
var myVar = new ClassInheritsFromNonUserCodeClass();
1331+
myVar.CallMethod();
1332+
}
1333+
1334+
public void CallMethod()
1335+
{
1336+
System.Diagnostics.Debugger.Break();
1337+
}
1338+
1339+
public int myField2;
1340+
public int myField;
1341+
}
1342+
1343+
public class ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass : DebuggerTests.ClassNonUserCodeToInheritThatInheritsFromNormalClass
1344+
{
1345+
public static void Run()
1346+
{
1347+
var myVar = new ClassInheritsFromNonUserCodeClassThatInheritsFromNormalClass();
1348+
myVar.CallMethod();
1349+
}
1350+
1351+
public void CallMethod()
1352+
{
1353+
System.Diagnostics.Debugger.Break();
1354+
}
1355+
1356+
public int myField;
1357+
}

src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
<ProjectReference Include="..\ApplyUpdateReferencedAssembly\ApplyUpdateReferencedAssembly.csproj" />
2222
<ProjectReference Include="..\debugger-test-special-char-in-path-#@\debugger-test-special-char-in-path.csproj" ReferenceOutputAssembly="false" />
2323
<ProjectReference Include="..\debugger-test-with-source-link\debugger-test-with-source-link.csproj" ReferenceOutputAssembly="false" Private="true" />
24+
<ProjectReference Include="..\debugger-test-without-debug-symbols-to-load\debugger-test-without-debug-symbols-to-load.csproj" Private="true" />
25+
<ProjectReference Include="..\debugger-test-with-non-user-code-class\debugger-test-with-non-user-code-class.csproj" Private="true" />
2426
<!-- loaded by *tests*, and not the test app -->
2527
<ProjectReference Include="..\lazy-debugger-test-embedded\lazy-debugger-test-embedded.csproj" ReferenceOutputAssembly="false" Private="true" />
2628

@@ -44,14 +46,15 @@
4446
<WasmMainJSPath>debugger-main.js</WasmMainJSPath>
4547
<!-- -1 enabled debugging and disables debug logging. -->
4648
<WasmDebugLevel Condition="'$(WasmDebugLevel)'==''">-1</WasmDebugLevel>
47-
4849
<WasmResolveAssembliesBeforeBuild>true</WasmResolveAssembliesBeforeBuild>
4950
</PropertyGroup>
5051

5152
<ItemGroup>
5253
<WasmAssembliesToBundle Include="$(OutDir)\$(TargetFileName)" />
5354
<WasmAssembliesToBundle Include="$(OutDir)\debugger-test-special-char-in-path.dll" />
5455
<WasmAssembliesToBundle Include="$(OutDir)\debugger-test-with-source-link.dll" />
56+
<WasmAssembliesToBundle Include="$(OutDir)\debugger-test-without-debug-symbols-to-load.dll" />
57+
<WasmAssembliesToBundle Include="$(OutDir)\debugger-test-with-non-user-code-class.dll" />
5558
<WasmAssembliesToBundle Include="$(MicrosoftNetCoreAppRuntimePackRidDir)\lib\$(NetCoreappCurrent)\System.Runtime.InteropServices.JavaScript.dll" />
5659

5760
<!-- Assemblies only dynamically loaded -->
@@ -63,6 +66,7 @@
6366

6467
<WasmAssemblySearchPaths Include="$(MicrosoftNetCoreAppRuntimePackRidDir)native"/>
6568
<WasmAssemblySearchPaths Include="$(MicrosoftNetCoreAppRuntimePackRidDir)lib\$(NetCoreAppCurrent)"/>
69+
<WasmAssemblySearchPaths Include="$(OutDir)"/>
6670
</ItemGroup>
6771
</Target>
6872
<Target Name="PreserveEnCAssembliesFromLinking"

0 commit comments

Comments
 (0)