Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor DLL -> WASM file extension change causing functionality failure when updating to .Net 8 #103071

Open
1 task done
gregsdennis opened this issue Jun 5, 2024 · 7 comments
Labels
arch-wasm WebAssembly architecture area-System.Reflection.Metadata feature-request os-browser Browser variant of arch-wasm
Milestone

Comments

@gregsdennis
Copy link
Contributor

gregsdennis commented Jun 5, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Similar to dotnet/aspnetcore#52162, I need to load assemblies after the website as loaded. However, I'm loading them into a compilation context so that users can enters some C# code which I then compile. (See https://json-everything.net/json-schema (source), and select "Generate a Schema".)

The problem on that site (because I haven't updated it yet) is that it can't find the .dlls... because they've been renamed to .wasms. I'm okay with the rename.

My problem, however, is that these .wasm files aren't accepted by the .Net emitter.

This code works in .Net 6, using .dll files:

Loading the references

var stream = await Client.GetStreamAsync(source);
references.Add(MetadataReference.CreateFromStream(stream));

Compiling

var syntaxTree = CSharpSyntaxTree.ParseText(fullSource);
var assemblyPath = Path.ChangeExtension(Path.GetTempFileName(), "dll");

var compilation = CSharpCompilation.Create(Path.GetFileName(assemblyPath))
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
    .AddReferences(references)
    .AddSyntaxTrees(syntaxTree);

using var dllStream = new MemoryStream();
using var pdbStream = new MemoryStream();
using var xmlStream = new MemoryStream();
var emitResult = compilation.Emit(dllStream, pdbStream, xmlStream);
if (!emitResult.Success)
{
    // .net 6 doesn't enter here
    // but .net 8 does with no changes except for the file extension
    return "Compilation error";
}

var assembly = Assembly.Load(dllStream.ToArray());

The diagnostics in the emitResult are primarily to do with the references:

error CS0009: Metadata file '<in-memory assembly>' could not be opened -- PE image doesn't contain managed metadata.

This happens whether the code should compile or not.

Expected Behavior

I expect the files to load into the compilation context and the emit to work, just as it does with .Net 6.

Steps To Reproduce

Minimal repro: https://github.com/gregsdennis/aspnet56080-repro

The solution file is in /BlazorApp1 for some reason. Not sure how that happened.

The .Net 6 app works fine, but the .Net 8 app doesn't. The only thing the .Net 8 app does differently is load .wasms instead of .dlls.

Exceptions (if any)

There are no exceptions, just the emit diagnostics.

.NET Version

8.0.206

Anything else?

Happy to know if there's something I'm missing, but it's obvious to me that the contents of a .wasm are different from the contents of a .dll. The assembly loader may be set up to understand and account for the difference, but the compiler/emitter isn't.

workaround

disable the .wasm extension for your project:

<PropertyGroup>
  <WasmEnableWebcil>false</WasmEnableWebcil>
</PropertyGroup>
@ScarletKuro
Copy link

ScarletKuro commented Jun 5, 2024

Just disable the .wasm extension for your project:

<PropertyGroup>
  <WasmEnableWebcil>false</WasmEnableWebcil>
</PropertyGroup>

More info: Webcil Documentation

In short, the payload is different, and .NET cannot load this directly. The webcil to PE conversion is not supported, and this is intentional.

@javiercn javiercn transferred this issue from dotnet/aspnetcore Jun 5, 2024
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 5, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Jun 5, 2024
@javiercn
Copy link
Member

javiercn commented Jun 5, 2024

@maraf @lewing FYI

@gregsdennis
Copy link
Contributor Author

So I won't be able to cater to those people who have that firewall issue that's mentioned in that doc. I get that it's the same for .Net 6, which doesn't have .wasm files, but it's a shame I can't use them because someone(s) decided not to support it.

@gregsdennis
Copy link
Contributor Author

Disabling WebCIL did work, BTW.

@JakeYallop
Copy link
Contributor

I had this same problem for my project as well (WasmSharp), I've not been contributing to it for a while, but I do have a couple of things bookmarked to look at regarding WebCIL, the idea being that maybe (eventually) I could accept the WebCIL format and decode it myself.

Firstly, there is this PR which adds support to ILSpy for decoding WebCIL: icsharpcode/ILSpy#3184

And more importantly, I found this:

https://github.com/StefH/ProtoBufJsonConverter/tree/main/src-webcil

Generate a valid MetadataReference based on a Wasm wrapped Webcil stream (MetadataReferenceService.BlazorWasm)

I haven't had the time to investigate any further myself, but I'll leave these links here in case they are useful

@lambdageek lambdageek added arch-wasm WebAssembly architecture area-System.Reflection.Metadata os-browser Browser variant of arch-wasm and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 6, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-reflection-metadata
See info in area-owners.md if you want to be subscribed.

@pavelsavara pavelsavara added this to the Future milestone Jul 11, 2024
@pavelsavara pavelsavara removed the untriaged New issue has not been triaged by the area owner label Jul 11, 2024
@teo-tsirpanis
Copy link
Contributor

Your scenario involves passing to Roslyn assemblies that are already loaded in your app. One way to implement this is:

  • Mono implements AssemblyExtensions.TryGetRawMetadata (currently returns always false).
  • Roslyn adds a MetadataReference.CreateFromAssemblyMetadata(Assembly) API that calls the above API.
    • It has the capability to read raw metadata without a PE file; we need to expose it.
  • User code calls the above API.

There isn't something required here on SRM's side. Reading metadata from WebCIL files without loading them should be tracked by a separate issue, if someone requests it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-wasm WebAssembly architecture area-System.Reflection.Metadata feature-request os-browser Browser variant of arch-wasm
Projects
None yet
Development

No branches or pull requests

7 participants