-
-
Notifications
You must be signed in to change notification settings - Fork 362
doc(FooterCounter): improve performance for ssr mode #6607
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
Conversation
Reviewer's GuideThis PR refactors the FooterCounter component to offload runtime updates to a dedicated JavaScript module for SSR performance, replaces C#-based timers with JS interop via JSModuleAutoLoader, and includes related style and markup optimizations in sample dashboards, video links, and page CSS. Sequence diagram for FooterCounter runtime update via JS interopsequenceDiagram
participant Blazor as Blazor Component (FooterCounter)
participant JS as JavaScript Module (FooterCounter.razor.js)
Blazor->>JS: init(id, totalSeconds) on first render
JS->>JS: Start setInterval(tick, 1000)
JS->>Blazor: (no direct callback, JS updates DOM)
loop Every 30 seconds
Blazor->>JS: updateFooterCounter(id, totalSeconds)
JS->>JS: Update totalSeconds in Data
end
Blazor->>JS: dispose(id) on component dispose
JS->>JS: clearInterval(handler), remove Data
Class diagram for updated FooterCounter componentclassDiagram
class FooterCounter {
- string? Runtime
- readonly CancellationTokenSource _disposeTokenSource
- ConnectionHubOptions _options
+ OnInitialized()
+ OnAfterRenderAsync(bool firstRender)
+ InvokeInitAsync()
+ DisposeAsync(bool disposing)
}
FooterCounter --|> WebSiteModuleComponentBase
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ArgoZhang - I've reviewed your changes - here's some feedback:
Blocking issues:
- User controlled data in methods like
innerHTML,outerHTMLordocument.writeis an anti-pattern that can lead to XSS vulnerabilities (link) - User controlled data in a
el.innerHTMLis an anti-pattern that can lead to XSS vulnerabilities (link)
General comments:
- The DisposeAsync override signature (protected override ValueTask DisposeAsync(bool disposing)) won’t be called by the Blazor runtime—override DisposeAsync() without parameters and invoke your JS module’s dispose(id) to clear the client‐side interval.
- Swapping VideoUrl.Any() for VideoUrl.Count > 0 may force full enumeration on IEnumerable; consider reverting to .Any() for a more efficient existence check.
- Silently catching all exceptions in OnAfterRenderAsync can hide issues—at minimum log or handle unexpected errors instead of swallowing them.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The DisposeAsync override signature (protected override ValueTask DisposeAsync(bool disposing)) won’t be called by the Blazor runtime—override DisposeAsync() without parameters and invoke your JS module’s dispose(id) to clear the client‐side interval.
- Swapping VideoUrl.Any() for VideoUrl.Count > 0 may force full enumeration on IEnumerable; consider reverting to .Any() for a more efficient existence check.
- Silently catching all exceptions in OnAfterRenderAsync can hide issues—at minimum log or handle unexpected errors instead of swallowing them.
## Individual Comments
### Comment 1
<location> `src/BootstrapBlazor.Server/Components/Components/FooterCounter.razor.js:13` </location>
<code_context>
+ const counter = Data.get(id);
+
+ counter.totalSeconds = (counter.totalSeconds || 0) + 1;
+ const now = Math.round(counter.totalSeconds, 0);
+
+ const days = Math.floor(now / (24 * 3600));
</code_context>
<issue_to_address>
Math.round does not accept a second argument.
Remove the second argument from Math.round, as it is ignored. If you need to round to a specific decimal place, consider using a different method.
</issue_to_address>
## Security Issues
### Issue 1
<location> `src/BootstrapBlazor.Server/Components/Components/FooterCounter.razor.js:21` </location>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities
*Source: opengrep*
</issue_to_address>
### Issue 2
<location> `src/BootstrapBlazor.Server/Components/Components/FooterCounter.razor.js:21` </location>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `el.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities
*Source: opengrep*
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const counter = Data.get(id); | ||
|
|
||
| counter.totalSeconds = (counter.totalSeconds || 0) + 1; | ||
| const now = Math.round(counter.totalSeconds, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: Math.round does not accept a second argument.
Remove the second argument from Math.round, as it is ignored. If you need to round to a specific decimal place, consider using a different method.
| const seconds = now % 60; | ||
|
|
||
| const pad = num => num.toString().padStart(2, '0'); | ||
| el.innerHTML = `Run ${pad(days)}.${pad(hours)}:${pad(minutes)}:${pad(seconds)}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities
Source: opengrep
| const seconds = now % 60; | ||
|
|
||
| const pad = num => num.toString().padStart(2, '0'); | ||
| el.innerHTML = `Run ${pad(days)}.${pad(hours)}:${pad(minutes)}:${pad(seconds)}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
security (javascript.browser.security.insecure-innerhtml): User controlled data in a el.innerHTML is an anti-pattern that can lead to XSS vulnerabilities
Source: opengrep
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6607 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 739 739
Lines 31669 31669
Branches 4458 4458
=========================================
Hits 31669 31669
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Link issues
fixes #6606
Summary By Copilot
Regression?
Risk
Verification
Packaging changes reviewed?
☑️ Self Check before Merge
Summary by Sourcery
Improve SSR performance by migrating FooterCounter timer logic to a client-side JavaScript module, refactoring the component lifecycle, and making related UI and style adjustments
Enhancements: