Skip to content

Commit

Permalink
feat(npm): implement Node API (#13633)
Browse files Browse the repository at this point in the history
This PR implements the NAPI for loading native modules into Deno. 

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
Co-authored-by: DjDeveloper <43033058+DjDeveloperr@users.noreply.github.com>
Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
  • Loading branch information
4 people authored Oct 5, 2022
1 parent 3a3a848 commit 0b016a7
Show file tree
Hide file tree
Showing 55 changed files with 5,299 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ gclient_config.py_entries
/target/
/std/hash/_wasm/target
/tools/wpt/manifest.json
/test_napi/node_modules
/test_napi/build
/test_napi/third_party_tests/node_modules

# Files that help ensure VSCode can work but we don't want checked into the
# repo
Expand Down
45 changes: 45 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ resolver = "2"
members = [
"bench_util",
"cli",
"cli/napi_sym",
"core",
"ops",
"runtime",
"serde_v8",
"test_ffi",
"test_napi",
"test_util",
"ext/broadcast_channel",
"ext/cache",
Expand All @@ -27,6 +29,7 @@ members = [
"ext/webidl",
"ext/websocket",
"ext/webstorage",
"ext/napi",
]
exclude = ["test_util/std/hash/_wasm"]

Expand Down Expand Up @@ -154,6 +157,8 @@ opt-level = 3
opt-level = 3
[profile.release.package.deno_websocket]
opt-level = 3
[profile.release.package.deno_napi]
opt-level = 3
[profile.release.package.num-bigint-dig]
opt-level = 3
[profile.release.package.v8]
Expand Down
1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ deno_graph = "0.34.0"
deno_lint = { version = "0.33.0", features = ["docs"] }
deno_runtime = { version = "0.79.0", path = "../runtime" }
deno_task_shell = "0.5.2"
napi_sym = { path = "./napi_sym", version = "0.1.0" }

atty = "=0.2.14"
base64 = "=0.13.0"
Expand Down
15 changes: 15 additions & 0 deletions cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,21 @@ fn main() {
if target != host {
panic!("Cross compiling with snapshot is not supported.");
}

#[cfg(target_os = "windows")]
println!(
"cargo:rustc-link-arg-bin=deno=/DEF:{}",
std::path::Path::new("exports.def")
.canonicalize()
.expect(
"Missing exports.def! Generate using tools/napi/generate_link_win.js"
)
.display(),
);

#[cfg(not(target_os = "windows"))]
println!("cargo:rustc-link-arg-bin=deno=-rdynamic");

// To debug snapshot issues uncomment:
// op_fetch_asset::trace_serializer();

Expand Down
146 changes: 146 additions & 0 deletions cli/exports.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
LIBRARY
EXPORTS
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
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
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
napi_coerce_to_string
napi_create_type_error
napi_fatal_exception
napi_create_async_work
napi_async_init
1 change: 1 addition & 0 deletions cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod lockfile;
mod logger;
mod lsp;
mod module_loader;
mod napi;
mod node;
mod npm;
mod ops;
Expand Down
78 changes: 78 additions & 0 deletions cli/napi/async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.

use deno_runtime::deno_napi::*;

#[repr(C)]
pub struct AsyncWork {
pub data: *mut c_void,
pub execute: napi_async_execute_callback,
pub complete: napi_async_complete_callback,
}

#[napi_sym::napi_sym]
fn napi_create_async_work(
_env: *mut Env,
_async_resource: napi_value,
_async_resource_name: napi_value,
execute: napi_async_execute_callback,
complete: napi_async_complete_callback,
data: *mut c_void,
result: *mut napi_async_work,
) -> Result {
let mut work = AsyncWork {
data,
execute,
complete,
};
*result = transmute::<Box<AsyncWork>, _>(Box::new(work));
Ok(())
}

#[napi_sym::napi_sym]
fn napi_cancel_async_work(
_env: &mut Env,
_async_work: napi_async_work,
) -> Result {
Ok(())
}

/// Frees a previously allocated work object.
#[napi_sym::napi_sym]
fn napi_delete_async_work(_env: &mut Env, work: napi_async_work) -> Result {
let work = Box::from_raw(work);
drop(work);

Ok(())
}

#[napi_sym::napi_sym]
fn napi_queue_async_work(env_ptr: *mut Env, work: napi_async_work) -> Result {
let work: &AsyncWork = &*(work as *const AsyncWork);
let env: &mut Env = env_ptr.as_mut().ok_or(Error::InvalidArg)?;

let fut = Box::new(move || {
(work.execute)(env_ptr as napi_env, work.data);
// Note: Must be called from the loop thread.
(work.complete)(env_ptr as napi_env, napi_ok, work.data);
});
env.add_async_work(fut);

Ok(())
}

// TODO: Custom async operations.

#[napi_sym::napi_sym]
fn napi_async_init(
_env: *mut Env,
_async_resource: napi_value,
_async_resource_name: napi_value,
_result: *mut *mut (),
) -> Result {
todo!()
}

#[napi_sym::napi_sym]
fn napi_async_destroy(_env: *mut Env, _async_context: *mut ()) -> Result {
todo!()
}
Loading

0 comments on commit 0b016a7

Please sign in to comment.