Conversation
Reviewer's guide (collapsed on small PRs)Reviewer's GuideOptimizes the HikVision component disposal flow by making plugin teardown asynchronous-safe, ensuring the plugin is hidden and destroyed before removing instance data, and tightening up observer cleanup. Sequence diagram for the updated HikVision dispose processsequenceDiagram
actor Caller
participant HikVisionModule as HikVisionModule
participant Data as Data
participant Observer as Observer
participant WebVideoCtrl as WebVideoCtrl
Caller->>HikVisionModule: dispose(id)
HikVisionModule->>Data: get(id)
Data-->>HikVisionModule: vision
HikVisionModule->>Observer: disconnect()
HikVisionModule->>WebVideoCtrl: I_HidPlugin()
alt realPlaying is true
HikVisionModule->>HikVisionModule: stopRealPlay(id)
HikVisionModule->>WebVideoCtrl: I_StopRealPlay(id)
end
alt logined is true
HikVisionModule->>HikVisionModule: logout(id)
HikVisionModule->>WebVideoCtrl: I_Logout(id)
end
HikVisionModule->>WebVideoCtrl: I_DestroyPlugin()
HikVisionModule->>Data: remove(id)
HikVisionModule-->>Caller: dispose complete
Flow diagram for the new HikVision plugin destroy promiseflowchart LR
A[Start destroyPlugin] --> B[Call JSVideoPlugin.DestroyPlugin]
B --> C[Set JSVideoPlugin to null]
C --> D[Delete window.JSVideoPlugin]
D --> E[Call removePlugin]
E --> F[Create new Promise]
F --> G[Resolve Promise]
G --> H[End destroyPlugin]
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.
Hey there - I've reviewed your changes - here's some feedback:
- In
hackJSDestroyPlugin, consider returningPromise.resolve()instead of manually constructing a new promise, and ensure the function consistently returns a promise even whenJSVideoPluginis falsy so callers can rely on a stable async contract. - In
dispose(id),Data.get(id)can potentially returnundefined, so it would be safer to guard againstvisionbeing nullish before destructuring and using its properties to avoid runtime errors. - Before calling
WebVideoCtrl.I_HidPlugin()andWebVideoCtrl.I_DestroyPlugin()indispose, it may be worth checking thatWebVideoCtrlis defined to prevent errors if the plugin script fails to load or is not initialized.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `hackJSDestroyPlugin`, consider returning `Promise.resolve()` instead of manually constructing a new promise, and ensure the function consistently returns a promise even when `JSVideoPlugin` is falsy so callers can rely on a stable async contract.
- In `dispose(id)`, `Data.get(id)` can potentially return `undefined`, so it would be safer to guard against `vision` being nullish before destructuring and using its properties to avoid runtime errors.
- Before calling `WebVideoCtrl.I_HidPlugin()` and `WebVideoCtrl.I_DestroyPlugin()` in `dispose`, it may be worth checking that `WebVideoCtrl` is defined to prevent errors if the plugin script fails to load or is not initialized.
## Individual Comments
### Comment 1
<location> `src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js:90-91` </location>
<code_context>
delete window.JSVideoPlugin;
removePlugin();
+
+ return new Promise((resolve, reject) => {
+ resolve();
+ });
}
</code_context>
<issue_to_address>
**suggestion:** Avoid redundant Promise construction and inconsistent return type from `hackJSDestroyPlugin`.
Because this only returns a `Promise` when `JSVideoPlugin` exists and `undefined` otherwise, callers get an inconsistent return type. The manual `new Promise` is also unnecessary since it resolves synchronously. Prefer returning `Promise.resolve()` (or `Promise.resolve(undefined)`) in all paths so the function always returns a `Promise` that can be safely `await`ed.
Suggested implementation:
```javascript
JSVideoPlugin = null;
delete window.JSVideoPlugin;
removePlugin();
return Promise.resolve();
}
}
```
To fully implement your suggestion, you should also:
1. Locate the full `hackJSDestroyPlugin` function in this file.
2. Ensure that all code paths within `hackJSDestroyPlugin` return a `Promise`, e.g. `return Promise.resolve();` or `return Promise.resolve(undefined);` when the plugin does not exist or when early-returning for other reasons.
3. If the function is sometimes called without awaiting previously, verify that callers still behave correctly given it now always returns a `Promise`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR improves the dispose performance for the HikVision component by adjusting the cleanup sequence and adding plugin hiding functionality. The changes address issue #802 by optimizing resource cleanup order and ensuring the plugin is properly hidden during disposal.
Key Changes
- Added Promise return to
hackJSDestroyPluginfor consistency with async operation patterns - Reordered cleanup operations in
dispose()function, movingData.remove(id)to the end - Added
WebVideoCtrl.I_HidPlugin()call early in the dispose process
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js | Modified dispose flow to hide plugin earlier and defer data removal; added Promise return to hackJSDestroyPlugin |
| src/components/BootstrapBlazor.HikVision/BootstrapBlazor.HikVision.csproj | Version bump from 10.0.2 to 10.0.3 |
Comments suppressed due to low confidence (3)
src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js:1
- Unused import registerBootstrapBlazorModule.
import { addScript, registerBootstrapBlazorModule } from '../BootstrapBlazor/modules/utility.js';
src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js:76
- Unused variable originalDestroy.
const originalDestroy = JSVideoPlugin.prototype.JS_DestroyPlugin;
src/components/BootstrapBlazor.HikVision/wwwroot/hikvision.js:190
- Unused variable logined.
const { szDeviceIdentify, logined } = vision;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (realPlaying === true) { | ||
| stopRealPlay(id); | ||
| } | ||
| if (logined === true) { | ||
| logout(id); | ||
| } |
There was a problem hiding this comment.
The dispose function calls async functions stopRealPlay(id) and logout(id) without awaiting them. This creates a race condition where WebVideoCtrl.I_DestroyPlugin() and Data.remove(id) may execute before the stop/logout operations complete, potentially causing resource leaks or errors.
Consider making dispose async and awaiting these operations:
export async function dispose(id) {
const vision = Data.get(id);
const { realPlaying, logined, observer } = vision;
if (observer) {
observer.disconnect();
}
WebVideoCtrl.I_HidPlugin();
if (realPlaying === true) {
await stopRealPlay(id);
}
if (logined === true) {
await logout(id);
}
WebVideoCtrl.I_DestroyPlugin();
Data.remove(id);
}
Link issues
fixes #802
Summary By Copilot
Regression?
Risk
Verification
Packaging changes reviewed?
☑️ Self Check before Merge
Summary by Sourcery
Improve HikVision video plugin disposal sequence to enhance performance and stability when cleaning up resources.
Enhancements: