Skip to content

Commit b2f7349

Browse files
Fix method wiping (#1448)
* Fix wiping assemblies that contain references to others in same directory * Fix generated IL for reporting calls to wiped methods * Add E2E test for method wiping
1 parent d4e2c28 commit b2f7349

File tree

6 files changed

+43
-2
lines changed

6 files changed

+43
-2
lines changed

samples/MonoSanity/wwwroot/index.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@
3636
</form>
3737
</fieldset>
3838

39+
<fieldset>
40+
<legend>Invoke wiped method</legend>
41+
<form id="invokeWipedMethod">
42+
<button type="submit" disabled>Go</button>
43+
<div><textarea rows="5" cols="80" readonly id="invokeWipedMethodStackTrace"></textarea></div>
44+
</form>
45+
</fieldset>
46+
3947
<fieldset>
4048
<legend>Call JS from .NET</legend>
4149
<form id="callJs">
@@ -103,6 +111,16 @@
103111
}
104112
};
105113

114+
el('invokeWipedMethod').onsubmit = function (evt) {
115+
evt.preventDefault();
116+
try {
117+
invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'InvokeWipedMethod', []);
118+
el('invokeWipedMethodStackTrace').value = 'WARNING: No exception occurred';
119+
} catch (ex) {
120+
el('invokeWipedMethodStackTrace').value = ex.toString();
121+
}
122+
};
123+
106124
el('callJs').onsubmit = function (evt) {
107125
evt.preventDefault();
108126
var expression = el('callJsEvalExpression').value;

samples/MonoSanity/wwwroot/loader.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
'mscorlib',
8181
'System',
8282
'System.Core',
83+
'System.Net.Http',
8384
];
8485

8586
var allAssemblyUrls = loadAssemblyUrls

samples/MonoSanityClient/Examples.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Runtime.InteropServices;
77
using System.Text;
8+
using System.Net.Http;
89

910
namespace MonoSanityClient
1011
{
@@ -30,6 +31,11 @@ public static void TriggerException(string message)
3031
throw new InvalidOperationException(message);
3132
}
3233

34+
public static void InvokeWipedMethod()
35+
{
36+
new HttpClientHandler();
37+
}
38+
3339
public static string EvaluateJavaScript(string expression)
3440
{
3541
var result = InternalCalls.InvokeJSUnmarshalled<string, string, object, object>(out var exceptionMessage, "evaluateJsExpression", expression, null, null);

src/Microsoft.AspNetCore.Blazor.BuildTools/Core/ILWipe/MethodWipedExceptionMethod.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public static MethodDefinition AddToAssembly(ModuleDefinition moduleDefinition)
2323
// }
2424
// }
2525
var ilWipeHelpersType = new TypeDefinition("ILWipe", "ILWipeHelpers",
26-
TypeAttributes.NotPublic | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);
26+
TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit,
27+
moduleDefinition.TypeSystem.Object);
2728
moduleDefinition.Types.Add(ilWipeHelpersType);
2829

2930
var methodAttributes =
@@ -38,6 +39,7 @@ public static MethodDefinition AddToAssembly(ModuleDefinition moduleDefinition)
3839

3940
var notImplExceptionType = ImportEquivalentTypeFromMscorlib(moduleDefinition, typeof(NotImplementedException));
4041
var notImplExceptionCtor = new MethodReference(".ctor", moduleDefinition.TypeSystem.Void, notImplExceptionType);
42+
notImplExceptionCtor.HasThis = true;
4143
notImplExceptionCtor.Parameters.Add(new ParameterDefinition(moduleDefinition.TypeSystem.String));
4244

4345
var il = createMethodWipedExceptionMethod.Body.GetILProcessor();

src/Microsoft.AspNetCore.Blazor.BuildTools/Core/ILWipe/WipeAssembly.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ public static void Exec(string inputPath, string outputPath, string specFilePath
4343
}
4444
}
4545

46+
// Also resolve referenced assemblies in the same directory
47+
if (moduleDefinition.AssemblyResolver is DefaultAssemblyResolver resolver)
48+
{
49+
resolver.AddSearchDirectory(Path.GetDirectoryName(inputPath));
50+
}
51+
4652
moduleDefinition.Write(outputPath);
4753
}
4854
}

test/Microsoft.AspNetCore.Blazor.E2ETest/Tests/MonoSanityTest.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure;
@@ -68,6 +68,14 @@ public void CanReceiveDotNetExceptionInJavaScript()
6868
Assert.Contains("Hello from test", GetValue(Browser, "triggerExceptionMessageStackTrace"));
6969
}
7070

71+
[Fact]
72+
public void ProvidesDiagnosticIfInvokingWipedMethod()
73+
{
74+
Browser.FindElement(By.CssSelector("#invokeWipedMethod button")).Click();
75+
76+
Assert.Contains("System.NotImplementedException: Cannot invoke method because it was wiped. See stack trace for details.", GetValue(Browser, "invokeWipedMethodStackTrace"));
77+
}
78+
7179
[Fact]
7280
public void CanCallJavaScriptFromDotNet()
7381
{

0 commit comments

Comments
 (0)