Skip to content

Proposed switch from neon to node-bindgen #7

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

Closed
mycognosist opened this issue Apr 15, 2021 · 9 comments
Closed

Proposed switch from neon to node-bindgen #7

mycognosist opened this issue Apr 15, 2021 · 9 comments

Comments

@mycognosist
Copy link
Member

Background

While scanning through the latest release of This Week in Rust on Saturday, I noticed this blog post: Sending tuples from Node to Rust and back. That introduced me to an alternative crate for generating bindings for Node: node-bindgen.

Yesterday I converted our batch verification & validation code to use node-bindgen and I have to say I like it a lot. It provides neat type conversion for JS values and stays out of my way so I can write idiomatic Rust code. I'm presenting some pro's and con's of the two approaches here so we can reach a decision together. I'll say up-front that I've in favour of node-bindgen.

Code Samples

A quick comparison of the verification function signatures, argument parsing and module exporting behaviour:

Neon (what we're currently using)

fn verify_message_array(mut cx: FunctionContext) -> JsResult<JsBoolean> {
    let js_msgs: Handle<JsArray> = cx.argument(0)?;
    let msg_array: Vec<Handle<JsValue>> = js_msgs.to_vec(&mut cx)?;

    // code code code

    Ok(cx.boolean(true))
}

// export our function for use in javascript
register_module!(mut cx, {
    cx.export_function("verifySignatures", verify_message_array)?;
}

node-bindgen

The secret sauce here is the #[node_bindgen] attribute (seen above the function signature definition) which automatically generates conversion code for Node and Rust to pass values back and forth.

Note: there's a slight difference here because this function is actually expecting an array of stringified values.

#[node_bindgen(name = "verifySignatures")]
fn verify_messages(array: Vec<String>) -> Result<bool, NjError> {
    // values are immediately available as `array`

    // code code code

    Ok(true)
}

// function is automatically exported ... no extra code required

neon

Pros:

  • CLI package creation support
  • Large user base (greater familiarity among devs?)
  • Also seems actively maintained

Cons:

  • Complicated interface
  • Multi-step type conversion

node-bindgen

Pros:

  • Actively maintained
  • Clean, idiomatic interface (easier to write, easier to maintain)
  • Allows introduction of novel type conversions (custom implementations)

Cons:

Conclusion

Without meaning to be rude, neon feels to me like it was written by JS devs while node-bindgen feels like it was written by Rust devs. Maybe that's an unkind thing to say but with neon I feel like I'm constantly working against the API.

In terms of performance, I have not yet seen a difference, so the key advantage of the switch here is maintainability of our code and improved developer experience. If I showed the node-bindgen validation code to another Rust dev they'd understand it instantly and could get to work implementing new features or making changes (no need to learn the esoterica of neon).

@staltz
Copy link
Member

staltz commented Apr 15, 2021

Yes, sounds great. I'm totally in favor of choosing something according to your intuition, and now the only thing I'm thinking is that I regret calling all these packages -neon because it couples the idea with Neon specifically. I think we could call it -jsrs (or -rsjs?) to make it more generic and also to open up the space for interchanging the rs-to-js library (be it node-bindgen or neon or something else) in the future.

@mycognosist
Copy link
Member Author

Agreed that the generic naming approach is the way to go. -rsjs seems like a nice fit to me (describes the rs-to-js nature of the library). So then this would be ssb-validate2-rsjs :)

Should I get a PR together to enact the switch to node-bindgen?

@staltz
Copy link
Member

staltz commented Apr 15, 2021

Yes and yes! :)

I also feel like renaming ssb-neon

@mycognosist
Copy link
Member Author

Great! I'll start right away :)

Somehow I didn't know about ssb-neon ssb-rsjs. That list of modules is very handy.

@staltz
Copy link
Member

staltz commented Apr 15, 2021

Another thing I'd like to prototype before doubling down on node-bindgen is compiling to Android and iOS. It was a headache to extend Neon to mobile and in the process I also built supporting libraries such as neon-load-or-build. I expect that moving to node-bindgen would give similar headaches.

I don't doubt it's possible, theoretically node-bindgen should work on Android and iOS with nodejs-mobile, we just need to try it out and fix issues until it works.

@mycognosist
Copy link
Member Author

Leaving this here for future reference: infinyon/node-bindgen#114

@staltz
Copy link
Member

staltz commented Apr 15, 2021

Since you're developing on an rpi4, it's already correctly compiling for aarch64, right?

@mycognosist
Copy link
Member Author

That's correct. I've been using my default toolchain for compilation (without any issues):

stable-aarch64-unknown-linux-gnu

@mycognosist
Copy link
Member Author

Housekeeping

I'm closing this issue. Spoiler-alert: we ended up switching to node-bindgen (#8).

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