fix: preserve notification plugin listener context

The notification plugin can return an object whose unregister method
expects its original listener object as this. Calling the extracted
method directly drops that context and produces an unhandled rejection
when the browser shell cleans up listeners.

Constraint: The desktop frontend also runs in browser-like dev shells where Tauri plugin APIs may be partially present
Rejected: Ignore cleanup errors | it leaves noisy unhandled rejections during local UI smoke tests
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- desktopNotifications
Not-tested: Native notification click behavior on every desktop platform
This commit is contained in:
程序员阿江(Relakkes) 2026-05-18 23:00:54 +08:00
parent 47cc63c402
commit 3c23788ff7
2 changed files with 8 additions and 4 deletions

View File

@ -344,7 +344,11 @@ describe('desktopNotifications', () => {
it('forwards notification click targets from native and plugin listeners', async () => {
const unlistenNative = vi.fn()
const unregisterPlugin = vi.fn()
const pluginListener = {
unregister: vi.fn(function (this: unknown) {
expect(this).toBe(pluginListener)
}),
}
type NativeClickCallback = (event: { payload: unknown }) => void
type PluginClickCallback = (notification: unknown) => void
let nativeCallback: NativeClickCallback = () => {
@ -366,7 +370,7 @@ describe('desktopNotifications', () => {
notificationPluginMock.onAction.mockImplementation(async (callback: (notification: unknown) => void) => {
pluginCallback = callback
pluginRegistered = true
return { unregister: unregisterPlugin }
return pluginListener
})
const onTarget = vi.fn()
@ -382,7 +386,7 @@ describe('desktopNotifications', () => {
cleanup()
expect(unlistenNative).toHaveBeenCalledTimes(1)
expect(unregisterPlugin).toHaveBeenCalledTimes(1)
expect(pluginListener.unregister).toHaveBeenCalledTimes(1)
})
it('requests OS-level window attention for blocking prompts', async () => {

View File

@ -339,7 +339,7 @@ function disposePluginListener(listener: unknown): void {
const unregister = listener && typeof listener === 'object'
? (listener as { unregister?: () => Promise<void> | void }).unregister
: undefined
if (unregister) void unregister()
if (typeof unregister === 'function') void unregister.call(listener)
}
export async function installDesktopNotificationClickListener(