summaryrefslogtreecommitdiff
path: root/ext/napi/lib.rs
diff options
context:
space:
mode:
authorhaturau <135221985+haturatu@users.noreply.github.com>2024-11-20 01:20:47 +0900
committerGitHub <noreply@github.com>2024-11-20 01:20:47 +0900
commit85719a67e59c7aa45bead26e4942d7df8b1b42d4 (patch)
treeface0aecaac53e93ce2f23b53c48859bcf1a36ec /ext/napi/lib.rs
parent67697bc2e4a62a9670699fd18ad0dd8efc5bd955 (diff)
parent186b52731c6bb326c4d32905c5e732d082e83465 (diff)
Merge branch 'denoland:main' into main
Diffstat (limited to 'ext/napi/lib.rs')
-rw-r--r--ext/napi/lib.rs85
1 files changed, 67 insertions, 18 deletions
diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs
index 4500c66fd..88b8c238d 100644
--- a/ext/napi/lib.rs
+++ b/ext/napi/lib.rs
@@ -5,9 +5,23 @@
#![allow(clippy::undocumented_unsafe_blocks)]
#![deny(clippy::missing_safety_doc)]
+//! Symbols to be exported are now defined in this JSON file.
+//! The `#[napi_sym]` macro checks for missing entries and panics.
+//!
+//! `./tools/napi/generate_symbols_list.js` is used to generate the LINK `cli/exports.def` on Windows,
+//! which is also checked into git.
+//!
+//! To add a new napi function:
+//! 1. Place `#[napi_sym]` on top of your implementation.
+//! 2. Add the function's identifier to this JSON list.
+//! 3. Finally, run `tools/napi/generate_symbols_list.js` to update `ext/napi/generated_symbol_exports_list_*.def`.
+
+pub mod js_native_api;
+pub mod node_api;
+pub mod util;
+pub mod uv;
+
use core::ptr::NonNull;
-use deno_core::error::type_error;
-use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::parking_lot::RwLock;
use deno_core::url::Url;
@@ -20,6 +34,18 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::thread_local;
+#[derive(Debug, thiserror::Error)]
+pub enum NApiError {
+ #[error("Invalid path")]
+ InvalidPath,
+ #[error(transparent)]
+ LibLoading(#[from] libloading::Error),
+ #[error("Unable to find register Node-API module at {}", .0.display())]
+ ModuleNotFound(PathBuf),
+ #[error(transparent)]
+ Permission(#[from] PermissionCheckError),
+}
+
#[cfg(unix)]
use libloading::os::unix::*;
@@ -29,6 +55,7 @@ use libloading::os::windows::*;
// Expose common stuff for ease of use.
// `use deno_napi::*`
pub use deno_core::v8;
+use deno_permissions::PermissionCheckError;
pub use std::ffi::CStr;
pub use std::os::raw::c_char;
pub use std::os::raw::c_void;
@@ -482,14 +509,14 @@ deno_core::extension!(deno_napi,
pub trait NapiPermissions {
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
- fn check(&mut self, path: &str) -> std::result::Result<PathBuf, AnyError>;
+ fn check(&mut self, path: &str) -> Result<PathBuf, PermissionCheckError>;
}
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
// change in the future.
impl NapiPermissions for deno_permissions::PermissionsContainer {
#[inline(always)]
- fn check(&mut self, path: &str) -> Result<PathBuf, AnyError> {
+ fn check(&mut self, path: &str) -> Result<PathBuf, PermissionCheckError> {
deno_permissions::PermissionsContainer::check_ffi(self, path)
}
}
@@ -512,7 +539,7 @@ fn op_napi_open<NP, 'scope>(
global: v8::Local<'scope, v8::Object>,
buffer_constructor: v8::Local<'scope, v8::Function>,
report_error: v8::Local<'scope, v8::Function>,
-) -> std::result::Result<v8::Local<'scope, v8::Value>, AnyError>
+) -> Result<v8::Local<'scope, v8::Value>, NApiError>
where
NP: NapiPermissions + 'static,
{
@@ -540,7 +567,7 @@ where
let type_tag = v8::Global::new(scope, type_tag);
let url_filename =
- Url::from_file_path(&path).map_err(|_| type_error("Invalid path"))?;
+ Url::from_file_path(&path).map_err(|_| NApiError::InvalidPath)?;
let env_shared =
EnvShared::new(napi_wrap, type_tag, format!("{url_filename}\0"));
@@ -565,17 +592,11 @@ where
// SAFETY: opening a DLL calls dlopen
#[cfg(unix)]
- let library = match unsafe { Library::open(Some(&path), flags) } {
- Ok(lib) => lib,
- Err(e) => return Err(type_error(e.to_string())),
- };
+ let library = unsafe { Library::open(Some(&path), flags) }?;
// SAFETY: opening a DLL calls dlopen
#[cfg(not(unix))]
- let library = match unsafe { Library::load_with_flags(&path, flags) } {
- Ok(lib) => lib,
- Err(e) => return Err(type_error(e.to_string())),
- };
+ let library = unsafe { Library::load_with_flags(&path, flags) }?;
let maybe_module = MODULE_TO_REGISTER.with(|cell| {
let mut slot = cell.borrow_mut();
@@ -610,10 +631,7 @@ where
// SAFETY: we are going blind, calling the register function on the other side.
unsafe { init(env_ptr, exports.into()) }
} else {
- return Err(type_error(format!(
- "Unable to find register Node-API module at {}",
- path.display()
- )));
+ return Err(NApiError::ModuleNotFound(path));
};
let exports = maybe_exports.unwrap_or(exports.into());
@@ -624,3 +642,34 @@ where
Ok(exports)
}
+
+#[allow(clippy::print_stdout)]
+pub fn print_linker_flags(name: &str) {
+ let symbols_path =
+ include_str!(concat!(env!("OUT_DIR"), "/napi_symbol_path.txt"));
+
+ #[cfg(target_os = "windows")]
+ println!("cargo:rustc-link-arg-bin={name}=/DEF:{}", symbols_path);
+
+ #[cfg(target_os = "macos")]
+ println!(
+ "cargo:rustc-link-arg-bin={name}=-Wl,-exported_symbols_list,{}",
+ symbols_path,
+ );
+
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "freebsd",
+ target_os = "openbsd"
+ ))]
+ println!(
+ "cargo:rustc-link-arg-bin={name}=-Wl,--export-dynamic-symbol-list={}",
+ symbols_path,
+ );
+
+ #[cfg(target_os = "android")]
+ println!(
+ "cargo:rustc-link-arg-bin={name}=-Wl,--export-dynamic-symbol-list={}",
+ symbols_path,
+ );
+}