Skip to content

Commit

Permalink
feat(neon): RFC#44 Borrow API breaking changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kjvalencik committed Aug 30, 2021
1 parent f2e1960 commit d26eee0
Show file tree
Hide file tree
Showing 23 changed files with 1,134 additions and 197 deletions.
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[alias]
# Neon defines mutually exclusive feature flags which prevents using `cargo clippy --all-features`
# The following aliases simplify linting the entire workspace
check-napi = "check --all-targets --no-default-features -p neon -p neon-runtime -p neon-build -p neon-macros -p electron-tests -p napi-tests --features proc-macros,try-catch-api,napi-experimental"
check-legacy = "check --all-targets --no-default-features -p neon -p neon-runtime -p neon-build -p neon-macros -p tests -p static_tests --features event-handler-api,proc-macros,try-catch-api,legacy-runtime"
clippy-legacy = "clippy --all-targets --no-default-features -p neon -p neon-runtime -p neon-build -p neon-macros -p tests -p static_tests --features event-handler-api,proc-macros,try-catch-api,legacy-runtime -- -A clippy::missing_safety_doc"
clippy-napi = "clippy --all-targets --no-default-features -p neon -p neon-runtime -p neon-build -p neon-macros -p electron-tests -p napi-tests --features proc-macros,try-catch-api,napi-experimental -- -A clippy::missing_safety_doc"
neon-test = "test --no-default-features --features napi-experimental"
Expand Down
33 changes: 30 additions & 3 deletions crates/neon-runtime/src/napi/arraybuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ use crate::raw::{Env, Local};
use std::mem::MaybeUninit;
use std::os::raw::c_void;
use std::ptr::null_mut;
use std::slice;

use crate::napi::bindings as napi;

pub unsafe fn new(out: &mut Local, env: Env, size: u32) -> bool {
let status = napi::create_arraybuffer(env, size as usize, null_mut(), out as *mut _);
pub unsafe fn new(env: Env, len: usize) -> Result<Local, napi::Status> {
let mut buf = MaybeUninit::uninit();
let status = napi::create_arraybuffer(env, len, null_mut(), buf.as_mut_ptr());

status == napi::Status::Ok
if status == napi::Status::PendingException {
return Err(status);
}

assert_eq!(status, napi::Status::Ok);

Ok(buf.assume_init())
}

pub unsafe fn data(env: Env, base_out: &mut *mut c_void, obj: Local) -> usize {
Expand Down Expand Up @@ -48,3 +56,22 @@ where
unsafe extern "C" fn drop_external<T>(_env: Env, _data: *mut c_void, hint: *mut c_void) {
Box::<T>::from_raw(hint as *mut _);
}

/// # Safety
/// * Caller must ensure `env` and `buf` are valid
/// * The lifetime `'a` does not exceed the lifetime of `Env` or `buf`
pub unsafe fn as_mut_slice<'a>(env: Env, buf: Local) -> &'a mut [u8] {
let mut data = MaybeUninit::uninit();
let mut size = 0usize;

assert_eq!(
napi::get_arraybuffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _),
napi::Status::Ok,
);

if size == 0 {
return &mut [];
}

slice::from_raw_parts_mut(data.assume_init().cast(), size)
}
11 changes: 11 additions & 0 deletions crates/neon-runtime/src/napi/bindings/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ mod napi1 {
fn close_handle_scope(env: Env, scope: HandleScope) -> Status;

fn is_arraybuffer(env: Env, value: Value, result: *mut bool) -> Status;
fn is_typedarray(env: Env, value: Value, result: *mut bool) -> Status;
fn is_buffer(env: Env, value: Value, result: *mut bool) -> Status;
fn is_error(env: Env, value: Value, result: *mut bool) -> Status;
fn is_array(env: Env, value: Value, result: *mut bool) -> Status;
Expand Down Expand Up @@ -90,6 +91,16 @@ mod napi1 {
byte_length: *mut usize,
) -> Status;

fn get_typedarray_info(
env: Env,
typedarray: Value,
typ: *mut TypedArrayType,
length: *mut usize,
data: *mut *mut c_void,
buf: *mut Value,
offset: *mut usize,
) -> Status;

fn create_buffer(
env: Env,
length: usize,
Expand Down
1 change: 1 addition & 0 deletions crates/neon-runtime/src/napi/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ macro_rules! generate {
use std::sync::Once;

pub(crate) use functions::*;
pub use types::TypedArrayType;
pub(crate) use types::*;

mod functions;
Expand Down
17 changes: 17 additions & 0 deletions crates/neon-runtime/src/napi/bindings/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ pub(crate) enum ValueType {
BigInt = 9,
}

#[allow(dead_code)]
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TypedArrayType {
I8 = 0,
U8 = 1,
U8Clamped = 2,
I16 = 3,
U16 = 4,
I32 = 5,
U32 = 6,
F32 = 7,
F64 = 8,
I64 = 9,
U64 = 10,
}

#[allow(dead_code)]
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
Expand Down
54 changes: 38 additions & 16 deletions crates/neon-runtime/src/napi/buffer.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
use crate::raw::{Env, Local};
use std::mem::MaybeUninit;
use std::os::raw::c_void;
use std::ptr::null_mut;
use std::slice;

use crate::napi::bindings as napi;

pub unsafe fn new(env: Env, out: &mut Local, size: u32) -> bool {
let mut bytes = null_mut();
let status = napi::create_buffer(env, size as usize, &mut bytes as *mut _, out as *mut _);
if status == napi::Status::Ok {
// zero-initialize it. If performance is critical, JsBuffer::uninitialized can be used
// instead.
std::ptr::write_bytes(bytes, 0, size as usize);
true
} else {
false
}
pub unsafe fn new(env: Env, len: usize) -> Result<Local, napi::Status> {
let (buf, bytes) = uninitialized(env, len)?;

std::ptr::write_bytes(bytes, 0, len);

Ok(buf)
}

pub unsafe fn uninitialized(env: Env, out: &mut Local, size: u32) -> bool {
let mut bytes = null_mut();
let status = napi::create_buffer(env, size as usize, &mut bytes as *mut _, out as *mut _);
status == napi::Status::Ok
pub unsafe fn uninitialized(env: Env, len: usize) -> Result<(Local, *mut u8), napi::Status> {
let mut buf = MaybeUninit::uninit();
let mut bytes = MaybeUninit::uninit();
let status = napi::create_buffer(env, len, bytes.as_mut_ptr(), buf.as_mut_ptr());

if status == napi::Status::PendingException {
return Err(status);
}

assert_eq!(status, napi::Status::Ok);

Ok((buf.assume_init(), bytes.assume_init().cast()))
}

pub unsafe fn new_external<T>(env: Env, data: T) -> Local
Expand Down Expand Up @@ -61,3 +64,22 @@ pub unsafe fn data(env: Env, base_out: &mut *mut c_void, obj: Local) -> usize {
unsafe extern "C" fn drop_external<T>(_env: Env, _data: *mut c_void, hint: *mut c_void) {
Box::<T>::from_raw(hint as *mut _);
}

/// # Safety
/// * Caller must ensure `env` and `buf` are valid
/// * The lifetime `'a` does not exceed the lifetime of `Env` or `buf`
pub unsafe fn as_mut_slice<'a>(env: Env, buf: Local) -> &'a mut [u8] {
let mut data = MaybeUninit::uninit();
let mut size = 0usize;

assert_eq!(
napi::get_buffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _),
napi::Status::Ok,
);

if size == 0 {
return &mut [];
}

slice::from_raw_parts_mut(data.assume_init().cast(), size)
}
1 change: 1 addition & 0 deletions crates/neon-runtime/src/napi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod string;
pub mod tag;
#[cfg(feature = "napi-4")]
pub mod tsfn;
pub mod typedarray;

mod bindings;
pub use bindings::*;
10 changes: 10 additions & 0 deletions crates/neon-runtime/src/napi/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ pub unsafe fn is_arraybuffer(env: Env, val: Local) -> bool {
result
}

/// Is `val` a TypedArray instance?
pub unsafe fn is_typedarray(env: Env, val: Local) -> bool {
let mut result = false;
assert_eq!(
napi::is_typedarray(env, val, &mut result as *mut _),
napi::Status::Ok
);
result
}

#[cfg(feature = "napi-5")]
pub unsafe fn is_date(env: Env, val: Local) -> bool {
let mut result = false;
Expand Down
40 changes: 40 additions & 0 deletions crates/neon-runtime/src/napi/typedarray.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::ffi::c_void;
use std::mem::MaybeUninit;

use crate::napi::bindings::{self as napi, TypedArrayType};
use crate::raw::{Env, Local};

#[derive(Debug)]
/// Information describing a JavaScript [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray)
pub struct TypedArrayInfo {
pub typ: TypedArrayType,
pub length: usize,
pub data: *mut c_void,
pub buf: Local,
pub offset: usize,
}

/// Get [information](TypedArrayInfo) describing a JavaScript `TypedArray`
///
/// # Safety
/// * `env` must be valid `napi_env` for the current scope
/// * `value` must be a handle pointing to a `TypedArray`
pub unsafe fn info(env: Env, value: Local) -> TypedArrayInfo {
let mut info = MaybeUninit::<TypedArrayInfo>::zeroed();
let ptr = info.as_mut_ptr();

assert_eq!(
napi::get_typedarray_info(
env,
value,
&mut (*ptr).typ,
&mut (*ptr).length,
&mut (*ptr).data,
&mut (*ptr).buf,
&mut (*ptr).offset,
),
napi::Status::Ok,
);

info.assume_init()
}
Loading

0 comments on commit d26eee0

Please sign in to comment.