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

fix(api.js): mock __TAURI_INTERNALS__ in mockIPC and mockWindows #8534

Merged
merged 2 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/fix-mock-tauri-internals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tauri-apps/api': 'patch:bug'
---

`mockIPC` and `mockWindows` no longer crash if `window.__TAURI_INTERNALS__` is undefined.
67 changes: 42 additions & 25 deletions tooling/api/src/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

interface IPCMessage {
cmd: string
callback: number
error: number
[key: string]: unknown
import { InvokeArgs, InvokeOptions } from './core'

function mockInternals() {
window.__TAURI_INTERNALS__ = window.__TAURI_INTERNALS__ ?? {}
}

/**
Expand Down Expand Up @@ -63,24 +62,41 @@ interface IPCMessage {
* @since 1.0.0
*/
export function mockIPC(
cb: (cmd: string, payload: Record<string, unknown>) => unknown
cb: <T>(cmd: string, payload?: InvokeArgs) => Promise<T>
): void {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
window.__TAURI_INTERNALS__.ipc = async ({
cmd,
callback,
error,
payload
}: IPCMessage) => {
try {
// @ts-expect-error The function key is dynamic and therefore not typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
window[`_${callback}`](await cb(cmd, payload))
} catch (err) {
// @ts-expect-error The function key is dynamic and therefore not typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
window[`_${error}`](err)
}
mockInternals()

window.__TAURI_INTERNALS__.transformCallback = function transformCallback(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
callback?: (response: any) => void,
once = false
) {
const identifier = window.crypto.getRandomValues(new Uint32Array(1))[0]
const prop = `_${identifier}`

Object.defineProperty(window, prop, {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: (result: any) => {
if (once) {
Reflect.deleteProperty(window, prop)
}

return callback && callback(result)
},
writable: false,
configurable: true
})

return identifier
}

window.__TAURI_INTERNALS__.invoke = function <T>(
cmd: string,
args?: InvokeArgs,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
options?: InvokeOptions
): Promise<T> {
return cb(cmd, args)
}
}

Expand Down Expand Up @@ -128,6 +144,7 @@ export function mockWindows(
current: string,
...additionalWindows: string[]
): void {
mockInternals()
window.__TAURI_INTERNALS__.metadata = {
windows: [current, ...additionalWindows].map((label) => ({ label })),
currentWindow: { label: current }
Expand All @@ -153,7 +170,7 @@ export function mockWindows(
* @since 1.6.0
*/
export function mockConvertFileSrc(osName: string): void {
window.__TAURI_INTERNALS__ = window.__TAURI_INTERNALS__ ?? {}
mockInternals()
window.__TAURI_INTERNALS__.convertFileSrc = function (
filePath,
protocol = 'asset'
Expand Down Expand Up @@ -199,9 +216,9 @@ export function clearMocks(): void {
if (window.__TAURI_INTERNALS__?.convertFileSrc)
// @ts-expect-error "The operand of a 'delete' operator must be optional' does not matter in this case
delete window.__TAURI_INTERNALS__.convertFileSrc
if (window.__TAURI_INTERNALS__?.ipc)
if (window.__TAURI_INTERNALS__?.invoke)
// @ts-expect-error "The operand of a 'delete' operator must be optional' does not matter in this case
delete window.__TAURI_INTERNALS__.ipc
delete window.__TAURI_INTERNALS__.invoke
if (window.__TAURI_INTERNALS__?.metadata)
// @ts-expect-error "The operand of a 'delete' operator must be optional' does not matter in this case
delete window.__TAURI_INTERNALS__.metadata
Expand Down