neon icon indicating copy to clipboard operation
neon copied to clipboard

Question: Why are the conversions like they are?

Open kaldis-berzins opened this issue 5 years ago • 2 comments

I do not intend criticize the framework or the work that the developers have done, I just want to understand the reasoning behind the design of it. Also, I am very new to the framework and haven't built much aside from a few tests and I am not as acquainted with rust as I am with javascript. With that aside, here is my question: why is there a need to explicitly convert from javascript values to rust values? As far as I see it, it just adds bloat to your code. This is the example on how to pass an array to javascript:

fn convert_vec_to_array(mut cx: FunctionContext) -> JsResult<JsArray> {
    let vec: Vec<String> = Vec::with_capacity(100);
    // Create the JS array
    let js_array = JsArray::new(&mut cx, vec.len() as u32);
    // Iterate over the rust Vec and map each value in the Vec to the JS array
    for (i, obj) in vec.iter().enumerate() {
        let js_string = cx.string(obj);
        js_array.set(&mut cx, i as u32, js_string).unwrap();
    }
    Ok(js_array)
}

What is preventing me from just returning a vector and having a match statement in the neon code someplace that converts the vector into a JsArray? And why isn't there a function that can convert a Vec to a JsArray? If it encounters a second Vec it could just recursively convert until it hits a primitive value, which it will eventually do. Same for structs or objects. There could very well be a good reason why some or all of these things are not possible, and I do not intend to criticize the current API. I just want to know why that is.

If conversion was to take place behind the scenes the same function could look like this:

fn convert_vec_to_array(mut cx: FunctionContext) -> std::io::Result<Vec<String>> {
   let vec:Vec<String> = Vec::with_capacity(100);
   Ok(vec)
}

then under the hood it would understand that Result should be a JsResult, Vec should be a JsArray and so on... This could possibly extend to arguments as well, but that could have various issues with object types and such.

kaldis-berzins avatar Apr 01 '20 18:04 kaldis-berzins

That kind of automated conversion is not trivial in a compiled language like Rust. For example, AFAIK it is ~impossible~ quite hard to write an .export_function method that can accept those signatures.

So, the current API is lower level. An option that we've been talking about is using a procedural macro to generate the conversion code at compile time, so that you could write the code from your second example, but that is still a ways off.

goto-bus-stop avatar Aug 14 '20 09:08 goto-bus-stop

This is a feature we really want and some thoughts are starting to be put together for it. https://github.com/neon-bindings/rfcs/pull/43

We were blocked by GAT, but that will be landing soon and hopefully TryFromJs and TryIntoJs traits can be implemented.

kjvalencik avatar Sep 15 '21 21:09 kjvalencik