-
Notifications
You must be signed in to change notification settings - Fork 285
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
Dynamic Loading #646
Dynamic Loading #646
Conversation
6855215
to
9f98c7f
Compare
pub(crate) use functions::*; | ||
|
||
// FIXME: Make this safe! | ||
pub unsafe fn setup() { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
5f111be
to
b5058d3
Compare
This will be reverted with the neon-build refactor.
b5058d3
to
1c0a540
Compare
this is looking fantastic 🥰 We talked about having new N-API versions behind feature flags so we can introduce them in minor releases. How could we support that in this approach? I don't know if it's feasible to do this with #[cfg(feature = "napi-7")]
fn detach_arraybuffer(...) -> Status; If not, perhaps we could generate separate structs for each version. mod napi1 {
generate!(extern "C" {
fn create_undefined(...) -> Status;
});
}
mod napi7 {
generate!(extern "C" {
fn detach_arraybuffer(...) -> Status;
});
}
pub fn setup() {
// wrapped in ONCE.call_once() stuff
napi1::load().expect("Could not load N-API functions");
#[cfg(feature = "napi-7")]
{
napi7::load().expect("Could not load N-API version 7 functions");
}
} |
I did some reading and learned a couple new things about macros. Yes, this is possible! The Additionally, doc comments are syntactic sugar for doc attributes. It will catch them as well, so we can add doc comments to these functions. Are there any functions that we need to feature gate already? |
I think the most recent addition thta we use is napi_get_all_property_names, which was added in N-API 6 in early 2020. So not strictly necessary to gate, but it could be a way to ensure that it all works at least. Another more useful option could be the type tagging stuff that is not yet in a numbered N-API version, but is released in Node.js 12.x and 14.x. But that would probably best be done in a separate PR that also starts to make use of it in JsBox. |
@goto-bus-stop After thinking about it a bit more, I think your module suggestion is cleaner. Using attributes, would require making assumptions about those attributes--that they are specifically for conditional compiling--because they would need to be applied in three different places. Putting them in versioned modules is nice and simple. |
@@ -0,0 +1,80 @@ | |||
macro_rules! napi_name { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sample macro output:
#[cfg(not(windows))]
use libloading::os::unix::Library;
use std::os::raw::{c_char, c_void};
use super::types::*;
pub(crate) struct Napi {
get_undefined: unsafe extern "C" fn(env: Env, result: *mut Value) -> Status,
/* ... repeat for each N-API function */
}
pub(crate) unsafe fn load() -> Result<(), libloading::Error> {
let host = Library::this();
NAPI = Napi {
get_undefined: *host.get("napi_get_undefined".as_bytes())?,
/* ... repeat for each N-API function */
};
Ok(())
}
#[inline]
pub(crate) unsafe fn get_undefined(env: Env, result: *mut Value) -> Status {
(NAPI.get_undefined)(env, result)
}
fn panic_load<T>() -> T {
panic!("Must load N-API bindings")
}
static mut NAPI: Napi = {
unsafe extern "C" fn get_undefined(_: Env, _: *mut Value) -> Status {
panic_load()
}
/* ... repeat for each N-API function */
Napi {
get_undefined,
/* ... repeat for each N-API function */
}
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to add this as a comment to more clearly document the output of the macro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is so helpful. Can you put it into a comment directly in the source file, maybe with a few sentences explaining the overall approach?
@goto-bus-stop I think we can defer the conditional compiling to a different PR since it's not strictly necessary and we still need to iron out the ergonomics of the feature flags. What do you think? A quick sketch, I'm thinking something like: # neon/Cargo.toml
[features]
# Default N-API version
napi = ["napi6"]
napi6 = ["napi-runtime/napi6"]
napi7 = ["napi-runtime/napi7"]
napi-experimental = ["napi-runtime/napi-experimental"]
# neon-runtime/Cargo.toml
[features]
napi = ["libloading"]
napi6 = ["napi"]
napi7 = ["napi6"]
napi-experimental = ["napi7"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is too exciting. And I can't believe how much easier it was to understand than I expected. My only comments were really some suggestions for comments explaining things maintainers will want to know down the line.
crates/neon-runtime/Cargo.toml
Outdated
smallvec = "1.4.2" | ||
|
||
[dev-dependencies] | ||
nodejs-sys = "0.7.0" # Dev dependency for easy copying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe be even more explicit in the comment, like "Not strictly needed; just here for easy manual copying"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
pub unsafe extern "C" fn new(out: &mut Local, env: Env, length: u32) { | ||
assert_eq!( | ||
napi::napi_create_array_with_length(env, length as usize, out as *mut _), | ||
napi::napi_status::napi_ok, | ||
napi::create_array_with_length(env, length as usize, out as *mut _), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These naming conventions aren't, like, gonna change the world, but they're so nice 😎
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's not to love about repeating the word napi
3x in a single identifier? 😆 s/napi::napi_status::napi_ok/napi::Status::Ok/
napi, napi.... napi.
...napi
@@ -0,0 +1,80 @@ | |||
macro_rules! napi_name { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is so helpful. Can you put it into a comment directly in the source file, maybe with a few sentences explaining the overall approach?
@@ -0,0 +1,154 @@ | |||
use std::ffi::c_void; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this file should have a comment at the top explaining the manual process we use for extracting the type declarations from nodejs_sys and pasting them here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this to bindings/mod.rs
instead because the approach is identical in types.rs
and functions.rs
.
Yeah, if we are OK with the module approach then there is no need to figure the details out now 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
As described in #584 and tested in experimented with in #645.
Follow-ups:
neon-build
Closes #645