mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
This reverts commit d00fbd7025
.
Reverting because, it caused a failure during v1.45.3 publish:
https://github.com/denoland/deno/actions/runs/10048730693/job/27773718095
This commit is contained in:
parent
715675565a
commit
3f8efe5289
22 changed files with 165 additions and 164 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1164,6 +1164,7 @@ dependencies = [
|
||||||
"lsp-types",
|
"lsp-types",
|
||||||
"memmem",
|
"memmem",
|
||||||
"monch",
|
"monch",
|
||||||
|
"napi_sym",
|
||||||
"nix 0.26.2",
|
"nix 0.26.2",
|
||||||
"notify",
|
"notify",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -1687,10 +1688,7 @@ version = "0.91.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_permissions",
|
"deno_permissions",
|
||||||
"libc",
|
|
||||||
"libloading 0.7.4",
|
"libloading 0.7.4",
|
||||||
"log",
|
|
||||||
"napi_sym",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -5,6 +5,7 @@ resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"bench_util",
|
"bench_util",
|
||||||
"cli",
|
"cli",
|
||||||
|
"cli/napi/sym",
|
||||||
"ext/broadcast_channel",
|
"ext/broadcast_channel",
|
||||||
"ext/cache",
|
"ext/cache",
|
||||||
"ext/canvas",
|
"ext/canvas",
|
||||||
|
@ -18,7 +19,6 @@ members = [
|
||||||
"ext/io",
|
"ext/io",
|
||||||
"ext/kv",
|
"ext/kv",
|
||||||
"ext/napi",
|
"ext/napi",
|
||||||
"ext/napi/sym",
|
|
||||||
"ext/net",
|
"ext/net",
|
||||||
"ext/node",
|
"ext/node",
|
||||||
"ext/url",
|
"ext/url",
|
||||||
|
@ -52,7 +52,7 @@ deno_media_type = { version = "0.1.4", features = ["module_specifier"] }
|
||||||
deno_permissions = { version = "0.21.0", path = "./runtime/permissions" }
|
deno_permissions = { version = "0.21.0", path = "./runtime/permissions" }
|
||||||
deno_runtime = { version = "0.169.0", path = "./runtime" }
|
deno_runtime = { version = "0.169.0", path = "./runtime" }
|
||||||
deno_terminal = "0.2.0"
|
deno_terminal = "0.2.0"
|
||||||
napi_sym = { version = "0.91.0", path = "./ext/napi/sym" }
|
napi_sym = { version = "0.91.0", path = "./cli/napi/sym" }
|
||||||
test_util = { package = "test_server", path = "./tests/util/server" }
|
test_util = { package = "test_server", path = "./tests/util/server" }
|
||||||
|
|
||||||
denokv_proto = "0.8.1"
|
denokv_proto = "0.8.1"
|
||||||
|
|
|
@ -78,6 +78,7 @@ deno_semver = "=0.5.7"
|
||||||
deno_task_shell = "=0.17.0"
|
deno_task_shell = "=0.17.0"
|
||||||
deno_terminal.workspace = true
|
deno_terminal.workspace = true
|
||||||
eszip = "=0.72.2"
|
eszip = "=0.72.2"
|
||||||
|
napi_sym.workspace = true
|
||||||
|
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
base32.workspace = true
|
base32.workspace = true
|
||||||
|
|
|
@ -396,7 +396,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
os => format!("generated_symbol_exports_list_{}.def", os),
|
os => format!("generated_symbol_exports_list_{}.def", os),
|
||||||
};
|
};
|
||||||
let symbols_path = std::path::Path::new("../ext/napi")
|
let symbols_path = std::path::Path::new("napi")
|
||||||
.join(symbols_file_name)
|
.join(symbols_file_name)
|
||||||
.canonicalize()
|
.canonicalize()
|
||||||
.expect(
|
.expect(
|
||||||
|
|
|
@ -15,6 +15,7 @@ mod js;
|
||||||
mod jsr;
|
mod jsr;
|
||||||
mod lsp;
|
mod lsp;
|
||||||
mod module_loader;
|
mod module_loader;
|
||||||
|
mod napi;
|
||||||
mod node;
|
mod node;
|
||||||
mod npm;
|
mod npm;
|
||||||
mod ops;
|
mod ops;
|
||||||
|
|
|
@ -15,6 +15,7 @@ mod errors;
|
||||||
mod file_fetcher;
|
mod file_fetcher;
|
||||||
mod http_util;
|
mod http_util;
|
||||||
mod js;
|
mod js;
|
||||||
|
mod napi;
|
||||||
mod node;
|
mod node;
|
||||||
mod npm;
|
mod npm;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
|
|
114
cli/napi/README.md
Normal file
114
cli/napi/README.md
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
# napi
|
||||||
|
|
||||||
|
This directory contains source for Deno's Node-API implementation. It depends on
|
||||||
|
`napi_sym` and `deno_napi`.
|
||||||
|
|
||||||
|
Files are generally organized the same as in Node.js's implementation to ease in
|
||||||
|
ensuring compatibility.
|
||||||
|
|
||||||
|
## Adding a new function
|
||||||
|
|
||||||
|
Add the symbol name to
|
||||||
|
[`cli/napi_sym/symbol_exports.json`](../napi_sym/symbol_exports.json).
|
||||||
|
|
||||||
|
```diff
|
||||||
|
{
|
||||||
|
"symbols": [
|
||||||
|
...
|
||||||
|
"napi_get_undefined",
|
||||||
|
- "napi_get_null"
|
||||||
|
+ "napi_get_null",
|
||||||
|
+ "napi_get_boolean"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Determine where to place the implementation. `napi_get_boolean` is related to JS
|
||||||
|
values so we will place it in `js_native_api.rs`. If something is not clear,
|
||||||
|
just create a new file module.
|
||||||
|
|
||||||
|
See [`napi_sym`](../napi_sym/) for writing the implementation:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[napi_sym::napi_sym]
|
||||||
|
pub fn napi_get_boolean(
|
||||||
|
env: *mut Env,
|
||||||
|
value: bool,
|
||||||
|
result: *mut napi_value,
|
||||||
|
) -> Result {
|
||||||
|
// ...
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Update the generated symbol lists using the script:
|
||||||
|
|
||||||
|
```
|
||||||
|
deno run --allow-write tools/napi/generate_symbols_lists.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a test in [`/tests/napi`](../../tests/napi/). You can also refer to Node.js
|
||||||
|
test suite for Node-API.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// tests/napi/boolean_test.js
|
||||||
|
import { assertEquals, loadTestLibrary } from "./common.js";
|
||||||
|
const lib = loadTestLibrary();
|
||||||
|
Deno.test("napi get boolean", function () {
|
||||||
|
assertEquals(lib.test_get_boolean(true), true);
|
||||||
|
assertEquals(lib.test_get_boolean(false), false);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// tests/napi/src/boolean.rs
|
||||||
|
|
||||||
|
use napi_sys::Status::napi_ok;
|
||||||
|
use napi_sys::ValueType::napi_boolean;
|
||||||
|
use napi_sys::*;
|
||||||
|
|
||||||
|
extern "C" fn test_boolean(
|
||||||
|
env: napi_env,
|
||||||
|
info: napi_callback_info,
|
||||||
|
) -> napi_value {
|
||||||
|
let (args, argc, _) = crate::get_callback_info!(env, info, 1);
|
||||||
|
assert_eq!(argc, 1);
|
||||||
|
|
||||||
|
let mut ty = -1;
|
||||||
|
assert!(unsafe { napi_typeof(env, args[0], &mut ty) } == napi_ok);
|
||||||
|
assert_eq!(ty, napi_boolean);
|
||||||
|
|
||||||
|
// Use napi_get_boolean here...
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(env: napi_env, exports: napi_value) {
|
||||||
|
let properties = &[crate::new_property!(env, "test_boolean\0", test_boolean)];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
napi_define_properties(env, exports, properties.len(), properties.as_ptr())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
// tests/napi/src/lib.rs
|
||||||
|
|
||||||
|
+ mod boolean;
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn napi_register_module_v1(
|
||||||
|
env: napi_env,
|
||||||
|
exports: napi_value,
|
||||||
|
) -> napi_value {
|
||||||
|
...
|
||||||
|
+ boolean::init(env, exports);
|
||||||
|
|
||||||
|
exports
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the test using `cargo test -p tests/napi`.
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
const NAPI_VERSION: u32 = 9;
|
const NAPI_VERSION: u32 = 9;
|
||||||
|
|
||||||
use crate::*;
|
use deno_runtime::deno_napi::*;
|
||||||
use libc::INT_MAX;
|
use libc::INT_MAX;
|
||||||
|
|
||||||
use super::util::check_new_from_utf8;
|
use super::util::check_new_from_utf8;
|
||||||
|
@ -17,9 +17,9 @@ use super::util::napi_set_last_error;
|
||||||
use super::util::v8_name_from_property_descriptor;
|
use super::util::v8_name_from_property_descriptor;
|
||||||
use crate::check_arg;
|
use crate::check_arg;
|
||||||
use crate::check_env;
|
use crate::check_env;
|
||||||
use crate::function::create_function;
|
use deno_runtime::deno_napi::function::create_function;
|
||||||
use crate::function::create_function_template;
|
use deno_runtime::deno_napi::function::create_function_template;
|
||||||
use crate::function::CallbackInfo;
|
use deno_runtime::deno_napi::function::CallbackInfo;
|
||||||
use napi_sym::napi_sym;
|
use napi_sym::napi_sym;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
@ -1644,7 +1644,7 @@ fn napi_get_cb_info(
|
||||||
check_arg!(env, argc);
|
check_arg!(env, argc);
|
||||||
let argc = unsafe { *argc as usize };
|
let argc = unsafe { *argc as usize };
|
||||||
for i in 0..argc {
|
for i in 0..argc {
|
||||||
let arg = args.get(i as _);
|
let mut arg = args.get(i as _);
|
||||||
unsafe {
|
unsafe {
|
||||||
*argv.add(i) = arg.into();
|
*argv.add(i) = arg.into();
|
||||||
}
|
}
|
20
cli/napi/mod.rs
Normal file
20
cli/napi/mod.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
#![allow(unused_mut)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||||
|
|
||||||
|
//! 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 `cli/napi/generated_symbol_exports_list_*.def`.
|
||||||
|
|
||||||
|
pub mod js_native_api;
|
||||||
|
pub mod node_api;
|
||||||
|
pub mod util;
|
|
@ -9,10 +9,10 @@ use super::util::napi_set_last_error;
|
||||||
use super::util::SendPtr;
|
use super::util::SendPtr;
|
||||||
use crate::check_arg;
|
use crate::check_arg;
|
||||||
use crate::check_env;
|
use crate::check_env;
|
||||||
use crate::*;
|
|
||||||
use deno_core::parking_lot::Condvar;
|
use deno_core::parking_lot::Condvar;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::V8CrossThreadTaskSpawner;
|
use deno_core::V8CrossThreadTaskSpawner;
|
||||||
|
use deno_runtime::deno_napi::*;
|
||||||
use napi_sym::napi_sym;
|
use napi_sym::napi_sym;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::atomic::AtomicU8;
|
use std::sync::atomic::AtomicU8;
|
||||||
|
@ -892,7 +892,7 @@ fn napi_create_threadsafe_function(
|
||||||
};
|
};
|
||||||
let resource_name = resource_name.to_rust_string_lossy(&mut env.scope());
|
let resource_name = resource_name.to_rust_string_lossy(&mut env.scope());
|
||||||
|
|
||||||
let tsfn = Box::new(TsFn {
|
let mut tsfn = Box::new(TsFn {
|
||||||
env,
|
env,
|
||||||
func,
|
func,
|
||||||
max_queue_size,
|
max_queue_size,
|
|
@ -20,7 +20,7 @@ pub fn napi_sym(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let name = &func.sig.ident;
|
let name = &func.sig.ident;
|
||||||
assert!(
|
assert!(
|
||||||
exports.symbols.contains(&name.to_string()),
|
exports.symbols.contains(&name.to_string()),
|
||||||
"ext/napi/sym/symbol_exports.json is out of sync!"
|
"cli/napi/sym/symbol_exports.json is out of sync!"
|
||||||
);
|
);
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
|
@ -1,13 +1,13 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
use crate::*;
|
use deno_runtime::deno_napi::*;
|
||||||
use libc::INT_MAX;
|
use libc::INT_MAX;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub(crate) struct SendPtr<T>(pub(crate) *const T);
|
pub struct SendPtr<T>(pub *const T);
|
||||||
|
|
||||||
impl<T> SendPtr<T> {
|
impl<T> SendPtr<T> {
|
||||||
// silly function to get around `clippy::redundant_locals`
|
// silly function to get around `clippy::redundant_locals`
|
||||||
pub(crate) fn take(self) -> *const T {
|
pub fn take(self) -> *const T {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,7 @@ impl<T> SendPtr<T> {
|
||||||
unsafe impl<T> Send for SendPtr<T> {}
|
unsafe impl<T> Send for SendPtr<T> {}
|
||||||
unsafe impl<T> Sync for SendPtr<T> {}
|
unsafe impl<T> Sync for SendPtr<T> {}
|
||||||
|
|
||||||
pub(crate) fn get_array_buffer_ptr(
|
pub fn get_array_buffer_ptr(ab: v8::Local<v8::ArrayBuffer>) -> *mut c_void {
|
||||||
ab: v8::Local<v8::ArrayBuffer>,
|
|
||||||
) -> *mut c_void {
|
|
||||||
match ab.data() {
|
match ab.data() {
|
||||||
Some(p) => p.as_ptr(),
|
Some(p) => p.as_ptr(),
|
||||||
None => std::ptr::null_mut(),
|
None => std::ptr::null_mut(),
|
||||||
|
@ -39,7 +37,7 @@ impl Drop for BufferFinalizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) extern "C" fn backing_store_deleter_callback(
|
pub extern "C" fn backing_store_deleter_callback(
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
_byte_length: usize,
|
_byte_length: usize,
|
||||||
deleter_data: *mut c_void,
|
deleter_data: *mut c_void,
|
||||||
|
@ -52,7 +50,7 @@ pub(crate) extern "C" fn backing_store_deleter_callback(
|
||||||
drop(finalizer);
|
drop(finalizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn make_external_backing_store(
|
pub fn make_external_backing_store(
|
||||||
env: *mut Env,
|
env: *mut Env,
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
byte_length: usize,
|
byte_length: usize,
|
||||||
|
@ -92,7 +90,9 @@ macro_rules! check_env {
|
||||||
macro_rules! return_error_status_if_false {
|
macro_rules! return_error_status_if_false {
|
||||||
($env: expr, $condition: expr, $status: ident) => {
|
($env: expr, $condition: expr, $status: ident) => {
|
||||||
if !$condition {
|
if !$condition {
|
||||||
return Err($crate::util::napi_set_last_error($env, $status).into());
|
return Err(
|
||||||
|
$crate::napi::util::napi_set_last_error($env, $status).into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ macro_rules! return_error_status_if_false {
|
||||||
macro_rules! return_status_if_false {
|
macro_rules! return_status_if_false {
|
||||||
($env: expr, $condition: expr, $status: ident) => {
|
($env: expr, $condition: expr, $status: ident) => {
|
||||||
if !$condition {
|
if !$condition {
|
||||||
return $crate::util::napi_set_last_error($env, $status);
|
return $crate::napi::util::napi_set_last_error($env, $status);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ macro_rules! check_arg {
|
||||||
($env: expr, $ptr: expr) => {
|
($env: expr, $ptr: expr) => {
|
||||||
$crate::return_status_if_false!(
|
$crate::return_status_if_false!(
|
||||||
$env,
|
$env,
|
||||||
!$crate::util::Nullable::is_null(&$ptr),
|
!$crate::napi::util::Nullable::is_null(&$ptr),
|
||||||
napi_invalid_arg
|
napi_invalid_arg
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -233,7 +233,6 @@ macro_rules! napi_wrap {
|
||||||
( $( # $attr:tt )* fn $name:ident $( < $( $x:lifetime ),* > )? ( $env:ident : & $( $lt:lifetime )? mut Env $( , $ident:ident : $ty:ty )* $(,)? ) -> napi_status $body:block ) => {
|
( $( # $attr:tt )* fn $name:ident $( < $( $x:lifetime ),* > )? ( $env:ident : & $( $lt:lifetime )? mut Env $( , $ident:ident : $ty:ty )* $(,)? ) -> napi_status $body:block ) => {
|
||||||
$( # $attr )*
|
$( # $attr )*
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(clippy::missing_safety_doc)]
|
|
||||||
pub unsafe extern "C" fn $name $( < $( $x ),* > )? ( env_ptr : *mut Env , $( $ident : $ty ),* ) -> napi_status {
|
pub unsafe extern "C" fn $name $( < $( $x ),* > )? ( env_ptr : *mut Env , $( $ident : $ty ),* ) -> napi_status {
|
||||||
let env: & $( $lt )? mut Env = $crate::check_env!(env_ptr);
|
let env: & $( $lt )? mut Env = $crate::check_env!(env_ptr);
|
||||||
|
|
||||||
|
@ -241,7 +240,7 @@ macro_rules! napi_wrap {
|
||||||
return napi_pending_exception;
|
return napi_pending_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
$crate::util::napi_clear_last_error(env);
|
$crate::napi::util::napi_clear_last_error(env);
|
||||||
|
|
||||||
let scope_env = unsafe { &mut *env_ptr };
|
let scope_env = unsafe { &mut *env_ptr };
|
||||||
let scope = &mut scope_env.scope();
|
let scope = &mut scope_env.scope();
|
||||||
|
@ -260,11 +259,11 @@ macro_rules! napi_wrap {
|
||||||
let env = unsafe { &mut *env_ptr };
|
let env = unsafe { &mut *env_ptr };
|
||||||
let global = v8::Global::new(env.isolate(), exception);
|
let global = v8::Global::new(env.isolate(), exception);
|
||||||
env.last_exception = Some(global);
|
env.last_exception = Some(global);
|
||||||
return $crate::util::napi_set_last_error(env_ptr, napi_pending_exception);
|
return $crate::napi::util::napi_set_last_error(env_ptr, napi_pending_exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
if result != napi_ok {
|
if result != napi_ok {
|
||||||
return $crate::util::napi_set_last_error(env_ptr, result);
|
return $crate::napi::util::napi_set_last_error(env_ptr, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -274,7 +273,6 @@ macro_rules! napi_wrap {
|
||||||
( $( # $attr:tt )* fn $name:ident $( < $( $x:lifetime ),* > )? ( $( $ident:ident : $ty:ty ),* $(,)? ) -> napi_status $body:block ) => {
|
( $( # $attr:tt )* fn $name:ident $( < $( $x:lifetime ),* > )? ( $( $ident:ident : $ty:ty ),* $(,)? ) -> napi_status $body:block ) => {
|
||||||
$( # $attr )*
|
$( # $attr )*
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(clippy::missing_safety_doc)]
|
|
||||||
pub unsafe extern "C" fn $name $( < $( $x ),* > )? ( $( $ident : $ty ),* ) -> napi_status {
|
pub unsafe extern "C" fn $name $( < $( $x ),* > )? ( $( $ident : $ty ),* ) -> napi_status {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn inner $( < $( $x ),* > )? ( $( $ident : $ty ),* ) -> napi_status $body
|
fn inner $( < $( $x ),* > )? ( $( $ident : $ty ),* ) -> napi_status $body
|
|
@ -16,7 +16,4 @@ path = "lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deno_core.workspace = true
|
deno_core.workspace = true
|
||||||
deno_permissions.workspace = true
|
deno_permissions.workspace = true
|
||||||
libc.workspace = true
|
|
||||||
libloading = { version = "0.7" }
|
libloading = { version = "0.7" }
|
||||||
log.workspace = true
|
|
||||||
napi_sym.workspace = true
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
# napi
|
|
||||||
|
|
||||||
This directory contains source for Deno's Node-API implementation. It depends on
|
|
||||||
`napi_sym` and `deno_napi`.
|
|
||||||
|
|
||||||
Files are generally organized the same as in Node.js's implementation to ease in
|
|
||||||
ensuring compatibility.
|
|
||||||
|
|
||||||
## Adding a new function
|
|
||||||
|
|
||||||
Add the symbol name to
|
|
||||||
[`cli/napi_sym/symbol_exports.json`](../napi_sym/symbol_exports.json).
|
|
||||||
|
|
||||||
```diff
|
|
||||||
{
|
|
||||||
"symbols": [
|
|
||||||
...
|
|
||||||
"napi_get_undefined",
|
|
||||||
- "napi_get_null"
|
|
||||||
+ "napi_get_null",
|
|
||||||
+ "napi_get_boolean"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Determine where to place the implementation. `napi_get_boolean` is related to JS
|
|
||||||
values so we will place it in `js_native_api.rs`. If something is not clear,
|
|
||||||
just create a new file module.
|
|
||||||
|
|
||||||
See [`napi_sym`](../napi_sym/) for writing the implementation:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[napi_sym::napi_sym]
|
|
||||||
pub fn napi_get_boolean(
|
|
||||||
env: *mut Env,
|
|
||||||
value: bool,
|
|
||||||
result: *mut napi_value,
|
|
||||||
) -> Result {
|
|
||||||
// ...
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Update the generated symbol lists using the script:
|
|
||||||
|
|
||||||
```
|
|
||||||
deno run --allow-write tools/napi/generate_symbols_lists.js
|
|
||||||
```
|
|
||||||
|
|
||||||
Add a test in [`/tests/napi`](../../tests/napi/). You can also refer to Node.js
|
|
||||||
test suite for Node-API.
|
|
||||||
|
|
||||||
```js
|
|
||||||
// tests/napi/boolean_test.js
|
|
||||||
import { assertEquals, loadTestLibrary } from "./common.js";
|
|
||||||
const lib = loadTestLibrary();
|
|
||||||
Deno.test("napi get boolean", function () {
|
|
||||||
assertEquals(lib.test_get_boolean(true), true);
|
|
||||||
assertEquals(lib.test_get_boolean(false), false);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// tests/napi/src/boolean.rs
|
|
||||||
|
|
||||||
use napi_sys::Status::napi_ok;
|
|
||||||
use napi_sys::ValueType::napi_boolean;
|
|
||||||
use napi_sys::*;
|
|
||||||
|
|
||||||
extern "C" fn test_boolean(
|
|
||||||
env: napi_env,
|
|
||||||
info: napi_callback_info,
|
|
||||||
) -> napi_value {
|
|
||||||
let (args, argc, _) = crate::get_callback_info!(env, info, 1);
|
|
||||||
assert_eq!(argc, 1);
|
|
||||||
|
|
||||||
let mut ty = -1;
|
|
||||||
assert!(unsafe { napi_typeof(env, args[0], &mut ty) } == napi_ok);
|
|
||||||
assert_eq!(ty, napi_boolean);
|
|
||||||
|
|
||||||
// Use napi_get_boolean here...
|
|
||||||
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init(env: napi_env, exports: napi_value) {
|
|
||||||
let properties = &[crate::new_property!(env, "test_boolean\0", test_boolean)];
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
napi_define_properties(env, exports, properties.len(), properties.as_ptr())
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```diff
|
|
||||||
// tests/napi/src/lib.rs
|
|
||||||
|
|
||||||
+ mod boolean;
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn napi_register_module_v1(
|
|
||||||
env: napi_env,
|
|
||||||
exports: napi_value,
|
|
||||||
) -> napi_value {
|
|
||||||
...
|
|
||||||
+ boolean::init(env, exports);
|
|
||||||
|
|
||||||
exports
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the test using `cargo test -p tests/napi`.
|
|
|
@ -5,21 +5,6 @@
|
||||||
#![allow(clippy::undocumented_unsafe_blocks)]
|
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||||
#![deny(clippy::missing_safety_doc)]
|
#![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 `cli/napi/generated_symbol_exports_list_*.def`.
|
|
||||||
|
|
||||||
pub mod js_native_api;
|
|
||||||
pub mod node_api;
|
|
||||||
pub mod util;
|
|
||||||
|
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env -S deno run --allow-read --allow-write
|
#!/usr/bin/env -S deno run --allow-read --allow-write
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import exports from "../../ext/napi/sym/symbol_exports.json" with {
|
import exports from "../../cli/napi/sym/symbol_exports.json" with {
|
||||||
type: "json",
|
type: "json",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ const symbolExportLists = {
|
||||||
|
|
||||||
for await (const [os, def] of Object.entries(symbolExportLists)) {
|
for await (const [os, def] of Object.entries(symbolExportLists)) {
|
||||||
const defUrl = new URL(
|
const defUrl = new URL(
|
||||||
`../../ext/napi/generated_symbol_exports_list_${os}.def`,
|
`../../cli/napi/generated_symbol_exports_list_${os}.def`,
|
||||||
import.meta.url,
|
import.meta.url,
|
||||||
);
|
);
|
||||||
await Deno.writeTextFile(defUrl.pathname, def, { create: true });
|
await Deno.writeTextFile(defUrl.pathname, def, { create: true });
|
||||||
|
|
Loading…
Reference in a new issue