Преглед на файлове

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

* fix(api.js): mock `__TAURI_INTERNALS__` in `mockIPC` and `mockWindows`

* mock internals.invoke instead of internals.ipc
Fabian-Lars преди 1 година
родител
ревизия
97e3341299
променени са 2 файла, в които са добавени 47 реда и са изтрити 25 реда
  1. 5 0
      .changes/fix-mock-tauri-internals.md
  2. 42 25
      tooling/api/src/mocks.ts

+ 5 - 0
.changes/fix-mock-tauri-internals.md

@@ -0,0 +1,5 @@
+---
+'@tauri-apps/api': 'patch:bug'
+---
+
+`mockIPC` and `mockWindows` no longer crash if `window.__TAURI_INTERNALS__` is undefined.

+ 42 - 25
tooling/api/src/mocks.ts

@@ -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__ ?? {}
 }
 
 /**
@@ -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)
   }
 }
 
@@ -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 }
@@ -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'
@@ -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