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

Issues as of 2023-06 .NET 7.0 #3

Open
skowront opened this issue Jun 2, 2023 · 0 comments
Open

Issues as of 2023-06 .NET 7.0 #3

skowront opened this issue Jun 2, 2023 · 0 comments

Comments

@skowront
Copy link

skowront commented Jun 2, 2023

First of all, great project and job. I'd like to share my sincere appreciation.

Secondly as of 06.2023 there are some issues with the code for .NET 7.0 (and I'm talking only about .NET 7.0, I did not test it with other versions).

  1. Basically the project doesn't work with .NET-7.0 unless changes are made,
  2. You are missing instantiation of public List CompileLog { get; set; } in lin 18 in CompileService.cs. The new() operator is needed or NullExceptions are thrown for newer .NET versions.
  3. .NET 7.0 has troubles with loading resource.dlls in Blazor (the default xxx.resources.dll is missing from output _framework directory, only localized ones are present under eg. fr or es directories, therefore an exception is thrown near this line: references.Add(MetadataReference.CreateFromStream(await this._http.GetStreamAsync(_uriHelper.BaseUri + "_framework/" + name)));)
  4. For the same line as aforementioned one, there should be "_framework/" instead of: "/_framework/_bin/"
  5. The function below seems to have some issues. The most concerning is that SyntaxTree in First part returns no diagnostic issues, and they are null, therefore the process crashes.
 public async Task<Assembly> Compile(string code)
        {
            await Init();

            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code, new CSharpParseOptions(LanguageVersion.Preview));
            foreach (var diagnostic in syntaxTree.GetDiagnostics()) //first place where nullexception is thrown
            {
                CompileLog.Add(diagnostic.ToString()); //another because CompileLog has no new() operator
            }

            if (syntaxTree.GetDiagnostics().Any(i => i.Severity == DiagnosticSeverity.Error)) //again null vulnerability
            {
                CompileLog.Add("Parse SyntaxTree Error!"); //again null vulnerability
                return null;
            }

            CompileLog.Add("Parse SyntaxTree Success");

            CSharpCompilation compilation = CSharpCompilation.Create("CompileBlazorInBlazor.Demo", new[] {syntaxTree},
                references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using (MemoryStream stream = new MemoryStream()) 
            {
                EmitResult result = compilation.Emit(stream);

                foreach (var diagnostic in result.Diagnostics) //first place where the diagnostics actually catch the errors
                {
                    CompileLog.Add(diagnostic.ToString());
                }

                if (!result.Success)
                {
                    CompileLog.Add("Compilation error");
                    return null;
                }

                CompileLog.Add("Compilation success!");

                stream.Seek(0, SeekOrigin.Begin);

//                var context = new CollectibleAssemblyLoadContext();
                Assembly assemby = AppDomain.CurrentDomain.Load(stream.ToArray());
                return assemby;
            }

            return null;
        }

I improved that function as follows:

public async Task<Assembly> Compile(string code)
        {
            await Init();
            try
            {
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code, new CSharpParseOptions(LanguageVersion.Preview));
                var diags = syntaxTree.GetDiagnostics();
                for (int i = 0; i < diags.Count(); i++)
                {
                    var diagnostic = diags.ElementAt(i);
                    CompileLog.Add(diagnostic.ToString());
                }

                if (syntaxTree.GetDiagnostics()?.Any(i => i.Severity == DiagnosticSeverity.Error) ?? true)
                {
                    CompileLog.Add("Parse SyntaxTree Error!");
                    return null;
                }

                CompileLog.Add("Parse SyntaxTree Success");

                CSharpCompilation compilation = CSharpCompilation.Create("CompileBlazorInBlazor.Demo", new[] { syntaxTree },
                    references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

                using (MemoryStream stream = new MemoryStream())
                {
                    EmitResult result = compilation.Emit(stream);

                    foreach (var diagnostic in result.Diagnostics)
                    {
                        CompileLog.Add(diagnostic.ToString());
                    }

                    if (!result.Success)
                    {
                        CompileLog.Add("Compilation error");
                        return null;
                    }

                    CompileLog.Add("Compilation success!");

                    stream.Seek(0, SeekOrigin.Begin);

                    Assembly assemby = AppDomain.CurrentDomain.Load(stream.ToArray());
                    return assemby;
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex);
                return null;
            }
            return null;
        }

PS Again, thanks for sharing your project. Some serious gourmet code! Great work!

PS2 This fork resolves some of the issues that I mentioned: https://github.com/BlazorComponents/CompileBlazorInBlazor

Best regards,
TS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant