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

[bug] Tauri command sends Result<(PathBuf, Vec<u8>, [isize; MAX_DIMS]), ipc_core::ErrorTy> as Array(3) #6455

Closed
JohnScience opened this issue Mar 15, 2023 · 3 comments
Labels
status: needs triage This issue needs to triage, applied to new issues type: bug

Comments

@JohnScience
Copy link

Describe the bug

I have the following Tauri command:

#[tauri::command]
fn default_slice_with_metadata(
    app_handle: tauri::AppHandle,
) -> Result<(PathBuf, Vec<u8>, [isize; MAX_DIMS]), ipc_core::ErrorTy> {
    // ...
    Ok(sent)
}

I.e. its return type is Result<(PathBuf, Vec<u8>, [isize; MAX_DIMS]), ipc_core::ErrorTy>.

On the frontend, we use wasm_bindgen to access global Tauri object and call invoke on it:

// tauri.rs
// ...
    #[wasm_bindgen]
    extern "C" {
        // At the time of writing, wasm_bindgen supports only async functions that return a JsValue
        #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "dialog"], js_name = "open")]
        pub async fn js_open(options: JsValue) -> JsValue;
        #[wasm_bindgen(js_namespace = ["window", "__TAURI__"], js_name = "invoke")]
        pub async fn invoke_1(cmd_name: &str, args: JsValue) -> JsValue;
        #[wasm_bindgen(js_namespace = ["window", "__TAURI__"], js_name = "invoke")]
        pub async fn invoke_0(cmd_name: &str) -> JsValue;
    }
// ...

On top of it we use a wrapper that makes calls to default_slice_with_metadata Tauri command more convenient:

#[cfg(feature = "tauri")]
pub async fn default_slice_with_metadata(
) -> Result<(PathBuf, Vec<u8>, [isize; MAX_DIMS]), ErrorTy> {
    let js_value = tauri_ipc::invoke_0("default_slice_with_metadata").await;
    crate::log(&js_value);
    let mock: Result<(PathBuf, Vec<u8>, [isize; MAX_DIMS]), ErrorTy> = Ok((PathBuf::new(), vec![], [0; MAX_DIMS]));
    let mock = serde_wasm_bindgen::to_value(&mock).unwrap();
    crate::log(&mock);
    serde_wasm_bindgen::from_value(js_value)
        .expect("serde_wasm_bindgen::from_value failed")
}

The code above was altered a bit because it is meant to demonstrate that Tauri sends the data in a way that is distinct from the way that is expected by serde-wasm-bindgen.

Screenshot (157)

Reproduction

Create a command with a similar signature and send an Ok(...) object.

Expected behavior

Result<(PathBuf, Vec<u8>, [isize; MAX_DIMS]), ipc_core::ErrorTy> should be sent as a value that would be compatible with serde-wasm-bindgen.

Platform and versions

Environment
  › OS: Windows 10.0.19045 X64
  › Webview2: 110.0.1587.69
  › MSVC: 
      - Visual Studio Build Tools 2019
  › Node.js: 18.12.1
  › npm: 8.19.2
  › pnpm: Not installed!
  › yarn: Not installed!
  › rustup: 1.25.2
  › rustc: 1.67.1
  › cargo: 1.67.1
  › Rust toolchain: stable-x86_64-pc-windows-msvc

Stack trace

No response

Additional context

No response

@FabianLars
Copy link
Member

I don't think this is possible with the current IPC approach. We convert everything to a JSON string before sending it over the IPC and serde_json converts tuples to arrays (which makes sense when the consumer is javascript).

So i'm not sure if there's anything we can do on our side without breaking everything else but projects using serde-wasm-bindgen 😅

All that said, i've never used serde-wasm-bindgen, nor looked into it much, so if you (or anyone else) have any ideas please share them with us 🙏

cc @JonasKruckenberg, he has way more experience with that bindgen stuff than me.

@JohnScience
Copy link
Author

One way how the breaking change can be avoided is to allow #[tauri::command] attribute macro accept an optional parameter. Another approach would be to add a new item to tauri.conf.json.

@FabianLars
Copy link
Member

Sooo, on closer inspection it looks like this is caused by the Result wrapper 🤔 invoke will only return the actual Ok (or Error) values, resembling Promise.resolve and Promise.reject respectively, without the actual Result/Ok/Error around it, in code this means you get this from invoke:

let js_value: (PathBuf, Vec<u8>, [isize; MAX_DIMS]) = tauri_ipc::invoke_0().await;

instead of this

let js_value: Ok((PathBuf, Vec<u8>, [isize; MAX_DIMS])) = tauri_ipc::invoke_0().await;

and i doubt that this is something we will change since the Result is used to determine if the Promise will be resolved/rejected. Instead i think you need to change your error handling here.

P.S. i didn't test any of this, but their readme which said that tuples get converted to/from arrays (which we also do), made me think the above.

@FabianLars FabianLars closed this as not planned Won't fix, can't repro, duplicate, stale Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: needs triage This issue needs to triage, applied to new issues type: bug
Projects
None yet
Development

No branches or pull requests

2 participants