summaryrefslogtreecommitdiff
path: root/ext/napi/sym
diff options
context:
space:
mode:
Diffstat (limited to 'ext/napi/sym')
-rw-r--r--ext/napi/sym/Cargo.toml21
-rw-r--r--ext/napi/sym/README.md38
-rw-r--r--ext/napi/sym/lib.rs31
-rw-r--r--ext/napi/sym/symbol_exports.json164
4 files changed, 254 insertions, 0 deletions
diff --git a/ext/napi/sym/Cargo.toml b/ext/napi/sym/Cargo.toml
new file mode 100644
index 000000000..7c13a9165
--- /dev/null
+++ b/ext/napi/sym/Cargo.toml
@@ -0,0 +1,21 @@
+# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+[package]
+name = "napi_sym"
+version = "0.107.0"
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+readme = "README.md"
+repository.workspace = true
+description = "proc macro for writing N-API symbols"
+
+[lib]
+path = "./lib.rs"
+proc-macro = true
+
+[dependencies]
+quote.workspace = true
+serde.workspace = true
+serde_json.workspace = true
+syn.workspace = true
diff --git a/ext/napi/sym/README.md b/ext/napi/sym/README.md
new file mode 100644
index 000000000..66eb4bff2
--- /dev/null
+++ b/ext/napi/sym/README.md
@@ -0,0 +1,38 @@
+# napi_sym
+
+A proc_macro for Deno's Node-API implementation. It does the following things:
+
+- Marks the symbol as `#[no_mangle]` and rewrites it as
+ `unsafe extern "C" $name`.
+- Asserts that the function symbol is present in
+ [`symbol_exports.json`](./symbol_exports.json).
+- Maps `deno_napi::Result` to raw `napi_result`.
+
+```rust
+use deno_napi::napi_value;
+use deno_napi::Env;
+use deno_napi::Error;
+use deno_napi::Result;
+
+#[napi_sym::napi_sym]
+fn napi_get_boolean(
+ env: *mut Env,
+ value: bool,
+ result: *mut napi_value,
+) -> Result {
+ let _env: &mut Env = env.as_mut().ok_or(Error::InvalidArg)?;
+ // *result = ...
+ Ok(())
+}
+```
+
+### `symbol_exports.json`
+
+A file containing the symbols that need to be put into the executable's dynamic
+symbol table at link-time.
+
+This is done using `/DEF:` on Windows, `-exported_symbol,_` on macOS and
+`--export-dynamic-symbol=` on Linux. See [`cli/build.rs`](../build.rs).
+
+On Windows, you need to generate the `.def` file by running
+[`tools/napi/generate_symbols_lists.js`](../../tools/napi/generate_symbols_lists.js).
diff --git a/ext/napi/sym/lib.rs b/ext/napi/sym/lib.rs
new file mode 100644
index 000000000..e2826306b
--- /dev/null
+++ b/ext/napi/sym/lib.rs
@@ -0,0 +1,31 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use proc_macro::TokenStream;
+use quote::quote;
+use serde::Deserialize;
+
+static NAPI_EXPORTS: &str = include_str!("./symbol_exports.json");
+
+#[derive(Deserialize)]
+struct SymbolExports {
+ pub symbols: Vec<String>,
+}
+
+#[proc_macro_attribute]
+pub fn napi_sym(_attr: TokenStream, item: TokenStream) -> TokenStream {
+ let func = syn::parse::<syn::ItemFn>(item).expect("expected a function");
+
+ let exports: SymbolExports =
+ serde_json::from_str(NAPI_EXPORTS).expect("failed to parse exports");
+ let name = &func.sig.ident;
+ assert!(
+ exports.symbols.contains(&name.to_string()),
+ "cli/napi/sym/symbol_exports.json is out of sync!"
+ );
+
+ TokenStream::from(quote! {
+ crate::napi_wrap! {
+ #func
+ }
+ })
+}
diff --git a/ext/napi/sym/symbol_exports.json b/ext/napi/sym/symbol_exports.json
new file mode 100644
index 000000000..00946b8ed
--- /dev/null
+++ b/ext/napi/sym/symbol_exports.json
@@ -0,0 +1,164 @@
+{
+ "symbols": [
+ "node_api_create_syntax_error",
+ "napi_make_callback",
+ "napi_has_named_property",
+ "napi_async_destroy",
+ "napi_coerce_to_object",
+ "napi_get_arraybuffer_info",
+ "napi_detach_arraybuffer",
+ "napi_get_undefined",
+ "napi_reference_unref",
+ "napi_fatal_error",
+ "napi_open_callback_scope",
+ "napi_close_callback_scope",
+ "napi_get_value_uint32",
+ "napi_create_function",
+ "napi_create_arraybuffer",
+ "napi_get_value_int64",
+ "napi_get_all_property_names",
+ "napi_resolve_deferred",
+ "napi_is_detached_arraybuffer",
+ "napi_create_string_utf8",
+ "napi_create_threadsafe_function",
+ "node_api_throw_syntax_error",
+ "napi_create_bigint_int64",
+ "napi_wrap",
+ "napi_set_property",
+ "napi_get_value_bigint_int64",
+ "napi_open_handle_scope",
+ "napi_create_error",
+ "napi_create_buffer",
+ "napi_cancel_async_work",
+ "napi_is_exception_pending",
+ "napi_acquire_threadsafe_function",
+ "napi_create_external",
+ "napi_get_threadsafe_function_context",
+ "napi_get_null",
+ "napi_create_string_utf16",
+ "node_api_create_external_string_utf16",
+ "napi_get_value_bigint_uint64",
+ "napi_module_register",
+ "napi_is_typedarray",
+ "napi_create_external_buffer",
+ "napi_get_new_target",
+ "napi_get_instance_data",
+ "napi_close_handle_scope",
+ "napi_get_value_string_utf16",
+ "napi_get_property_names",
+ "napi_is_arraybuffer",
+ "napi_get_cb_info",
+ "napi_define_properties",
+ "napi_add_env_cleanup_hook",
+ "node_api_get_module_file_name",
+ "napi_get_node_version",
+ "napi_create_int64",
+ "napi_create_double",
+ "napi_get_and_clear_last_exception",
+ "napi_create_reference",
+ "napi_get_typedarray_info",
+ "napi_call_threadsafe_function",
+ "napi_get_last_error_info",
+ "napi_create_array_with_length",
+ "napi_coerce_to_number",
+ "napi_get_global",
+ "napi_is_error",
+ "napi_set_instance_data",
+ "napi_create_typedarray",
+ "napi_throw_type_error",
+ "napi_has_property",
+ "napi_get_value_external",
+ "napi_create_range_error",
+ "napi_typeof",
+ "napi_ref_threadsafe_function",
+ "napi_create_bigint_uint64",
+ "napi_get_prototype",
+ "napi_adjust_external_memory",
+ "napi_release_threadsafe_function",
+ "napi_delete_async_work",
+ "napi_create_string_latin1",
+ "node_api_create_external_string_latin1",
+ "napi_is_array",
+ "napi_unref_threadsafe_function",
+ "napi_throw_error",
+ "napi_has_own_property",
+ "napi_get_reference_value",
+ "napi_remove_env_cleanup_hook",
+ "napi_get_value_string_utf8",
+ "napi_is_promise",
+ "napi_get_boolean",
+ "napi_run_script",
+ "napi_get_element",
+ "napi_get_named_property",
+ "napi_get_buffer_info",
+ "napi_get_value_bool",
+ "napi_reference_ref",
+ "napi_create_object",
+ "napi_create_promise",
+ "napi_create_int32",
+ "napi_escape_handle",
+ "napi_open_escapable_handle_scope",
+ "napi_throw",
+ "napi_get_value_double",
+ "napi_set_named_property",
+ "napi_call_function",
+ "napi_create_date",
+ "napi_object_freeze",
+ "napi_get_uv_event_loop",
+ "napi_get_value_string_latin1",
+ "napi_reject_deferred",
+ "napi_add_finalizer",
+ "napi_create_array",
+ "napi_delete_reference",
+ "napi_get_date_value",
+ "napi_create_dataview",
+ "napi_get_version",
+ "napi_define_class",
+ "napi_is_date",
+ "napi_remove_wrap",
+ "napi_delete_property",
+ "napi_instanceof",
+ "napi_create_buffer_copy",
+ "napi_delete_element",
+ "napi_object_seal",
+ "napi_queue_async_work",
+ "napi_get_value_bigint_words",
+ "napi_is_buffer",
+ "napi_get_array_length",
+ "napi_get_property",
+ "napi_new_instance",
+ "napi_set_element",
+ "napi_create_bigint_words",
+ "napi_strict_equals",
+ "napi_is_dataview",
+ "napi_close_escapable_handle_scope",
+ "napi_get_dataview_info",
+ "napi_get_value_int32",
+ "napi_unwrap",
+ "napi_throw_range_error",
+ "napi_coerce_to_bool",
+ "napi_create_uint32",
+ "napi_has_element",
+ "napi_create_external_arraybuffer",
+ "napi_create_symbol",
+ "node_api_symbol_for",
+ "napi_coerce_to_string",
+ "napi_create_type_error",
+ "napi_fatal_exception",
+ "napi_create_async_work",
+ "napi_async_init",
+ "node_api_create_property_key_utf16",
+ "napi_type_tag_object",
+ "napi_check_object_type_tag",
+ "node_api_post_finalizer",
+ "napi_add_async_cleanup_hook",
+ "napi_remove_async_cleanup_hook",
+ "uv_mutex_init",
+ "uv_mutex_lock",
+ "uv_mutex_unlock",
+ "uv_mutex_destroy",
+ "uv_async_init",
+ "uv_async_send",
+ "uv_close"
+ ]
+}