Search code examples
rustwasm-bindgen

type mismatch resolving future_to_promise


I'm trying to do below:

  1. Receive function via argument
  2. Execute the function that returns Promise
  3. Wait Promise to be resolved
  4. Execute something
  5. return Promise
fn get_replaced(parser: Parser, string_generators: Vec<Function>, initial_capacity: usize) -> Result<JsString, JsValue> {
    // do something
}
#[wasm_bindgen]
pub fn markdown_img_url_editor(markdown_text: &str, converter: &Function, before_collect_callback: JsValue) -> Promise {

// do something
    if before_collect_callback.is_null() || before_collect_callback.is_undefined() {
        // do something
    } else {
        match before_collect_callback.dyn_into::<Function>() {
            Ok(callback) => {
                match callback.call0(&JsValue::NULL) {
                    Ok(maybe_promise) => {
                        if let Ok(p) = maybe_promise.dyn_into::<Promise>() {

                            // return p.then(&Closure::wrap(Box::new(move |_| get_replaced_wrap(parser, string_generators, markdown_text.len() + 128))));
                            let future = JsFuture::from(p).compat().then(|_| future::ready(get_replaced(parser, string_generators, markdown_text.len() + 128)));
                            let ff = future.compat();
                            return future_to_promise(ff);

At first, I want to call js_sys::Promise#then. However, there is no way to return something from the closure passed to js_sys::Promise#then.

So, I'm trying to convert js_sys::Promise to wasm_bindgen_futures::JsFuture, call futures::future::TryFutureExt#and_then and convert wasm_bindgen_futures::JsFuture to js_sys::Promise using future_to_promise.

Now, I get compile error shown below:

$cargo build
   Compiling markdown_img_url_editor_rust v0.1.0 (C:\msys64\home\yumetodo\markdown_img_url_editor\markdown_img_url_editor_rust)
warning: unused import: `futures::future::Future`
 --> src\lib.rs:6:5
  |
6 | use futures::future::Future;
  |     ^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

error[E0271]: type mismatch resolving `<futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<wasm_bindgen_futures::legacy_shared::JsFuture>, futures_util::future::ready::Ready<std::result::Result<js_sys::JsString, wasm_bindgen::JsValue>>, [closure@src\lib.rs:116:74: 116:159 parser:_, string_generators:_, markdown_text:_]> as core::future::future::Future>::Output == std::result::Result<wasm_bindgen::JsValue, _>`
   --> src\lib.rs:118:36
    |
118 |                             return future_to_promise(ff);
    |                                    ^^^^^^^^^^^^^^^^^ expected struct `js_sys::JsString`, found struct `wasm_bindgen::JsValue`
    |
    = note: expected type `std::result::Result<js_sys::JsString, wasm_bindgen::JsValue>`
               found type `std::result::Result<wasm_bindgen::JsValue, _>`
    = note: required because of the requirements on the impl of `futures_core::future::TryFuture` for `futures_util::future::then::Then<futures_util::compat::compat01as03::Compat01As03<wasm_bindgen_futures::legacy_shared::JsFuture>, futures_util::future::ready::Ready<std::result::Result<js_sys::JsString, wasm_bindgen::JsValue>>, [closure@src\lib.rs:116:74: 116:159 parser:_, string_generators:_, markdown_text:_]>`
    = note: required by `wasm_bindgen_futures::legacy::future_to_promise`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0271`.
error: Could not compile `markdown_img_url_editor_rust`.

found type std::result::Result<wasm_bindgen::JsValue, _>

I cannot understand the reason these error was occered. get_replaced returns Result<JsString, JsValue>. Why error meesage says that found type std::result::Result<wasm_bindgen::JsValue, _>????

Please tell me how to resolve this error or anthoer solution.


Cargo.toml

[package]
name = "markdown_img_url_editor_rust"
version = "0.1.0"
authors = ["yumetodo <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
pulldown-cmark = "0.5.3"
pulldown-cmark-to-cmark = "1.2.2"
wasm-bindgen = "0.2.50"
# wasm-bindgen-futures = "0.3.27"
wasm-bindgen-futures = { version="0.3.27", features=["futures_0_3"] }
js-sys = "0.3.27"
futures-preview = { version="0.3.0-alpha", features=["compat"] }
# futures-preview="0.3.0-alpha"

[lib]
crate-type = ["cdylib"]

full source code is below:
https://github.com/yumetodo/markdown_img_url_editor/tree/refaactor/by_rust/markdown_img_url_editor_rust

My build env is below:

$rustup --version
rustup 1.18.3 (435397f48 2019-05-22)
$cargo --version
cargo 1.37.0 (9edd08916 2019-08-02)
$rustc --version
rustc 1.37.0 (eae3437df 2019-08-13)

OS: Windows 10 1809, Ubuntu 18.04


Solution

  • Finally, I gave up to fight and decide to refactor API. future_to_promise request static lifetime &str and pulldown_cmark only accept &'a str is a critical problem.

    ref: https://qiitadon.com/web/statuses/102710559203790261(written in Japanese)

    To refactor API, I made a bold assumption that the parser will produce the same result for the same input. So, I can decide not to hold parser.

    As a result, I make such API

    #[wasm_bindgen]
    pub struct MarkdownImgUrlEditor {
        markdown_text: String,
        string_generators: Vec<Function>,
        initial_capacity: usize,
    }
    #[wasm_bindgen]
    impl MarkdownImgUrlEditor {
        #[wasm_bindgen(constructor)]
        pub fn new(text: String, converter: &Function) -> Result<MarkdownImgUrlEditor, JsValue> {
        }
        pub fn replace(&mut self) -> Result<String, JsValue> {
        }
    }
    

    the process that before_collect_callback do will be executed between calling new and replace.

    https://github.com/yumetodo/markdown_img_url_editor/pull/13


    BTW, I noticed that pulldown_cmark is broken. I cannot get image alt.

    So, I created an issue.

    https://github.com/raphlinus/pulldown-cmark/issues/394