commit
58977c89d2
9 changed files with 151 additions and 83 deletions
27
.cirrus.yml
Normal file
27
.cirrus.yml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
freebsd_instance:
|
||||||
|
image: freebsd-12-1-release-amd64
|
||||||
|
|
||||||
|
task:
|
||||||
|
name: FreeBSD 12.1
|
||||||
|
env:
|
||||||
|
DEBUG: 'napi:*'
|
||||||
|
setup_script:
|
||||||
|
- pkg update
|
||||||
|
- pkg install -y -f curl node yarn npm libnghttp2 llvm
|
||||||
|
- curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||||
|
- sh rustup.sh -y --profile minimal --default-toolchain stable
|
||||||
|
- . $HOME/.cargo/env
|
||||||
|
- |
|
||||||
|
echo "~~~~ rustc --version ~~~~"
|
||||||
|
rustc --version
|
||||||
|
echo "~~~~ node -v ~~~~"
|
||||||
|
node -v
|
||||||
|
echo "~~~~ yarn --version ~~~~"
|
||||||
|
yarn --version
|
||||||
|
test_script:
|
||||||
|
- . $HOME/.cargo/env
|
||||||
|
- yarn install --ignore-platform --frozen-lockfile --registry https://registry.npmjs.org
|
||||||
|
- yarn build
|
||||||
|
- cargo test -p napi-sys --lib -- --nocapture
|
||||||
|
- yarn build:test
|
||||||
|
- yarn test
|
|
@ -5,6 +5,7 @@ parserOptions:
|
||||||
jsx: true
|
jsx: true
|
||||||
ecmaVersion: 2020
|
ecmaVersion: 2020
|
||||||
sourceType: module
|
sourceType: module
|
||||||
|
extraFileExtensions: ['.cjs']
|
||||||
project: ./tsconfig.json
|
project: ./tsconfig.json
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
@ -220,3 +221,10 @@ overrides:
|
||||||
- '@typescript-eslint'
|
- '@typescript-eslint'
|
||||||
parserOptions:
|
parserOptions:
|
||||||
project: ./bench/tsconfig.json
|
project: ./bench/tsconfig.json
|
||||||
|
|
||||||
|
- files:
|
||||||
|
- ./*.{cjs,js}
|
||||||
|
plugins:
|
||||||
|
- '@typescript-eslint'
|
||||||
|
parserOptions:
|
||||||
|
project: ./tsconfig.root-lint.json
|
||||||
|
|
5
.github/workflows/napi3.yaml
vendored
5
.github/workflows/napi3.yaml
vendored
|
@ -73,6 +73,11 @@ jobs:
|
||||||
command: test
|
command: test
|
||||||
args: -p napi-sys --lib -- --nocapture
|
args: -p napi-sys --lib -- --nocapture
|
||||||
|
|
||||||
|
- name: Write ava.config.js for ava@2
|
||||||
|
run: |
|
||||||
|
node write-ava-config.js
|
||||||
|
cat ava.config.js
|
||||||
|
|
||||||
- name: Unit tests
|
- name: Unit tests
|
||||||
run: |
|
run: |
|
||||||
yarn --cwd ./test_module --ignore-engines build
|
yarn --cwd ./test_module --ignore-engines build
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
const configuration = {
|
const configuration = {
|
||||||
extensions: ['ts', 'tsx'],
|
extensions: ['ts', 'tsx'],
|
||||||
files: ['test_module/__test__/**/*.spec.ts'],
|
files: ['test_module/__test__/**/*.spec.ts'],
|
||||||
require: ['@swc-node/register'],
|
require: [
|
||||||
|
require('os').platform() === 'freebsd'
|
||||||
|
? 'ts-node/register/transpile-only'
|
||||||
|
: '@swc-node/register',
|
||||||
|
],
|
||||||
environmentVariables: {
|
environmentVariables: {
|
||||||
SWC_NODE_PROJECT: './test_module/tsconfig.json',
|
TS_NODE_PROJECT: './test_module/tsconfig.json',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,4 +15,4 @@ if (parseInt(process.versions.napi, 10) < 4) {
|
||||||
configuration.compileEnhancements = false
|
configuration.compileEnhancements = false
|
||||||
}
|
}
|
||||||
|
|
||||||
export default configuration
|
module.exports = configuration
|
145
napi/src/lib.rs
145
napi/src/lib.rs
|
@ -16,16 +16,16 @@
|
||||||
//!
|
//!
|
||||||
//! #[js_function(1)]
|
//! #[js_function(1)]
|
||||||
//! pub fn uv_read_file(ctx: CallContext) -> Result<JsObject> {
|
//! pub fn uv_read_file(ctx: CallContext) -> Result<JsObject> {
|
||||||
//! let path = ctx.get::<JsString>(0)?;
|
//! let path = ctx.get::<JsString>(0)?;
|
||||||
//! let (sender, receiver) = oneshot::channel();
|
//! let (sender, receiver) = oneshot::channel();
|
||||||
//! let p = path.as_str()?.to_owned();
|
//! let p = path.as_str()?.to_owned();
|
||||||
//! thread::spawn(|| {
|
//! thread::spawn(|| {
|
||||||
//! let res = fs::read(p).map_err(|e| Error::new(Status::Unknown, format!("{}", e)));
|
//! let res = fs::read(p).map_err(|e| Error::new(Status::Unknown, format!("{}", e)));
|
||||||
//! sender.send(res).expect("Send data failed");
|
//! sender.send(res).expect("Send data failed");
|
||||||
//! });
|
//! });
|
||||||
//! ctx.env.execute(receiver.map_err(|e| Error::new(Status::Unknown, format!("{}", e))).map(|x| x.and_then(|x| x)), |&mut env, data| {
|
//! ctx.env.execute(receiver.map_err(|e| Error::new(Status::Unknown, format!("{}", e))).map(|x| x.and_then(|x| x)), |&mut env, data| {
|
||||||
//! env.create_buffer_with_data(data)
|
//! env.create_buffer_with_data(data)
|
||||||
//! })
|
//! })
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//! ### tokio_rt
|
//! ### tokio_rt
|
||||||
|
@ -39,13 +39,13 @@
|
||||||
//!
|
//!
|
||||||
//! #[js_function(1)]
|
//! #[js_function(1)]
|
||||||
//! pub fn tokio_readfile(ctx: CallContext) -> Result<JsObject> {
|
//! pub fn tokio_readfile(ctx: CallContext) -> Result<JsObject> {
|
||||||
//! let js_filepath = ctx.get::<JsString>(0)?;
|
//! let js_filepath = ctx.get::<JsString>(0)?;
|
||||||
//! let path_str = js_filepath.as_str()?;
|
//! let path_str = js_filepath.as_str()?;
|
||||||
//! ctx.env.execute_tokio_future(
|
//! ctx.env.execute_tokio_future(
|
||||||
//! tokio::fs::read(path_str.to_owned())
|
//! tokio::fs::read(path_str.to_owned())
|
||||||
//! .map(|v| v.map_err(|e| Error::new(Status::Unknown, format!("failed to read file, {}", e)))),
|
//! .map(|v| v.map_err(|e| Error::new(Status::Unknown, format!("failed to read file, {}", e)))),
|
||||||
//! |&mut env, data| env.create_buffer_with_data(data),
|
//! |&mut env, data| env.create_buffer_with_data(data),
|
||||||
//! )
|
//! )
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -70,22 +70,22 @@
|
||||||
//! ```
|
//! ```
|
||||||
//! #[derive(Serialize, Debug, Deserialize)]
|
//! #[derive(Serialize, Debug, Deserialize)]
|
||||||
//! struct AnObject {
|
//! struct AnObject {
|
||||||
//! a: u32,
|
//! a: u32,
|
||||||
//! b: Vec<f64>,
|
//! b: Vec<f64>,
|
||||||
//! c: String,
|
//! c: String,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! #[js_function(1)]
|
//! #[js_function(1)]
|
||||||
//! fn deserialize_from_js(ctx: CallContext) -> Result<JsUndefined> {
|
//! fn deserialize_from_js(ctx: CallContext) -> Result<JsUndefined> {
|
||||||
//! let arg0 = ctx.get::<JsUnknown>(0)?;
|
//! let arg0 = ctx.get::<JsUnknown>(0)?;
|
||||||
//! let de_serialized: AnObject = ctx.env.from_js_value(arg0)?;
|
//! let de_serialized: AnObject = ctx.env.from_js_value(arg0)?;
|
||||||
//! ...
|
//! ...
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! #[js_function]
|
//! #[js_function]
|
||||||
//! fn serialize(ctx: CallContext) -> Result<JsUnknown> {
|
//! fn serialize(ctx: CallContext) -> Result<JsUnknown> {
|
||||||
//! let value = AnyObject { a: 1, b: vec![0.1, 2.22], c: "hello" };
|
//! let value = AnyObject { a: 1, b: vec![0.1, 2.22], c: "hello" };
|
||||||
//! ctx.env.to_js_value(&value)
|
//! ctx.env.to_js_value(&value)
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -138,7 +138,7 @@ pub type ContextlessResult<T> = Result<Option<T>>;
|
||||||
/// register_module!(test_module, init);
|
/// register_module!(test_module, init);
|
||||||
///
|
///
|
||||||
/// fn init(module: &mut Module) -> Result<()> {
|
/// fn init(module: &mut Module) -> Result<()> {
|
||||||
/// module.create_named_method("nativeFunction", native_function)?;
|
/// module.create_named_method("nativeFunction", native_function)?;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -154,11 +154,8 @@ macro_rules! register_module {
|
||||||
_ => Err(Error::from_status(status)),
|
_ => Err(Error::from_status(status)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[no_mangle]
|
|
||||||
#[cfg_attr(target_os = "linux", link_section = ".ctors")]
|
extern "C" fn register_module() {
|
||||||
#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
|
|
||||||
#[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
|
|
||||||
pub static __REGISTER_MODULE: extern "C" fn() = {
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
@ -167,58 +164,54 @@ macro_rules! register_module {
|
||||||
|
|
||||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||||
use $crate::shutdown_tokio_rt;
|
use $crate::shutdown_tokio_rt;
|
||||||
|
static mut MODULE_DESCRIPTOR: Option<sys::napi_module> = None;
|
||||||
|
unsafe {
|
||||||
|
MODULE_DESCRIPTOR = Some(sys::napi_module {
|
||||||
|
nm_version: 1,
|
||||||
|
nm_flags: 0,
|
||||||
|
nm_filename: concat!(file!(), "\0").as_ptr() as *const c_char,
|
||||||
|
nm_register_func: Some(napi_register_module_v1),
|
||||||
|
nm_modname: concat!(stringify!($module_name), "\0").as_ptr() as *const c_char,
|
||||||
|
nm_priv: 0 as *mut _,
|
||||||
|
reserved: [0 as *mut _; 4],
|
||||||
|
});
|
||||||
|
|
||||||
extern "C" fn register_module() {
|
sys::napi_module_register(MODULE_DESCRIPTOR.as_mut().unwrap() as *mut sys::napi_module);
|
||||||
static mut MODULE_DESCRIPTOR: Option<sys::napi_module> = None;
|
}
|
||||||
unsafe {
|
|
||||||
MODULE_DESCRIPTOR = Some(sys::napi_module {
|
|
||||||
nm_version: 1,
|
|
||||||
nm_flags: 0,
|
|
||||||
nm_filename: concat!(file!(), "\0").as_ptr() as *const c_char,
|
|
||||||
nm_register_func: Some(init_module),
|
|
||||||
nm_modname: concat!(stringify!($module_name), "\0").as_ptr() as *const c_char,
|
|
||||||
nm_priv: 0 as *mut _,
|
|
||||||
reserved: [0 as *mut _; 4],
|
|
||||||
});
|
|
||||||
|
|
||||||
sys::napi_module_register(MODULE_DESCRIPTOR.as_mut().unwrap() as *mut sys::napi_module);
|
#[no_mangle]
|
||||||
}
|
pub unsafe extern "C" fn napi_register_module_v1(
|
||||||
|
raw_env: sys::napi_env,
|
||||||
|
raw_exports: sys::napi_value,
|
||||||
|
) -> sys::napi_value {
|
||||||
|
let env = Env::from_raw(raw_env);
|
||||||
|
let mut exports: JsObject = JsObject::from_raw_unchecked(raw_env, raw_exports);
|
||||||
|
let mut cjs_module = Module { env, exports };
|
||||||
|
let result = $init(&mut cjs_module);
|
||||||
|
|
||||||
extern "C" fn init_module(
|
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||||
raw_env: sys::napi_env,
|
let hook_result = check_status(unsafe {
|
||||||
raw_exports: sys::napi_value,
|
sys::napi_add_env_cleanup_hook(raw_env, Some(shutdown_tokio_rt), ptr::null_mut())
|
||||||
) -> sys::napi_value {
|
});
|
||||||
let env = Env::from_raw(raw_env);
|
|
||||||
let mut exports: JsObject = JsObject::from_raw_unchecked(raw_env, raw_exports);
|
|
||||||
let mut cjs_module = Module { env, exports };
|
|
||||||
let result = $init(&mut cjs_module);
|
|
||||||
|
|
||||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
#[cfg(not(all(feature = "tokio_rt", napi4)))]
|
||||||
let hook_result = check_status(unsafe {
|
let hook_result = Ok(());
|
||||||
sys::napi_add_env_cleanup_hook(raw_env, Some(shutdown_tokio_rt), ptr::null_mut())
|
|
||||||
});
|
|
||||||
|
|
||||||
#[cfg(not(all(feature = "tokio_rt", napi4)))]
|
match hook_result.and_then(move |_| result) {
|
||||||
let hook_result = Ok(());
|
Ok(_) => cjs_module.exports.raw(),
|
||||||
|
Err(e) => {
|
||||||
match hook_result.and_then(move |_| result) {
|
unsafe {
|
||||||
Ok(_) => cjs_module.exports.raw(),
|
sys::napi_throw_error(
|
||||||
Err(e) => {
|
raw_env,
|
||||||
unsafe {
|
ptr::null(),
|
||||||
sys::napi_throw_error(
|
CString::from_vec_unchecked(format!("Error initializing module: {}", e).into())
|
||||||
raw_env,
|
.as_ptr() as *const _,
|
||||||
ptr::null(),
|
)
|
||||||
CString::from_vec_unchecked(format!("Error initializing module: {}", e).into())
|
};
|
||||||
.as_ptr() as *const _,
|
ptr::null_mut()
|
||||||
)
|
|
||||||
};
|
|
||||||
ptr::null_mut()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
register_module
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ export class BuildCommand extends Command {
|
||||||
libExt = '.dll'
|
libExt = '.dll'
|
||||||
break
|
break
|
||||||
case 'linux':
|
case 'linux':
|
||||||
|
case 'freebsd':
|
||||||
dylibName = `lib${dylibName}`
|
dylibName = `lib${dylibName}`
|
||||||
libExt = '.so'
|
libExt = '.so'
|
||||||
break
|
break
|
||||||
|
|
24
sys/build.rs
24
sys/build.rs
|
@ -28,21 +28,37 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if node_major_version < 10 {
|
if node_major_version < 8 && node_version.minor < 9 {
|
||||||
panic!("node version is too low")
|
panic!("node version is too low")
|
||||||
}
|
}
|
||||||
|
|
||||||
let node_include_path = find_node_include_path(node_full_version.trim_end());
|
let node_include_path_buf = find_node_include_path(node_full_version.trim_end());
|
||||||
|
|
||||||
|
let node_include_path = match env::var("NODE_INCLUDE_PATH") {
|
||||||
|
Ok(node_include_path) => node_include_path,
|
||||||
|
Err(_) => node_include_path_buf.to_str().unwrap().to_owned(),
|
||||||
|
};
|
||||||
|
|
||||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
|
||||||
let mut sys_bindings_path = PathBuf::from("src");
|
let mut sys_bindings_path = PathBuf::from("src");
|
||||||
sys_bindings_path.push("bindings.h");
|
sys_bindings_path.push("bindings.h");
|
||||||
|
|
||||||
bindgen::Builder::default()
|
let mut bindgen_builder = bindgen::Builder::default()
|
||||||
.derive_default(true)
|
.derive_default(true)
|
||||||
.header(sys_bindings_path.to_str().unwrap().to_owned())
|
.header(sys_bindings_path.to_str().unwrap().to_owned())
|
||||||
.clang_arg(String::from("-I") + node_include_path.to_str().unwrap())
|
.clang_arg(format!("-I{}", node_include_path));
|
||||||
|
|
||||||
|
if let Ok(uv_include_path) = env::var("UV_INCLUDE_PATH") {
|
||||||
|
bindgen_builder = bindgen_builder.clang_arg(format!("-I{}", uv_include_path));
|
||||||
|
} else if cfg!(target_os = "freebsd") {
|
||||||
|
bindgen_builder = bindgen_builder.clang_arg(format!(
|
||||||
|
"-I{}",
|
||||||
|
node_include_path_buf.parent().unwrap().to_str().unwrap()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
bindgen_builder
|
||||||
.rustified_enum("(napi_|uv_).+")
|
.rustified_enum("(napi_|uv_).+")
|
||||||
.whitelist_function("(napi_|uv_|extras_).+")
|
.whitelist_function("(napi_|uv_|extras_).+")
|
||||||
.whitelist_type("(napi_|uv_|extras_).+")
|
.whitelist_type("(napi_|uv_|extras_).+")
|
||||||
|
|
4
tsconfig.root-lint.json
Normal file
4
tsconfig.root-lint.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"files": ["./ava.config.cjs", "./write-ava-config.js"]
|
||||||
|
}
|
10
write-ava-config.js
Normal file
10
write-ava-config.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
const { writeFileSync } = require('fs')
|
||||||
|
const { join } = require('path')
|
||||||
|
|
||||||
|
const config = require('./ava.config.cjs')
|
||||||
|
|
||||||
|
const code = `
|
||||||
|
export default ${JSON.stringify(config, null, 2)}
|
||||||
|
`
|
||||||
|
|
||||||
|
writeFileSync(join(__dirname, 'ava.config.js'), code)
|
Loading…
Add table
Reference in a new issue