Skip to content

WASM-compilation breaks Microsoft.CodeAnalysis #114950

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

Closed
VYDocuWare opened this issue Apr 23, 2025 · 9 comments
Closed

WASM-compilation breaks Microsoft.CodeAnalysis #114950

VYDocuWare opened this issue Apr 23, 2025 · 9 comments
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript question Answer questions and provide assistance, not an issue with source code or documentation.

Comments

@VYDocuWare
Copy link

VYDocuWare commented Apr 23, 2025

Description

Hello. I've created a project, which makes use of Microsoft.CodeAnalysis, and I compile it to WASM using

<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>

However, when I start RoslynWebAssembly/bin/Release/net9.0/browser-wasm/AppBundle/main.js in a browser environment, I get the following error:

Uncaught ManagedError: Argument_EmptyString Arg_ParamName_Name, path at sn (marshal-to-js.ts:420:18) at gn (managed-exports.ts:316:15) at Object.<anonymous> (invoke-cs.ts:321:17) at main.js:12:50

Any help?

Reproduction Steps

Here's a reproduction of the non-working project: https://github.com/VYDocuWare/RoslynWebAssembly

Expected behavior

The wasm-compiled method returns "IsSpeculativeSemanticModel", which is my test of whether the SemanticModel has been generated.

Actual behavior

I get the following error:

Uncaught ManagedError: Argument_EmptyString Arg_ParamName_Name, path at sn (marshal-to-js.ts:420:18) at gn (managed-exports.ts:316:15) at Object.<anonymous> (invoke-cs.ts:321:17) at main.js:12:50

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

@ghost ghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 23, 2025
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Apr 23, 2025
@jeffschwMSFT jeffschwMSFT added arch-wasm WebAssembly architecture area-VM-meta-mono labels Apr 23, 2025
@lewing lewing added area-System.Runtime.InteropServices.JavaScript and removed area-VM-meta-mono needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Apr 23, 2025
@maraf
Copy link
Member

maraf commented Apr 24, 2025

@VYDocuWare It is an exception raised inside Roslyn codebase. You can wrap your JSExport method with try-catch to get more details

[JSExport]
static bool GetCompiledResult()
{
    try
    {
        var expressionOutcome = ExpressionProcessor.ProcessExpression();
        return expressionOutcome.IsSpeculativeSemanticModel;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex}");
        return false;
    }
}

@maraf maraf added the needs-author-action An issue or pull request that requires more info or actions from the author. label Apr 24, 2025
@VYDocuWare
Copy link
Author

VYDocuWare commented Apr 24, 2025

Thanks. I pushed the try/catch and a simplifying change to the reproduction-repository.

Here's the error I now get:

dotnet.native.js:8 Error: System.ArgumentException: Argument_EmptyString Arg_ParamName_Name, path
dotnet.native.js:8    at System.ArgumentException.ThrowNullOrEmptyException(String , String )
dotnet.native.js:8    at System.ArgumentException.ThrowIfNullOrEmpty(String , String )
dotnet.native.js:8    at System.IO.Strategies.FileStreamHelpers.ValidateArguments(String , FileMode , FileAccess , FileShare , Int32 , FileOptions , Int64 )
dotnet.native.js:8    at System.IO.FileStream..ctor(String , FileMode , FileAccess , FileShare , Int32 , FileOptions , Int64 )
dotnet.native.js:8    at System.IO.FileStream..ctor(String , FileMode , FileAccess , FileShare , Int32 , FileOptions )
dotnet.native.js:8    at System.IO.FileStream..ctor(String , FileMode , FileAccess , FileShare , Int32 , Boolean )
dotnet.native.js:8    at System.IO.FileStream..ctor(String , FileMode , FileAccess , FileShare )
dotnet.native.js:8    at Roslyn.Utilities.StandardFileSystem.OpenFile(String , FileMode , FileAccess , FileShare )
dotnet.native.js:8    at Roslyn.Utilities.CommonCompilerFileSystemExtensions.OpenFileWithNormalizedException(ICommonCompilerFileSystem , String , FileMode , FileAccess , FileShare )
dotnet.native.js:8    at Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(String , MetadataReferenceProperties , DocumentationProvider )
dotnet.native.js:8    at DocuWare.WorkflowDesigner.ExpressionProcessing.ExpressionProcessor.GetProcessingResult()
dotnet.native.js:8    at DocuWare.WorkflowDesigner.ExpressionProcessing.ExpressionProcessor.ProcessExpression()
dotnet.native.js:8    at RoslynWebAssembly.Program.GetCompiledResult()

I see it's due to the below code in ExpressionProcessor.cs:

var compilation = VisualBasicCompilation.Create("TemporaryCompilation",
    syntaxTrees: new[] { tree },
    references: new[]
    {
        MetadataReference.CreateFromFile(typeof(Microsoft.VisualBasic.Constants).Assembly.Location),
        MetadataReference.CreateFromFile(typeof(System.Diagnostics.Debug).Assembly.Location),
        MetadataReference.CreateFromFile(Assembly.Load("System.Runtime, Version=6.0.0.0").Location),
    });

I actually need these references, as I can't validate my code without them. Any help?

@dotnet-policy-service dotnet-policy-service bot removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Apr 24, 2025
@JakeYallop
Copy link
Contributor

.Assembly.Location is empty when running in WASM. To create metadata references, you currently have to redownload the dlls and use CreateFromStream:

https://github.com/JakeYallop/WasmSharp/blob/main/packages/core/src/Services/WasmMetadataReferenceResolver.cs#L24-L31

With #111642, there is probably going to be an easier way to do this in .NET 10.

@maraf maraf added question Answer questions and provide assistance, not an issue with source code or documentation. needs-author-action An issue or pull request that requires more info or actions from the author. labels Apr 24, 2025
@VYDocuWare
Copy link
Author

VYDocuWare commented Apr 24, 2025

Thanks. I now load the .dlls separately, and it seems to work. I pushed the code to the repository. However, from my understanding, this will cause the browser to fetch the .dlls every time there's a validation request.

Is there a way to load the .dlls once, and then reuse them across all the validation requests? That is, can I "store" the .dlls someplace accessible to the validator, and have it check for them?

@dotnet-policy-service dotnet-policy-service bot removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Apr 24, 2025
@VYDocuWare
Copy link
Author

Also, I've noticed that the WASM Expression Validator works in the main browser thread, causing it to block when running. Is there a way to make it run in a separate thread, without using web workers myself?

@JakeYallop
Copy link
Contributor

Is there a way to load the .dlls once, and then reuse them across all the validation requests? That is, can I "store" the .dlls someplace accessible to the validator, and have it check for them?

WasmSharp has a global metadata reference cache that it stores all the metadata references in.

Is there a way to make it run in a separate thread, without using web workers myself?

Not that I know of - however it's been a while since I last looked into any of this (including e.g multi-threaded WASM).

@maraf
Copy link
Member

maraf commented Apr 25, 2025

Also, I've noticed that the WASM Expression Validator works in the main browser thread, causing it to block when running. Is there a way to make it run in a separate thread, without using web workers myself?

If you set WasmEnableThreads=true in your csproj, you'll get a multi threaded .NET runtime. It's still experimental, but the progress from last year is amazing.

@VYDocuWare
Copy link
Author

WasmSharp has a global metadata reference cache that it stores all the metadata references in.

How can I make use of this in my own project?

@JakeYallop
Copy link
Contributor

It's more complicated that it sounds - its just a

static readonly List<MetadataReference> References

With a wrapper class around it.

@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Apr 25, 2025
@github-actions github-actions bot locked and limited conversation to collaborators May 27, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript question Answer questions and provide assistance, not an issue with source code or documentation.
Projects
None yet
Development

No branches or pull requests

5 participants