Skip to content

Adding analyzer to warn about JSInterop calls not wrapped in a try catch block - #67900

Merged
ilonatommy merged 36 commits into
dotnet:mainfrom
MayaKirova:mkirova/unguarded-JSInterop-analyzer
Jul 21, 2026
Merged

Adding analyzer to warn about JSInterop calls not wrapped in a try catch block#67900
ilonatommy merged 36 commits into
dotnet:mainfrom
MayaKirova:mkirova/unguarded-JSInterop-analyzer

Conversation

@MayaKirova

Copy link
Copy Markdown
Contributor

Adding analyzer to warn about JSInterop calls not wrapped in a try catch block

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Description

Added analyzer that shows warnning and code fixer that wraps the JSInterop calls (InvokeAsync, InvokeVoidAsync etc.) in try/catch block.

Also added some tests:

Area Test Scenario Expected Result
Analyzer Unguarded IJSRuntime extension call (InvokeVoidAsync) Warning is reported
Analyzer Unguarded IJSObjectReference extension call (InvokeVoidAsync) Warning is reported
Analyzer Unguarded IJSRuntime.InvokeAsync<T> call Warning is reported
Analyzer Unguarded IJSObjectReference.InvokeAsync<T> call Warning is reported
Analyzer Unguarded IJSInProcessRuntime.Invoke<T> call Warning is reported
Analyzer Unguarded IJSInProcessObjectReference.Invoke<T> call Warning is reported
Analyzer JS interop call already inside try/catch No diagnostic is reported
Analyzer JS interop call nested in guarded flow (if inside try/catch) No diagnostic is reported
Code Fixer Unguarded awaited InvokeVoidAsync Call is wrapped in try/catch
Code Fixer Unguarded awaited InvokeAsync<T> Call is wrapped in try/catch
Code Fixer Unguarded non-awaited InvokeVoidAsync Call is wrapped in try/catch

Fixes #67306

MayaKirova and others added 30 commits June 30, 2026 14:09
… to string type names. Add more tests accordingly.
… block with at least one catch as guarded. Adding tests accordingly.
…dd some tests for calls inside lambda expressions.
…JSDisconnectedException or generic Exception.
Co-authored-by: Youssef Fahmy <youssefvictor00@gmail.com>
…eption, JSDisconnectedException or generic Exception."

This reverts commit 48fa81a.
… be different types of exceptions thrown."

This reverts commit 218e570.
Co-authored-by: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Co-authored-by: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 20, 2026 09:33
@MayaKirova
MayaKirova requested a review from a team as a code owner July 20, 2026 09:33
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Jul 20, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Thanks for your PR, @MayaKirova. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new Components analyzer (and code fix) to warn when JavaScript interop calls aren’t wrapped in a try/catch, aiming to improve resiliency in scenarios like prerendering and disconnected clients.

Changes:

  • Added JSInteropAnalyzer to report a warning for unguarded JS interop invocations.
  • Added JSInteropCodeFixProvider plus new unit tests covering diagnostics and fix behavior.
  • Updated template sample and diagnostics documentation to reflect the new guidance.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/ProjectTemplates/Web.ProjectTemplates/content/RazorClassLibrary-CSharp/ExampleJsInterop.cs Updates template sample to wrap JS interop calls in try/catch and provide clearer failures.
src/Components/Analyzers/test/JSInteropCodeFixProviderTest.cs Adds tests validating the new code fix behavior.
src/Components/Analyzers/test/JSInteropAnalyzerTest.cs Adds tests validating diagnostics for various JS interop call shapes and contexts.
src/Components/Analyzers/src/Resources.resx Adds localized strings for the new diagnostic and code fix.
src/Components/Analyzers/src/JSInteropCodeFixProvider.cs Introduces a code fix to wrap eligible JS interop calls in try/catch.
src/Components/Analyzers/src/JSInteropAnalyzer.cs Introduces the analyzer logic for detecting unguarded JS interop calls.
src/Components/Analyzers/src/DiagnosticDescriptors.cs Registers the new diagnostic descriptor and assigns an ID.
docs/list-of-diagnostics.md Updates the published diagnostic list/range for BL diagnostics.

Comment thread src/Components/Analyzers/src/DiagnosticDescriptors.cs Outdated
Comment on lines +114 to +123
SyntaxFactory.CatchClause()
.WithCatchKeyword(SyntaxFactory.Token(indentList, SyntaxKind.CatchKeyword, SyntaxFactory.TriviaList(SyntaxFactory.Space)))
.WithDeclaration(
SyntaxFactory.CatchDeclaration(
SyntaxFactory.ParseTypeName("Exception"))
.WithCloseParenToken(SyntaxFactory.Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, eolList)))
.WithBlock(
SyntaxFactory.Block()
.WithOpenBraceToken(SyntaxFactory.Token(indentList, SyntaxKind.OpenBraceToken, eolList))
.WithCloseBraceToken(SyntaxFactory.Token(indentList, SyntaxKind.CloseBraceToken, SyntaxTriviaList.Empty)))),
Comment thread docs/list-of-diagnostics.md
@ilonatommy

Copy link
Copy Markdown
Member

@MayaKirova, we have to wait for #67898, then we can merge/rerun.

@ilonatommy

Copy link
Copy Markdown
Member

await using var module = await jsRuntime.InvokeAsync<IJSObjectReference>(

build

auto-merge was automatically disabled July 21, 2026 06:58

Head branch was pushed to by a user without write access

@ilonatommy
ilonatommy merged commit 6b3ab41 into dotnet:main Jul 21, 2026
27 checks passed
@ilonatommy ilonatommy added this to the 11.0-preview7 milestone Jul 21, 2026
Comment on lines +38 to +41
catch (JSException ex)
{
throw new InvalidOperationException("Unable to invoke the web worker JavaScript function.", ex);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ilonatommy I'm not sure how is this better than letting the call throw, if an exception is going to propagate up anyways?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better because it prevents the warnings that are treated as errors in the template tests and would fail the CI. The alternative would be to supress this warning but that's not a good practice for the template code. User can decide to swallow the exception if they want but I don't think we should promote such a solution in the template.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Blazor] Analyzer to warn about JSInterop calls not wrapped in a try catch block

4 participants