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

Javascript bind->return example #7

Open
ajnewlands opened this issue Sep 24, 2021 · 4 comments
Open

Javascript bind->return example #7

ajnewlands opened this issue Sep 24, 2021 · 4 comments

Comments

@ajnewlands
Copy link

Hello,

It would be very helpful to have a 'hello world' style example of binding a native function into the JavaScript environment and returning a value. I've been able to do the former, but haven't succeeded in actually resolving the returned promise on the JavaScript side.

On the Rust side I have:

    let wvc = wv.clone();
    wv.bind("RustMethod", move |seq, content| {
        println!("{}, {}", seq, content);
        wvc.r#return(seq, 0, "{}");
    });

On the JavaScript side I have tried a few variations on

document.addEventListener("DOMContentLoaded", function() {
    RustMethod("foo").then(
        (response) => {
            console.log("Callback " + response);
        },
        (reject) => {
            console.log("Rejection " + reject);
        }
    );
});

On the Rust side, the method is clearly invoked as evidenced by the println!() macro generating output. However, the promise returned by RustMethod seems to never resolve, suggesting that something is awry with the parameters passed to the return method.

Any pointer towards getting this to work would be much appreciated :-)

@MoAlyousef
Copy link
Collaborator

Hello

I'm not sure I understood the question.
The seq parameter is used to match methods using webview's internal RPC engine.
The req/content parameter is the arguments passed to the js function, represented as JSON. A small example:

extern crate fltk;
extern crate tinyjson; // We use the tinyjson crate to parse the content parameter

use fltk::{app, prelude::*, window};
use tinyjson::JsonValue;

const HTML: &str = r#"
data:text/html,
<!doctype html>
<html>
<body>hello</body>
<script>
    window.onload = function() {
        add(1, 2).then(function(res) {
            document.body.innerText = `added, ${res}`;
          });
    };
</script>
</html>"#;

fn main() {
    let app = app::App::default();
    let mut win = window::Window::default()
        .with_size(800, 600)
        .with_label("Webview");
    let mut wv_win = window::Window::default()
        .with_size(790, 590)
        .center_of_parent();
    win.end();
    win.make_resizable(true);
    win.show();

    let mut wv = fltk_webview::Webview::create(true, &mut wv_win);
    wv.navigate(HTML);
    
    let wvc = wv.clone();
    wv.bind("add", move |seq, content| {
        println!("{}, {}", seq, content);
        let parsed: JsonValue = content.parse().unwrap();
        let val1: &f64 = parsed[0].get().unwrap();
        let val2: &f64 = parsed[1].get().unwrap();
        let ret = val1 + val2;
        wvc.r#return(seq, 0, &ret.to_string());
    });

    app.run().unwrap();
}

If you mean you want to get the value out of the closure, you can do that by passing a smart pointer (usually a Rc<RefCell<T>>, borrow_mut() in the closure, this will give you the value even outside the closure.

    let ret = Rc::from(RefCell::from(0.0));
    let ret_c = ret.clone();
    let wvc = wv.clone();
    wv.bind("add", move |seq, content| {
        println!("{}, {}", seq, content);
        let parsed: JsonValue = content.parse().unwrap();
        let val1: &f64 = parsed[0].get().unwrap();
        let val2: &f64 = parsed[1].get().unwrap();
        *ret_c.borrow_mut() = val1 + val2;
        wvc.r#return(seq, 0, &ret_c.borrow().to_string());
    });

@ajnewlands
Copy link
Author

Hi Mohammed, thank you for getting back to me.

The first case, with the "add" method is exactly what I am talking about.
I added the source code above to a brand new project and it exhibits the same behavior as I saw with my own code, i.e.
(1) stdout reports the sequence number and argument array
(2) The promise doesn't seem to resolve on the javascript side (the body of the document continues to show 'Hello' rather than 'added, 3' as I would expect).

I assume it does work on your system, so perhaps it is platform specific (I tried on a pair of Windows 10 machines with the webview 2 runtime). I'll set up a Linux instance with X11, try it there and report back.

Thanks!
Andrew

@ajnewlands
Copy link
Author

I went and tried the same code on Linux and observed that it does indeed work, so it appears that the webview::return method fails on Windows, only, at least on the pair of machines I tried.

@MoAlyousef
Copy link
Collaborator

Yeah I finally tried on Windows also, and I see what you mention. I think it's this issue here:
webview/webview#498

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants