├── testdata ├── .gitignore └── package.json ├── .rustfmt.toml ├── src ├── core.js ├── napi_reference_ref.rs ├── napi_reference_unref.rs ├── napi_release_threadsafe_function.rs ├── napi_ref_threadsafe_function.rs ├── napi_call_threadsafe_function.rs ├── napi_unref_threadsafe_function.rs ├── napi_get_all_property_names.rs ├── napi_delete_async_work.rs ├── napi_cancel_async_work.rs ├── napi_get_version.rs ├── napi_get_last_error_info.rs ├── napi_open_escapable_handle_scope.rs ├── napi_escape_handle.rs ├── napi_get_reference_value.rs ├── napi_is_exception_pending.rs ├── napi_throw.rs ├── napi_delete_reference.rs ├── napi_get_instance_data.rs ├── napi_adjust_external_memory.rs ├── node_api_get_module_file_name.rs ├── napi_create_object.rs ├── napi_is_date.rs ├── napi_close_escapable_handle_scope.rs ├── napi_get_null.rs ├── napi_add_env_cleanup_hook.rs ├── napi_get_undefined.rs ├── napi_remove_env_cleanup_hook.rs ├── napi_is_array.rs ├── napi_is_dataview.rs ├── napi_is_arraybuffer.rs ├── napi_is_promise.rs ├── napi_is_typedarray.rs ├── napi_is_error.rs ├── napi_create_reference.rs ├── napi_detach_arraybuffer.rs ├── napi_get_value_bool.rs ├── napi_open_handle_scope.rs ├── napi_create_double.rs ├── napi_get_boolean.rs ├── napi_get_value_double.rs ├── napi_get_value_int32.rs ├── napi_get_value_uint32.rs ├── napi_create_date.rs ├── napi_create_int32.rs ├── napi_create_int64.rs ├── napi_create_array_with_length.rs ├── napi_create_uint32.rs ├── napi_get_array_length.rs ├── napi_create_bigint_int64.rs ├── napi_get_global.rs ├── napi_create_bigint_uint64.rs ├── napi_close_handle_scope.rs ├── napi_get_value_bigint_int64.rs ├── napi_get_value_bigint_uint64.rs ├── napi_get_value_external.rs ├── napi_reject_deferred.rs ├── napi_is_buffer.rs ├── napi_resolve_deferred.rs ├── napi_strict_equals.rs ├── napi_get_date_value.rs ├── napi_has_element.rs ├── napi_delete_element.rs ├── napi_fatal_exception.rs ├── napi_get_and_clear_last_exception.rs ├── napi_coerce_to_bool.rs ├── napi_get_prototype.rs ├── napi_has_property.rs ├── napi_coerce_to_number.rs ├── napi_coerce_to_object.rs ├── napi_coerce_to_string.rs ├── napi_create_external.rs ├── napi_get_new_target.rs ├── napi_instanceof.rs ├── napi_delete_property.rs ├── napi_remove_wrap.rs ├── napi_create_promise.rs ├── napi_set_element.rs ├── napi_set_instance_data.rs ├── napi_get_element.rs ├── napi_is_detached_arraybuffer.rs ├── napi_create_bigint_words.rs ├── napi_create_arraybuffer.rs ├── napi_create_string_latin1.rs ├── napi_create_string_utf16.rs ├── napi_has_named_property.rs ├── napi_create_error.rs ├── napi_create_threadsafe_function.rs ├── napi_get_arraybuffer_info.rs ├── napi_get_property.rs ├── napi_get_property_names.rs ├── napi_create_type_error.rs ├── napi_create_range_error.rs ├── napi_set_property.rs ├── napi_set_named_property.rs ├── napi_throw_error.rs ├── node_api_create_syntax_error.rs ├── napi_throw_type_error.rs ├── napi_wrap.rs ├── napi_get_node_version.rs ├── napi_throw_range_error.rs ├── napi_create_buffer.rs ├── node_api_throw_syntax_error.rs ├── util.rs ├── napi_create_symbol.rs ├── napi_unwrap.rs ├── napi_get_named_property.rs ├── napi_create_string_utf8.rs ├── napi_create_buffer_copy.rs ├── napi_new_instance.rs ├── napi_get_buffer_info.rs ├── napi_call_function.rs ├── napi_create_function.rs ├── napi_get_dataview_info.rs ├── napi_get_value_bigint_words.rs ├── napi_get_typedarray_info.rs ├── napi_run_script.rs ├── napi_module_register.rs ├── napi_queue_async_work.rs ├── napi_fatal_error.rs ├── napi_create_external_buffer.rs ├── napi_get_value_string_utf16.rs ├── napi_create_async_work.rs ├── napi_get_value_string_latin1.rs ├── napi_define_properties.rs ├── napi_get_cb_info.rs ├── napi_get_value_string_utf8.rs ├── napi_create_dataview.rs ├── napi_typeof.rs ├── napi_create_external_arraybuffer.rs ├── env.rs ├── napi_create_typedarray.rs ├── napi_define_class.rs ├── function.rs ├── ffi.rs └── main.rs ├── test ├── skia-canvas.js ├── test_parcel_optimizer.jpeg ├── node-usb.js ├── fs-xattr.js ├── dprint.js ├── parcel_fs_search.js ├── parcel_hash.js ├── example.js ├── parcel_transformer.js ├── parcel_css.js └── parcel_optimizer_image.js ├── .gitignore ├── example_module ├── build.rs ├── Cargo.toml ├── src │ └── lib.rs └── Cargo.lock ├── README.md ├── .cargo └── config ├── Cargo.toml ├── proc_macro ├── Cargo.toml └── lib.rs ├── LICENSE └── Cargo.lock /testdata/.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | tab_spaces = 2 3 | edition = "2018" 4 | 5 | -------------------------------------------------------------------------------- /src/core.js: -------------------------------------------------------------------------------- 1 | function print(txt) { 2 | Deno.core.print(txt + "\n"); 3 | } 4 | -------------------------------------------------------------------------------- /test/skia-canvas.js: -------------------------------------------------------------------------------- 1 | const exported = dlopen("testdata/node_modules/skia-canvas/lib/v6/index.node"); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.node 2 | target/ 3 | example_module/target/ 4 | node_modules/ 5 | .vscode/ 6 | exports.def 7 | -------------------------------------------------------------------------------- /example_module/build.rs: -------------------------------------------------------------------------------- 1 | extern crate napi_build; 2 | 3 | fn main() { 4 | napi_build::setup(); 5 | } 6 | -------------------------------------------------------------------------------- /test/test_parcel_optimizer.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/littledivy/napi-rusty-v8/HEAD/test/test_parcel_optimizer.jpeg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deno N-API 2 | 3 | [WIP] N-API implementation for Deno. 4 | 5 | ## Moved to https://github.com/denoland/deno/pull/13633 6 | -------------------------------------------------------------------------------- /src/napi_reference_ref.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_reference_ref() -> Result { 5 | // TODO 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /src/napi_reference_unref.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_reference_unref() -> Result { 5 | // TODO 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /src/napi_release_threadsafe_function.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_release_threadsafe_function() -> Result { 5 | Ok(()) 6 | } 7 | -------------------------------------------------------------------------------- /src/napi_ref_threadsafe_function.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_ref_threadsafe_function() -> Result { 5 | // TODO 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /test/node-usb.js: -------------------------------------------------------------------------------- 1 | const usb = dlopen( 2 | "./testdata/node_modules/usb/prebuilds/linux-x64/node.napi.glibc.node", 3 | ); 4 | 5 | print(usb.getDeviceList()); 6 | -------------------------------------------------------------------------------- /src/napi_call_threadsafe_function.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_call_threadsafe_function() -> Result { 5 | // TODO 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /src/napi_unref_threadsafe_function.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_unref_threadsafe_function() -> Result { 5 | // TODO 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /src/napi_get_all_property_names.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_get_all_property_names(env: napi_env) -> Result { 5 | // TODO 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /src/napi_delete_async_work.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_delete_async_work(env: napi_env, work: napi_async_work) -> Result { 5 | // TODO 6 | Ok(()) 7 | } 8 | -------------------------------------------------------------------------------- /test/fs-xattr.js: -------------------------------------------------------------------------------- 1 | const xattr = dlopen("testdata/node_modules/fs-xattr/build/Release/xattr.node"); 2 | 3 | xattr.set("example.txt", "foo", Deno.core.encode("bar")); 4 | xattr.get("exports.def", "foo").catch(print); 5 | -------------------------------------------------------------------------------- /src/napi_cancel_async_work.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_cancel_async_work( 5 | env: napi_env, 6 | async_work: napi_async_work, 7 | ) -> Result { 8 | // TODO 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/napi_get_version.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | pub const NAPI_VERSION: u32 = 8; 4 | 5 | #[napi_sym] 6 | fn napi_get_version(_: napi_env, version: *mut u32) -> Result { 7 | *version = NAPI_VERSION; 8 | Ok(()) 9 | } 10 | -------------------------------------------------------------------------------- /.cargo/config: -------------------------------------------------------------------------------- 1 | [target.x86_64-unknown-linux-gnu] 2 | rustflags = [ 3 | "-C", 4 | "link-args=-Wl,-export-dynamic", 5 | "-C", 6 | "linker=clang", 7 | ] 8 | 9 | [target.x86_64-windows-msvc] 10 | rustflags = ["-C", "target-feature=+crt-static"] 11 | -------------------------------------------------------------------------------- /src/napi_get_last_error_info.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_get_last_error_info( 5 | env: napi_env, 6 | error_code: *mut *const napi_extended_error_info, 7 | ) -> Result { 8 | *error_code = std::ptr::null(); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/napi_open_escapable_handle_scope.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_open_escapable_handle_scope( 5 | env: napi_env, 6 | result: *mut napi_escapable_handle_scope, 7 | ) -> Result { 8 | // TODO: do this properly 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/napi_escape_handle.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_escape_handle( 5 | env: napi_env, 6 | handle_scope: napi_escapable_handle_scope, 7 | escapee: napi_value, 8 | result: *mut napi_value, 9 | ) -> Result { 10 | // TODO 11 | Ok(()) 12 | } 13 | -------------------------------------------------------------------------------- /src/napi_get_reference_value.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[napi_sym] 4 | fn napi_get_reference_value( 5 | env: napi_env, 6 | reference: napi_ref, 7 | result: *mut napi_value, 8 | ) -> Result { 9 | // TODO 10 | *result = transmute(reference); 11 | Ok(()) 12 | } 13 | -------------------------------------------------------------------------------- /src/napi_is_exception_pending.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | 4 | #[napi_sym] 5 | fn napi_is_exception_pending(env: napi_env, result: *mut bool) -> Result { 6 | let mut env = &mut *(env as *mut Env); 7 | // TODO 8 | *result = false; 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "napi-deno" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | deno_core = "0.114.0" 8 | libloading = "0.7" 9 | napi_sym = { path = "./proc_macro", version = "0.0.0" } 10 | tokio = { version = "1.10.1", features = ["full"] } 11 | 12 | -------------------------------------------------------------------------------- /src/napi_throw.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | 4 | #[napi_sym] 5 | fn napi_throw(env: napi_env, error: napi_value) -> Result { 6 | let mut env = &mut *(env as *mut Env); 7 | let error = transmute(error); 8 | env.scope.throw_exception(error); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/napi_delete_reference.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | // use deno_core::v8; 4 | 5 | // TODO: properly implement ref counting stuff 6 | #[napi_sym] 7 | fn napi_delete_reference(env: napi_env, nref: napi_ref) -> Result { 8 | let mut _env = &mut *(env as *mut Env); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/napi_get_instance_data.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | 4 | #[napi_sym] 5 | fn napi_get_instance_data(env: napi_env, result: *mut *mut c_void) -> Result { 6 | let env = &mut *(env as *mut Env); 7 | let shared = env.shared(); 8 | *result = shared.instance_data; 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/napi_adjust_external_memory.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | 4 | #[napi_sym] 5 | fn napi_adjust_external_memory( 6 | env: napi_env, 7 | change_in_bytes: i64, 8 | adjusted_value: *mut i64, 9 | ) -> Result { 10 | let mut _env = &mut *(env as *mut Env); 11 | // TODO 12 | Ok(()) 13 | } 14 | -------------------------------------------------------------------------------- /test/dprint.js: -------------------------------------------------------------------------------- 1 | const dprint = dlopen( 2 | "./testdata/node_modules/dprint-node/dprint-node.linux-x64-gnu.node", 3 | ); 4 | 5 | print( 6 | dprint.format( 7 | "hello.js", 8 | "function x(){let a=1;return a;}", 9 | { 10 | lineWidth: 100, 11 | semiColons: "asi", 12 | }, 13 | ), 14 | ); 15 | -------------------------------------------------------------------------------- /src/node_api_get_module_file_name.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | 4 | #[napi_sym] 5 | fn node_api_get_module_file_name( 6 | env: napi_env, 7 | result: *mut *const c_char, 8 | ) -> Result { 9 | let env = &mut *(env as *mut Env); 10 | let shared = env.shared(); 11 | *result = shared.filename; 12 | Ok(()) 13 | } 14 | -------------------------------------------------------------------------------- /src/napi_create_object.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_object(env: napi_env, result: *mut napi_value) -> Result { 7 | let mut env = &mut *(env as *mut Env); 8 | let object = v8::Object::new(env.scope); 9 | *result = std::mem::transmute(object); 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /src/napi_is_date.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_date(env: napi_env, value: napi_value, result: *mut bool) -> Result { 7 | let mut env = &mut (env as *mut Env); 8 | let value: v8::Local = transmute(value); 9 | *result = value.is_date(); 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /src/napi_close_escapable_handle_scope.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | // use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_close_escapable_handle_scope( 7 | env: napi_env, 8 | scope: napi_escapable_handle_scope, 9 | ) -> Result { 10 | let mut env = &mut *(env as *mut Env); 11 | // TODO: do this properly 12 | Ok(()) 13 | } 14 | -------------------------------------------------------------------------------- /src/napi_get_null.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_null(env: napi_env, result: *mut napi_value) -> Result { 7 | let mut env = &mut *(env as *mut Env); 8 | let value: v8::Local = v8::null(env.scope).into(); 9 | *result = std::mem::transmute(value); 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /test/parcel_fs_search.js: -------------------------------------------------------------------------------- 1 | const lib = dlopen( 2 | "./testdata/node_modules/@parcel/fs-search/fs-search.darwin-arm64.node", 3 | ); 4 | 5 | const file = lib.findFirstFile( 6 | [ 7 | "./test/example_non_existent.js", 8 | "./test/example.js", 9 | "./test/example_non_existent2.js", 10 | ], 11 | ); 12 | 13 | print(file); // ./test/example.js 14 | -------------------------------------------------------------------------------- /src/napi_add_env_cleanup_hook.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | // use deno_core::v8; 4 | 5 | // TODO: properly implement 6 | #[napi_sym] 7 | fn napi_add_env_cleanup_hook( 8 | env: napi_env, 9 | hook: extern "C" fn(*const c_void), 10 | data: *const c_void, 11 | ) -> Result { 12 | let mut _env = &mut *(env as *mut Env); 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /src/napi_get_undefined.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_undefined(env: napi_env, result: *mut napi_value) -> Result { 7 | let mut env = &mut *(env as *mut Env); 8 | let value: v8::Local = v8::undefined(env.scope).into(); 9 | *result = std::mem::transmute(value); 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /src/napi_remove_env_cleanup_hook.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | // use deno_core::v8; 4 | 5 | // TODO: properly implement 6 | #[napi_sym] 7 | fn napi_remove_env_cleanup_hook( 8 | env: napi_env, 9 | hook: extern "C" fn(*const c_void), 10 | data: *const c_void, 11 | ) -> Result { 12 | let mut _env = &mut *(env as *mut Env); 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /src/napi_is_array.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_array( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut (env as *mut Env); 12 | let value: v8::Local = transmute(value); 13 | *result = value.is_array(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /proc_macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "napi_sym" 3 | version = "0.0.0" 4 | description = "proc macro for writing N-API symbols" 5 | readme = "../README.md" 6 | license = "MIT" 7 | edition = "2021" 8 | 9 | [lib] 10 | path = "./lib.rs" 11 | proc-macro = true 12 | 13 | [dependencies] 14 | proc-macro2 = "1" 15 | quote = "1" 16 | syn = { version = "1", features = ["full", "extra-traits"] } 17 | -------------------------------------------------------------------------------- /src/napi_is_dataview.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_dataview( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut (env as *mut Env); 12 | let value: v8::Local = transmute(value); 13 | *result = value.is_data_view(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_is_arraybuffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_arraybuffer( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut (env as *mut Env); 12 | let value: v8::Local = transmute(value); 13 | *result = value.is_array_buffer(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_is_promise.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_promise( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | *result = value.is_promise(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_is_typedarray.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_typedarray( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = transmute(value); 13 | *result = value.is_typed_array(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /test/parcel_hash.js: -------------------------------------------------------------------------------- 1 | const lib = dlopen( 2 | "./testdata/node_modules/@parcel/hash/parcel-hash.darwin-arm64.node", 3 | ); 4 | 5 | print(lib.hashString("Hello, Deno!")); // 210a1f862b67f327 6 | print(lib.hashBuffer(Deno.core.encode("Hello, Deno!"))); // 210a1f862b67f327 7 | 8 | const hasher = new lib.Hash(); 9 | hasher.writeString("Hello, Deno!"); 10 | print(hasher.finish()); // 210a1f862b67f327 11 | -------------------------------------------------------------------------------- /src/napi_is_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_error( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut (env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | // TODO 14 | *result = value.is_object(); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_create_reference.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | // use deno_core::v8; 4 | 5 | // TODO: properly implement ref counting stuff 6 | #[napi_sym] 7 | fn napi_create_reference( 8 | env: napi_env, 9 | value: napi_value, 10 | _initial_refcount: u32, 11 | result: *mut napi_ref, 12 | ) -> Result { 13 | let mut _env = &mut *(env as *mut Env); 14 | *result = value; 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_detach_arraybuffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_detach_arraybuffer(env: napi_env, value: napi_value) -> Result { 7 | let mut env = &mut (env as *mut Env); 8 | let value: v8::Local = std::mem::transmute(value); 9 | let ab = v8::Local::::try_from(value).unwrap(); 10 | ab.detach(); 11 | Ok(()) 12 | } 13 | -------------------------------------------------------------------------------- /src/napi_get_value_bool.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_bool( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | *result = value.boolean_value(env.scope); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_open_handle_scope.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_open_handle_scope( 7 | env: napi_env, 8 | result: *mut napi_handle_scope, 9 | ) -> Result { 10 | let env = &mut *(env as *mut Env); 11 | let scope = &mut v8::HandleScope::new(env.scope); 12 | *result = transmute(scope); 13 | env.open_handle_scopes += 1; 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_create_double.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_double( 7 | env: napi_env, 8 | value: f64, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = v8::Number::new(env.scope, value).into(); 13 | *result = std::mem::transmute(value); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_get_boolean.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_boolean( 7 | env: napi_env, 8 | value: bool, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = v8::Boolean::new(env.scope, value).into(); 13 | *result = std::mem::transmute(value); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_get_value_double.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_double( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut f64, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | *result = value.number_value(env.scope).unwrap(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_get_value_int32.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_int32( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut i32, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | *result = value.int32_value(env.scope).unwrap(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_get_value_uint32.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_uint32( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut u32, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | *result = value.uint32_value(env.scope).unwrap(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_create_date.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_date( 7 | env: napi_env, 8 | time: f64, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = 13 | v8::Date::new(env.scope, time).unwrap().into(); 14 | *result = std::mem::transmute(value); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_create_int32.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_int32( 7 | env: napi_env, 8 | value: i32, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = 13 | v8::Number::new(env.scope, value as f64).into(); 14 | *result = std::mem::transmute(value); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_create_int64.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_int64( 7 | env: napi_env, 8 | value: i64, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = 13 | v8::Number::new(env.scope, value as f64).into(); 14 | *result = std::mem::transmute(value); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /test/example.js: -------------------------------------------------------------------------------- 1 | const exports = dlopen("./example_module/target/release/libexample_module.so"); 2 | 3 | print(exports.hello("Rust")); 4 | print(exports.add(1, 2)); 5 | 6 | const point = new exports.Point(1, 2); 7 | print("point.x: " + point.get_x()); 8 | print("point.y: " + point.get_y()); 9 | point.set_x(3); 10 | print("point.x: " + point.get_x()); 11 | 12 | // For testing async 13 | // print(exports.readFileAsync("exports.def")); 14 | -------------------------------------------------------------------------------- /example_module/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_module" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | 9 | [dependencies] 10 | napi = { version = "2", features = ["napi8", "tokio_rt", "async"] } 11 | napi-derive = { version = "2", features = ["type-def"] } 12 | futures = "0.3" 13 | tokio = { version = "1", features = ["default", "fs"] } 14 | 15 | [build-dependencies] 16 | napi-build = "1" 17 | -------------------------------------------------------------------------------- /src/napi_create_array_with_length.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_array_with_length( 7 | env: napi_env, 8 | len: i32, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = v8::Array::new(env.scope, len).into(); 13 | *result = std::mem::transmute(value); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_create_uint32.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_uint32( 7 | env: napi_env, 8 | value: u32, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = 13 | v8::Number::new(env.scope, value as f64).into(); 14 | *result = std::mem::transmute(value); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_get_array_length.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_array_length( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut u32, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | *result = v8::Local::::try_from(value).unwrap().length(); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_create_bigint_int64.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_bigint_int64( 7 | env: napi_env, 8 | value: i64, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = 13 | v8::BigInt::new_from_i64(env.scope, value).into(); 14 | *result = std::mem::transmute(value); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_get_global.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_global(env: napi_env, result: *mut napi_value) -> Result { 7 | let mut env = &mut *(env as *mut Env); 8 | let context = env.scope.get_current_context(); 9 | let global = context.global(env.scope); 10 | let value: v8::Local = global.into(); 11 | *result = std::mem::transmute(value); 12 | Ok(()) 13 | } 14 | -------------------------------------------------------------------------------- /src/napi_create_bigint_uint64.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_bigint_uint64( 7 | env: napi_env, 8 | value: u64, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = 13 | v8::BigInt::new_from_u64(env.scope, value).into(); 14 | *result = std::mem::transmute(value); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_close_handle_scope.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_close_handle_scope(env: napi_env, scope: napi_handle_scope) -> Result { 7 | let env = &mut *(env as *mut Env); 8 | if env.open_handle_scopes == 0 { 9 | return Err(Error::HandleScopeMismatch); 10 | } 11 | let scope = transmute::<_, &mut v8::HandleScope>(scope); 12 | drop(scope); 13 | env.open_handle_scopes -= 1; 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/napi_get_value_bigint_int64.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_bigint_int64( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut i64, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let bigint = value.to_big_int(env.scope).unwrap(); 14 | *result = bigint.i64_value().0; 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_get_value_bigint_uint64.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_bigint_uint64( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut u64, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let bigint = value.to_big_int(env.scope).unwrap(); 14 | *result = bigint.u64_value().0; 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_get_value_external.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_external( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut *mut c_void, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let ext = v8::Local::::try_from(value).unwrap(); 14 | *result = ext.value(); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_reject_deferred.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_reject_deferred( 7 | env: napi_env, 8 | deferred: napi_deferred, 9 | error: napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let resolver: v8::Local = std::mem::transmute(deferred); 13 | resolver 14 | .reject(env.scope, std::mem::transmute(error)) 15 | .unwrap(); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_is_buffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_buffer( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut (env as *mut Env); 12 | let value: v8::Local = transmute(value); 13 | // TODO: should we assume Buffer as Uint8Array in Deno? 14 | // or use std/node polyfill? 15 | *result = value.is_typed_array(); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_resolve_deferred.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_resolve_deferred( 7 | env: napi_env, 8 | deferred: napi_deferred, 9 | result: napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let resolver: v8::Local = std::mem::transmute(deferred); 13 | resolver 14 | .resolve(env.scope, std::mem::transmute(result)) 15 | .unwrap(); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_strict_equals.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_strict_equals( 7 | env: napi_env, 8 | lhs: napi_value, 9 | rhs: napi_value, 10 | result: *mut bool, 11 | ) -> Result { 12 | let mut env = &mut (env as *mut Env); 13 | let lhs: v8::Local = std::mem::transmute(lhs); 14 | let rhs: v8::Local = std::mem::transmute(rhs); 15 | *result = lhs.strict_equals(rhs); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_get_date_value.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_date_value( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut f64, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let date = v8::Local::::try_from(value).unwrap(); 14 | *result = date.number_value(env.scope).unwrap(); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_has_element.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_has_element( 7 | env: napi_env, 8 | value: napi_value, 9 | index: u32, 10 | result: *mut bool, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let value: v8::Local = std::mem::transmute(value); 14 | let obj = value.to_object(env.scope).unwrap(); 15 | *result = obj.has_index(env.scope, index).unwrap_or(false); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_delete_element.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_delete_element( 7 | env: napi_env, 8 | value: napi_value, 9 | index: u32, 10 | result: *mut bool, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let value: v8::Local = std::mem::transmute(value); 14 | let obj = value.to_object(env.scope).unwrap(); 15 | *result = obj.delete_index(env.scope, index).unwrap_or(false); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_fatal_exception.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[no_mangle] 6 | pub unsafe extern "C" fn napi_fatal_exception( 7 | env: napi_env, 8 | value: napi_value, 9 | ) -> ! { 10 | let mut env = &mut *(env as *mut Env); 11 | let value: v8::Local = std::mem::transmute(value); 12 | let error = value.to_rust_string_lossy(env.scope); 13 | panic!( 14 | "Fatal exception triggered by napi_fatal_exception!\n{}", 15 | error 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_get_and_clear_last_exception.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_and_clear_last_exception( 7 | env: napi_env, 8 | result: *mut napi_value, 9 | ) -> Result { 10 | let mut env = &mut *(env as *mut Env); 11 | // TODO: just return undefined for now we don't cache 12 | // exceptions in env. 13 | let value: v8::Local = v8::undefined(env.scope).into(); 14 | *result = std::mem::transmute(value); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/napi_coerce_to_bool.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_coerce_to_bool( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let coerced = value.to_boolean(env.scope); 14 | let value: v8::Local = coerced.into(); 15 | *result = std::mem::transmute(value); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_get_prototype.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_prototype( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let obj = value.to_object(env.scope).unwrap(); 14 | let proto = obj.get_prototype(env.scope).unwrap(); 15 | *result = std::mem::transmute(proto); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_has_property.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_has_property( 7 | env: napi_env, 8 | value: napi_value, 9 | key: napi_value, 10 | result: *mut bool, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let value: v8::Local = transmute(value); 14 | let obj = value.to_object(env.scope).unwrap(); 15 | *result = obj 16 | .has(env.scope, std::mem::transmute(key)) 17 | .unwrap_or(false); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /src/napi_coerce_to_number.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_coerce_to_number( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let coerced = value.to_number(env.scope).unwrap(); 14 | let value: v8::Local = coerced.into(); 15 | *result = std::mem::transmute(value); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_coerce_to_object.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_coerce_to_object( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let coerced = value.to_object(env.scope).unwrap(); 14 | let value: v8::Local = coerced.into(); 15 | *result = std::mem::transmute(value); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_coerce_to_string.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_coerce_to_string( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let coerced = value.to_string(env.scope).unwrap(); 14 | let value: v8::Local = coerced.into(); 15 | *result = std::mem::transmute(value); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_create_external.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_external( 7 | env: napi_env, 8 | value: *mut c_void, 9 | finalize_cb: napi_finalize, 10 | finalize_hint: *mut c_void, 11 | result: *mut napi_value, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | let value: v8::Local = v8::External::new(env.scope, value).into(); 15 | // TODO: finalization 16 | *result = std::mem::transmute(value); 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /src/napi_get_new_target.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::function::CallbackInfo; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_get_new_target( 8 | env: napi_env, 9 | cbinfo: napi_callback_info, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | 14 | let cbinfo: &CallbackInfo = &*(cbinfo as *const CallbackInfo); 15 | let args = &*(cbinfo.args as *const v8::FunctionCallbackArguments); 16 | 17 | // TODO: need v8 binding 18 | 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /src/napi_instanceof.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_instanceof( 7 | env: napi_env, 8 | value: napi_value, 9 | constructor: napi_value, 10 | result: *mut bool, 11 | ) -> Result { 12 | let mut env = &mut (env as *mut Env); 13 | let value: v8::Local = transmute(value); 14 | let constructor: v8::Local = transmute(constructor); 15 | // TODO: what is the rusty v8 API 16 | // *result = value.instance_of(constructor); 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /src/napi_delete_property.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_delete_property( 7 | env: napi_env, 8 | value: napi_value, 9 | key: napi_value, 10 | result: *mut bool, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let value: v8::Local = std::mem::transmute(value); 14 | let obj = value.to_object(env.scope).unwrap(); 15 | *result = obj 16 | .delete(env.scope, std::mem::transmute(key)) 17 | .unwrap_or(false); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /testdata/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testdata", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@parcel/css": "^1.2.0", 8 | "@parcel/fs-search": "^2.2.1", 9 | "@parcel/hash": "^2.2.1", 10 | "@parcel/optimizer-image": "^2.2.1", 11 | "@parcel/transformer-js": "^2.2.1", 12 | "@swc/cli": "^0.1.55", 13 | "@swc/core": "^1.2.133", 14 | "dprint-node": "^1.0.5", 15 | "fs-xattr": "^0.4.0", 16 | "skia-canvas": "^0.9.28", 17 | "usb": "^2.0.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/napi_remove_wrap.rs: -------------------------------------------------------------------------------- 1 | use crate::env::{Env, EnvShared}; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_remove_wrap(env: napi_env, value: *mut v8::Value) -> Result { 7 | let mut env = &mut *(env as *mut Env); 8 | let value: v8::Local = std::mem::transmute(value); 9 | let obj = value.to_object(env.scope).unwrap(); 10 | let shared = &*(env.shared as *const EnvShared); 11 | let napi_wrap = v8::Local::new(env.scope, &shared.napi_wrap); 12 | obj.delete_private(env.scope, napi_wrap).unwrap(); 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /src/napi_create_promise.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_promise( 7 | env: napi_env, 8 | deferred: *mut napi_deferred, 9 | promise_out: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let resolver = v8::PromiseResolver::new(env.scope).unwrap(); 13 | let promise: v8::Local = resolver.get_promise(env.scope).into(); 14 | *deferred = std::mem::transmute(resolver); 15 | *promise_out = std::mem::transmute(promise); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /src/napi_set_element.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_set_element( 7 | env: napi_env, 8 | object: napi_value, 9 | index: u32, 10 | value: napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let object: v8::Local = std::mem::transmute(object); 14 | let array = v8::Local::::try_from(object).unwrap(); 15 | let value: v8::Local = std::mem::transmute(value); 16 | array.set_index(env.scope, index, value).unwrap(); 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /src/napi_set_instance_data.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | 4 | #[napi_sym] 5 | fn napi_set_instance_data( 6 | env: napi_env, 7 | data: *mut c_void, 8 | finalize_cb: napi_finalize, 9 | finalize_hint: *mut c_void, 10 | ) -> Result { 11 | let env = &mut *(env as *mut Env); 12 | let shared = env.shared_mut(); 13 | shared.instance_data = data; 14 | shared.data_finalize = if !(finalize_cb as *const c_void).is_null() { 15 | Some(finalize_cb) 16 | } else { 17 | None 18 | }; 19 | shared.data_finalize_hint = finalize_hint; 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /src/napi_get_element.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_element( 7 | env: napi_env, 8 | object: napi_value, 9 | index: u32, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let object: v8::Local = std::mem::transmute(object); 14 | let array = v8::Local::::try_from(object).unwrap(); 15 | let value: v8::Local = array.get_index(env.scope, index).unwrap(); 16 | *result = std::mem::transmute(value); 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /src/napi_is_detached_arraybuffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_is_detached_arraybuffer( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut bool, 10 | ) -> Result { 11 | let mut env = &mut (env as *mut Env); 12 | let value: v8::Local = transmute(value); 13 | let ab = v8::Local::::try_from(value).unwrap(); 14 | // TODO: what is API for checking if ArrayBuffer is detached? 15 | // there's only is_detachable I could find. 16 | *result = false; 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /src/napi_create_bigint_words.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_bigint_words( 7 | env: napi_env, 8 | sign_bit: bool, 9 | words: *const u64, 10 | word_count: usize, 11 | result: *mut napi_value, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | let value: v8::Local = v8::BigInt::new_from_words( 15 | env.scope, 16 | sign_bit, 17 | std::slice::from_raw_parts(words, word_count), 18 | ) 19 | .unwrap() 20 | .into(); 21 | *result = std::mem::transmute(value); 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_create_arraybuffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | use crate::util::get_array_buffer_ptr; 6 | 7 | #[napi_sym] 8 | fn napi_create_arraybuffer( 9 | env: napi_env, 10 | len: usize, 11 | data: *mut *mut u8, 12 | result: *mut napi_value, 13 | ) -> Result { 14 | let mut env = &mut *(env as *mut Env); 15 | let value = v8::ArrayBuffer::new(env.scope, len); 16 | if !data.is_null() { 17 | *data = get_array_buffer_ptr(value); 18 | } 19 | let value: v8::Local = value.into(); 20 | *result = std::mem::transmute(value); 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /src/napi_create_string_latin1.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_string_latin1( 7 | env: napi_env, 8 | string: *const u8, 9 | length: usize, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let string = std::slice::from_raw_parts(string, length); 14 | let v8str = 15 | v8::String::new_from_one_byte(env.scope, string, v8::NewStringType::Normal) 16 | .unwrap(); 17 | let value: v8::Local = v8str.into(); 18 | *result = std::mem::transmute(value); 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /src/napi_create_string_utf16.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_string_utf16( 7 | env: napi_env, 8 | string: *const u16, 9 | length: usize, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let string = std::slice::from_raw_parts(string, length); 14 | let v8str = 15 | v8::String::new_from_two_byte(env.scope, string, v8::NewStringType::Normal) 16 | .unwrap(); 17 | let value: v8::Local = v8str.into(); 18 | *result = std::mem::transmute(value); 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /src/napi_has_named_property.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_has_named_property( 7 | env: napi_env, 8 | value: napi_value, 9 | key: *const c_char, 10 | result: *mut bool, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let value: v8::Local = transmute(value); 14 | let obj = value.to_object(env.scope).unwrap(); 15 | let key = CStr::from_ptr(key).to_str().unwrap(); 16 | let key = v8::String::new(env.scope, key).unwrap(); 17 | *result = obj.has(env.scope, key.into()).unwrap_or(false); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /src/napi_create_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_error( 7 | env: napi_env, 8 | code: napi_value, 9 | msg: napi_value, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | 14 | let code: v8::Local = std::mem::transmute(code); 15 | let msg: v8::Local = std::mem::transmute(msg); 16 | 17 | let msg = msg.to_string(env.scope).unwrap(); 18 | 19 | let error = v8::Exception::error(env.scope, msg); 20 | *result = std::mem::transmute(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_create_threadsafe_function.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | 4 | #[napi_sym] 5 | fn napi_create_threadsafe_function( 6 | env: napi_env, 7 | func: napi_value, 8 | async_resource: napi_value, 9 | async_resource_name: napi_value, 10 | max_queue_size: usize, 11 | initial_thread_count: usize, 12 | thread_finialize_data: *mut c_void, 13 | thread_finalize_cb: napi_finalize, 14 | context: *const c_void, 15 | call_js_cb: napi_threadsafe_function_call_js, 16 | result: *mut napi_threadsafe_function, 17 | ) -> Result { 18 | let env = &mut *(env as *mut Env); 19 | // TODO 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /src/napi_get_arraybuffer_info.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::util::get_array_buffer_ptr; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_get_arraybuffer_info( 8 | env: napi_env, 9 | value: napi_value, 10 | data: *mut *mut u8, 11 | length: *mut usize, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | let value: v8::Local = std::mem::transmute(value); 15 | let buf = v8::Local::::try_from(value).unwrap(); 16 | if !data.is_null() { 17 | *data = get_array_buffer_ptr(buf); 18 | } 19 | *length = buf.byte_length(); 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /src/napi_get_property.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_property( 7 | env: napi_env, 8 | object: napi_value, 9 | key: napi_value, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let object: v8::Local = std::mem::transmute(object); 14 | let object = object.to_object(env.scope).unwrap(); 15 | let key: v8::Local = std::mem::transmute(key); 16 | let value: v8::Local = object.get(env.scope, key).unwrap(); 17 | *result = std::mem::transmute(value); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /src/napi_get_property_names.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_property_names( 7 | env: napi_env, 8 | object: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let object: v8::Local = std::mem::transmute(object); 13 | let array: v8::Local = object 14 | .to_object(env.scope) 15 | .unwrap() 16 | .get_property_names(env.scope) 17 | .unwrap(); 18 | let value: v8::Local = array.into(); 19 | *result = std::mem::transmute(value); 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /src/napi_create_type_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_type_error( 7 | env: napi_env, 8 | code: napi_value, 9 | msg: napi_value, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | 14 | let code: v8::Local = std::mem::transmute(code); 15 | let msg: v8::Local = std::mem::transmute(msg); 16 | 17 | let msg = msg.to_string(env.scope).unwrap(); 18 | 19 | let error = v8::Exception::type_error(env.scope, msg); 20 | *result = std::mem::transmute(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_create_range_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_range_error( 7 | env: napi_env, 8 | code: napi_value, 9 | msg: napi_value, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | 14 | let code: v8::Local = std::mem::transmute(code); 15 | let msg: v8::Local = std::mem::transmute(msg); 16 | 17 | let msg = msg.to_string(env.scope).unwrap(); 18 | 19 | let error = v8::Exception::range_error(env.scope, msg); 20 | *result = std::mem::transmute(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_set_property.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_set_property( 7 | env: napi_env, 8 | object: napi_value, 9 | property: napi_value, 10 | value: napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let object: v8::Local = std::mem::transmute(object); 14 | let object = object.to_object(env.scope).unwrap(); 15 | let property: v8::Local = std::mem::transmute(property); 16 | let value: v8::Local = std::mem::transmute(value); 17 | object.set(env.scope, property, value).unwrap(); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /src/napi_set_named_property.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_set_named_property( 7 | env: napi_env, 8 | object: napi_value, 9 | name: *const c_char, 10 | value: napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let name = CStr::from_ptr(name).to_str().unwrap(); 14 | let object: v8::Local = std::mem::transmute(object); 15 | let value: v8::Local = std::mem::transmute(value); 16 | let name = v8::String::new(env.scope, name).unwrap(); 17 | object.set(env.scope, name.into(), value).unwrap(); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /src/napi_throw_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_throw_error( 7 | env: napi_env, 8 | code: *const c_char, 9 | msg: *const c_char, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | 13 | // let code = CStr::from_ptr(code).to_str().unwrap(); 14 | let msg = CStr::from_ptr(msg).to_str().unwrap(); 15 | 16 | // let code = v8::String::new(env.scope, code).unwrap(); 17 | let msg = v8::String::new(env.scope, msg).unwrap(); 18 | 19 | let error = v8::Exception::error(env.scope, msg); 20 | env.scope.throw_exception(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/node_api_create_syntax_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn node_api_create_syntax_error( 7 | env: napi_env, 8 | code: napi_value, 9 | msg: napi_value, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | 14 | let code: v8::Local = std::mem::transmute(code); 15 | let msg: v8::Local = std::mem::transmute(msg); 16 | 17 | let msg = msg.to_string(env.scope).unwrap(); 18 | 19 | let error = v8::Exception::syntax_error(env.scope, msg); 20 | *result = std::mem::transmute(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_throw_type_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_throw_type_error( 7 | env: napi_env, 8 | code: *const c_char, 9 | msg: *const c_char, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | 13 | // let code = CStr::from_ptr(code).to_str().unwrap(); 14 | let msg = CStr::from_ptr(msg).to_str().unwrap(); 15 | 16 | // let code = v8::String::new(env.scope, code).unwrap(); 17 | let msg = v8::String::new(env.scope, msg).unwrap(); 18 | 19 | let error = v8::Exception::type_error(env.scope, msg); 20 | env.scope.throw_exception(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_wrap.rs: -------------------------------------------------------------------------------- 1 | use crate::env::{Env, EnvShared}; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_wrap( 7 | env: napi_env, 8 | value: *mut v8::Value, 9 | native_object: *mut c_void, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let obj = value.to_object(env.scope).unwrap(); 14 | let shared = &*(env.shared as *const EnvShared); 15 | let napi_wrap = v8::Local::new(env.scope, &shared.napi_wrap); 16 | let ext = v8::External::new(env.scope, native_object); 17 | obj.set_private(env.scope, napi_wrap, ext.into()); 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /src/napi_get_node_version.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | thread_local! { 4 | static NODE_VERSION: napi_node_version = { 5 | let release = std::ffi::CString::new("Deno N-API").unwrap(); 6 | let release = release.as_ptr(); 7 | std::mem::forget(release); 8 | napi_node_version { 9 | major: 17, 10 | minor: 4, 11 | patch: 0, 12 | release: release, 13 | } 14 | } 15 | } 16 | 17 | #[napi_sym] 18 | fn napi_get_node_version( 19 | _: napi_env, 20 | result: *mut *const napi_node_version, 21 | ) -> Result { 22 | NODE_VERSION.with(|version| { 23 | *result = version as *const napi_node_version; 24 | }); 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /src/napi_throw_range_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_throw_range_error( 7 | env: napi_env, 8 | code: *const c_char, 9 | msg: *const c_char, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | 13 | // let code = CStr::from_ptr(code).to_str().unwrap(); 14 | let msg = CStr::from_ptr(msg).to_str().unwrap(); 15 | 16 | // let code = v8::String::new(env.scope, code).unwrap(); 17 | let msg = v8::String::new(env.scope, msg).unwrap(); 18 | 19 | let error = v8::Exception::range_error(env.scope, msg); 20 | env.scope.throw_exception(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_create_buffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | use crate::util::get_array_buffer_ptr; 6 | 7 | #[napi_sym] 8 | fn napi_create_buffer( 9 | env: napi_env, 10 | len: usize, 11 | data: *mut *mut u8, 12 | result: *mut napi_value, 13 | ) -> Result { 14 | let mut env = &mut *(env as *mut Env); 15 | let value = v8::ArrayBuffer::new(env.scope, len); 16 | if !data.is_null() { 17 | *data = get_array_buffer_ptr(value); 18 | } 19 | let value = v8::Uint8Array::new(env.scope, value, 0, len).unwrap(); 20 | let value: v8::Local = value.into(); 21 | *result = std::mem::transmute(value); 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/node_api_throw_syntax_error.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn node_api_throw_syntax_error( 7 | env: napi_env, 8 | code: *const c_char, 9 | msg: *const c_char, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | 13 | // let code = CStr::from_ptr(code).to_str().unwrap(); 14 | let msg = CStr::from_ptr(msg).to_str().unwrap(); 15 | 16 | // let code = v8::String::new(env.scope, code).unwrap(); 17 | let msg = v8::String::new(env.scope, msg).unwrap(); 18 | 19 | let error = v8::Exception::syntax_error(env.scope, msg); 20 | env.scope.throw_exception(error); 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use deno_core::v8; 2 | use std::cell::Cell; 3 | 4 | unsafe fn get_backing_store_slice( 5 | backing_store: &v8::SharedRef, 6 | byte_offset: usize, 7 | byte_length: usize, 8 | ) -> &mut [u8] { 9 | let cells: *const [Cell] = 10 | &backing_store[byte_offset..byte_offset + byte_length]; 11 | let mut bytes = cells as *mut [u8]; 12 | &mut *bytes 13 | } 14 | 15 | pub fn get_array_buffer_ptr(ab: v8::Local) -> *mut u8 { 16 | let backing_store = ab.get_backing_store(); 17 | let byte_length = ab.byte_length(); 18 | let mut slice = 19 | unsafe { get_backing_store_slice(&backing_store, 0, byte_length) }; 20 | slice.as_mut_ptr() 21 | } 22 | -------------------------------------------------------------------------------- /src/napi_create_symbol.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_symbol( 7 | env: napi_env, 8 | description: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let description = match result.is_null() { 13 | true => None, 14 | false => Some( 15 | std::mem::transmute::>(description) 16 | .to_string(env.scope) 17 | .unwrap(), 18 | ), 19 | }; 20 | let sym = v8::Symbol::new(env.scope, description); 21 | let local: v8::Local = sym.into(); 22 | *result = transmute(local); 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /src/napi_unwrap.rs: -------------------------------------------------------------------------------- 1 | use crate::env::{Env, EnvShared}; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_unwrap( 7 | env: napi_env, 8 | value: napi_value, 9 | result: *mut *mut c_void, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | let value: v8::Local = std::mem::transmute(value); 13 | let obj = value.to_object(env.scope).unwrap(); 14 | let shared = &*(env.shared as *const EnvShared); 15 | let napi_wrap = v8::Local::new(env.scope, &shared.napi_wrap); 16 | let ext = obj.get_private(env.scope, napi_wrap).unwrap(); 17 | let ext = v8::Local::::try_from(ext).unwrap(); 18 | *result = ext.value(); 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /src/napi_get_named_property.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_named_property( 7 | env: napi_env, 8 | object: napi_value, 9 | utf8_name: *const c_char, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | let object: v8::Local = std::mem::transmute(object); 14 | let utf8_name = std::ffi::CStr::from_ptr(utf8_name); 15 | let name = v8::String::new(env.scope, &utf8_name.to_string_lossy()).unwrap(); 16 | let value: v8::Local = object 17 | .to_object(env.scope) 18 | .unwrap() 19 | .get(env.scope, name.into()) 20 | .unwrap(); 21 | *result = std::mem::transmute(value); 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/napi_create_string_utf8.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_string_utf8( 7 | env: napi_env, 8 | string: *const u8, 9 | length: isize, 10 | result: *mut napi_value, 11 | ) -> Result { 12 | let mut env = &mut *(env as *mut Env); 13 | 14 | let string = if length == -1 { 15 | std::ffi::CStr::from_ptr(string as *const _) 16 | .to_str() 17 | .unwrap() 18 | } else { 19 | let string = std::slice::from_raw_parts(string, length as usize); 20 | std::str::from_utf8(string).unwrap() 21 | }; 22 | let v8str = v8::String::new(env.scope, string).unwrap(); 23 | let value: v8::Local = v8str.into(); 24 | *result = std::mem::transmute(value); 25 | 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /src/napi_create_buffer_copy.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | use crate::util::get_array_buffer_ptr; 6 | 7 | #[napi_sym] 8 | fn napi_create_buffer_copy( 9 | env: napi_env, 10 | len: usize, 11 | data: *mut u8, 12 | result_data: *mut *mut u8, 13 | result: *mut napi_value, 14 | ) -> Result { 15 | let mut env = &mut *(env as *mut Env); 16 | let value = v8::ArrayBuffer::new(env.scope, len); 17 | let ptr = get_array_buffer_ptr(value); 18 | std::ptr::copy(data, ptr, len); 19 | if !result_data.is_null() { 20 | *result_data = ptr; 21 | } 22 | let value = v8::Uint8Array::new(env.scope, value, 0, len).unwrap(); 23 | let value: v8::Local = value.into(); 24 | *result = std::mem::transmute(value); 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /src/napi_new_instance.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_new_instance( 7 | env: napi_env, 8 | constructor: napi_value, 9 | argc: usize, 10 | argv: *const napi_value, 11 | result: *mut napi_value, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | let constructor: v8::Local = std::mem::transmute(constructor); 15 | let constructor = v8::Local::::try_from(constructor).unwrap(); 16 | let args: &[v8::Local] = 17 | std::mem::transmute(std::slice::from_raw_parts(argv, argc)); 18 | let inst = constructor.new_instance(env.scope, args).unwrap(); 19 | let value: v8::Local = inst.into(); 20 | *result = std::mem::transmute(value); 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /src/napi_get_buffer_info.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::util::get_array_buffer_ptr; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_get_buffer_info( 8 | env: napi_env, 9 | value: napi_value, 10 | data: *mut *mut u8, 11 | length: *mut usize, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | let value: v8::Local = std::mem::transmute(value); 15 | let buf = v8::Local::::try_from(value).unwrap(); 16 | let buffer_name = v8::String::new(env.scope, "buffer").unwrap(); 17 | let abuf = v8::Local::::try_from( 18 | buf.get(env.scope, buffer_name.into()).unwrap(), 19 | ) 20 | .unwrap(); 21 | if !data.is_null() { 22 | *data = get_array_buffer_ptr(abuf); 23 | } 24 | *length = abuf.byte_length(); 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /src/napi_call_function.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_call_function( 7 | env: napi_env, 8 | recv: napi_value, 9 | func: napi_value, 10 | argc: usize, 11 | argv: *const napi_value, 12 | result: *mut napi_value, 13 | ) -> Result { 14 | let mut env = &mut *(env as *mut Env); 15 | let recv: v8::Local = std::mem::transmute(recv); 16 | let func: v8::Local = std::mem::transmute(func); 17 | let func = v8::Local::::try_from(func).unwrap(); 18 | let args: &[v8::Local] = 19 | std::mem::transmute(std::slice::from_raw_parts(argv, argc)); 20 | let ret = func.call(env.scope, recv, args).unwrap(); 21 | let value: v8::Local = ret.into(); 22 | *result = std::mem::transmute(value); 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /src/napi_create_function.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::function::create_function; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_create_function( 8 | env: &mut Env, 9 | name: *const u8, 10 | length: isize, 11 | cb: napi_callback, 12 | cb_info: napi_callback_info, 13 | result: *mut napi_value, 14 | ) -> Result { 15 | let mut env = &mut *(env as *mut Env); 16 | let name = if length == -1 { 17 | std::ffi::CStr::from_ptr(name as *const _).to_str().unwrap() 18 | } else { 19 | let name = std::slice::from_raw_parts(name, length as usize); 20 | std::str::from_utf8(name).unwrap() 21 | }; 22 | let function = create_function(env, Some(name), cb, cb_info); 23 | let value: v8::Local = function.into(); 24 | *result = std::mem::transmute(value); 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /src/napi_get_dataview_info.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::util::get_array_buffer_ptr; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_get_dataview_info( 8 | env: napi_env, 9 | value: napi_value, 10 | data: *mut *mut u8, 11 | length: *mut usize, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | let value: v8::Local = std::mem::transmute(value); 15 | let buf = v8::Local::::try_from(value).unwrap(); 16 | let buffer_name = v8::String::new(env.scope, "buffer").unwrap(); 17 | let abuf = v8::Local::::try_from( 18 | buf.get(env.scope, buffer_name.into()).unwrap(), 19 | ) 20 | .unwrap(); 21 | if !data.is_null() { 22 | *data = get_array_buffer_ptr(abuf); 23 | } 24 | *length = abuf.byte_length(); 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /src/napi_get_value_bigint_words.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_bigint_words( 7 | env: napi_env, 8 | value: napi_value, 9 | sign_bit: *mut i32, 10 | size: *mut usize, 11 | out_words: *mut u64, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | 15 | let value: v8::Local = std::mem::transmute(value); 16 | let bigint = value.to_big_int(env.scope).unwrap(); 17 | 18 | let out_words = std::slice::from_raw_parts_mut(out_words, *size); 19 | let mut words = Vec::with_capacity(bigint.word_count()); 20 | let (sign, _) = bigint.to_words_array(words.as_mut_slice()); 21 | *sign_bit = sign as i32; 22 | 23 | for (i, word) in out_words.iter_mut().enumerate() { 24 | *word = words[i]; 25 | } 26 | 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /src/napi_get_typedarray_info.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::util::get_array_buffer_ptr; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_get_typedarray_info( 8 | env: napi_env, 9 | value: napi_value, 10 | data: *mut *mut u8, 11 | length: *mut usize, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | let value: v8::Local = std::mem::transmute(value); 15 | let buf = v8::Local::::try_from(value).unwrap(); 16 | let buffer_name = v8::String::new(env.scope, "buffer").unwrap(); 17 | let abuf = v8::Local::::try_from( 18 | buf.get(env.scope, buffer_name.into()).unwrap(), 19 | ) 20 | .unwrap(); 21 | if !data.is_null() { 22 | *data = get_array_buffer_ptr(abuf); 23 | } 24 | *length = abuf.byte_length(); 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /src/napi_run_script.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_run_script( 7 | env: napi_env, 8 | script: napi_value, 9 | result: *mut napi_value, 10 | ) -> Result { 11 | let mut env = &mut *(env as *mut Env); 12 | 13 | let script: v8::Local = std::mem::transmute(script); 14 | if !script.is_string() { 15 | return Err(Error::StringExpected); 16 | } 17 | let script = script.to_string(env.scope).unwrap(); 18 | 19 | let script = v8::Script::compile(env.scope, script, None); 20 | if script.is_none() { 21 | return Err(Error::GenericFailure); 22 | } 23 | let script = script.unwrap(); 24 | let rv = script.run(env.scope); 25 | 26 | if let Some(rv) = rv { 27 | *result = std::mem::transmute(rv); 28 | } else { 29 | return Err(Error::GenericFailure); 30 | } 31 | 32 | Ok(()) 33 | } 34 | -------------------------------------------------------------------------------- /src/napi_module_register.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | use std::cell::RefCell; 3 | use std::thread_local; 4 | 5 | thread_local! { 6 | pub static MODULE: RefCell> = RefCell::new(None); 7 | } 8 | 9 | type napi_addon_register_func = 10 | extern "C" fn(env: napi_env, exports: napi_value) -> napi_value; 11 | 12 | #[repr(C)] 13 | #[derive(Debug, Clone)] 14 | pub struct NapiModule { 15 | pub nm_version: i32, 16 | pub nm_flags: u32, 17 | nm_filename: *const c_char, 18 | pub nm_register_func: napi_addon_register_func, 19 | nm_modname: *const c_char, 20 | nm_priv: *mut c_void, 21 | reserved: [*mut c_void; 4], 22 | } 23 | 24 | #[napi_sym] 25 | fn napi_module_register(module: *const NapiModule) -> Result { 26 | MODULE.with(|cell| { 27 | let mut slot = cell.borrow_mut(); 28 | assert!(slot.is_none()); 29 | slot.replace(module); 30 | }); 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /example_module/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate napi_derive; 3 | 4 | use futures::prelude::*; 5 | use napi::bindgen_prelude::*; 6 | use tokio::fs; 7 | 8 | #[napi] 9 | fn hello(name: String) -> String { 10 | println!("Hello, {}!", name); 11 | String::from("World") 12 | } 13 | 14 | #[napi] 15 | fn add(a: i32, b: i32) -> i32 { 16 | a + b 17 | } 18 | 19 | #[napi(js_name = "Point")] 20 | pub struct Point { 21 | pub x: i32, 22 | pub y: i32, 23 | } 24 | 25 | #[napi] 26 | impl Point { 27 | #[napi(constructor)] 28 | pub fn new(x: i32, y: i32) -> Point { 29 | Point { x, y } 30 | } 31 | } 32 | 33 | #[napi] 34 | async fn read_file_async(path: String) -> Result { 35 | fs::read(path) 36 | .map(|r| match r { 37 | Ok(content) => Ok(content.into()), 38 | Err(e) => Err(Error::new( 39 | Status::GenericFailure, 40 | format!("failed to read file, {}", e), 41 | )), 42 | }) 43 | .await 44 | } 45 | -------------------------------------------------------------------------------- /src/napi_queue_async_work.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::napi_create_async_work::AsyncWork; 4 | use std::sync::Arc; 5 | use std::sync::Mutex; 6 | 7 | #[napi_sym] 8 | fn napi_queue_async_work(env: napi_env, work: napi_async_work) -> Result { 9 | let env_ptr = &mut *(env as *mut Env); 10 | let work = transmute::>(work); 11 | 12 | let data = Arc::new(Mutex::new(work)); 13 | let (tx, rx) = std::sync::mpsc::channel::<()>(); 14 | 15 | let shared = Arc::clone(&data); 16 | tokio::task::spawn_blocking(move || { 17 | let env = transmute(env_ptr); 18 | let work = shared.lock().unwrap(); 19 | (work.execute)(env, work.data); 20 | tx.send(()).unwrap(); 21 | }); 22 | 23 | // Note: Must be called from the loop thread. 24 | // TODO: Don't block the loop thread. 25 | rx.recv().unwrap(); 26 | let work = data.lock().unwrap(); 27 | (work.complete)(env, napi_ok, work.data); 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /test/parcel_transformer.js: -------------------------------------------------------------------------------- 1 | const lib = dlopen( 2 | "./testdata/node_modules/@parcel/transformer-js/parcel-swc.darwin-arm64.node", 3 | ); 4 | 5 | const { code } = lib.transform({ 6 | filename: "main.js", 7 | code: Deno.core.encode("const x = 1;"), 8 | module_id: "1", 9 | project_root: ".", 10 | replace_env: false, 11 | inline_fs: false, 12 | insert_node_globals: false, 13 | is_browser: true, 14 | is_worker: false, 15 | env: {}, 16 | is_type_script: false, 17 | is_jsx: false, 18 | // jsx_pragma: undefined, 19 | // jsx_pragma_frag: config?.pragmaFrag, 20 | automatic_jsx_runtime: false, 21 | // jsx_import_source: config?.jsxImportSource, 22 | is_development: false, 23 | react_refresh: false, 24 | decorators: false, 25 | targets: null, 26 | source_maps: false, 27 | scope_hoist: false, 28 | source_type: "Module", 29 | supports_module_workers: false, 30 | is_library: true, 31 | is_esm_output: false, 32 | trace_bailouts: true, 33 | }); 34 | 35 | print(Deno.core.decode(code)); 36 | -------------------------------------------------------------------------------- /src/napi_fatal_error.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | 3 | #[no_mangle] 4 | pub unsafe extern "C" fn napi_fatal_error( 5 | location: *const c_char, 6 | location_len: isize, 7 | message: *const c_char, 8 | message_len: isize, 9 | ) -> ! { 10 | let location = if location.is_null() { 11 | None 12 | } else { 13 | Some(if location_len < 0 { 14 | std::ffi::CStr::from_ptr(location).to_str().unwrap() 15 | } else { 16 | let slice = std::slice::from_raw_parts( 17 | location as *const u8, 18 | location_len as usize, 19 | ); 20 | std::str::from_utf8(slice).unwrap() 21 | }) 22 | }; 23 | let message = if message_len < 0 { 24 | std::ffi::CStr::from_ptr(message).to_str().unwrap() 25 | } else { 26 | let slice = 27 | std::slice::from_raw_parts(message as *const u8, message_len as usize); 28 | std::str::from_utf8(slice).unwrap() 29 | }; 30 | panic!( 31 | "Fatal exception triggered by napi_fatal_error!\nLocation: {:?}\n{}", 32 | location, message 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /src/napi_create_external_buffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_external_buffer( 7 | env: napi_env, 8 | byte_length: isize, 9 | data: *mut c_void, 10 | finalize_cb: napi_finalize, 11 | finalize_hint: *mut c_void, 12 | result: *mut napi_value, 13 | ) -> Result { 14 | let mut env = &mut *(env as *mut Env); 15 | let slice = if byte_length == -1 { 16 | std::ffi::CStr::from_ptr(data as *const _).to_bytes() 17 | } else { 18 | std::slice::from_raw_parts(data as *mut u8, byte_length as usize) 19 | }; 20 | // TODO: make this not copy the slice 21 | // TODO: finalization 22 | let store = v8::ArrayBuffer::new_backing_store_from_boxed_slice( 23 | slice.to_vec().into_boxed_slice(), 24 | ); 25 | let ab = v8::ArrayBuffer::with_backing_store(env.scope, &store.make_shared()); 26 | let value = v8::Uint8Array::new(env.scope, ab, 0, slice.len()).unwrap(); 27 | let value: v8::Local = value.into(); 28 | *result = std::mem::transmute(value); 29 | Ok(()) 30 | } 31 | -------------------------------------------------------------------------------- /test/parcel_css.js: -------------------------------------------------------------------------------- 1 | const lib = dlopen( 2 | "./testdata/node_modules/@parcel/css-darwin-arm64/parcel-css.darwin-arm64.node", 3 | ); 4 | 5 | // Test case from @parcel/css 6 | // https://github.com/parcel-bundler/parcel-css/blob/1e89b39cd922d2e577c8e39611f484a525fd8937/test.js 7 | const result = lib.transform({ 8 | filename: "test.css", 9 | minify: false, 10 | targets: { 11 | safari: 4 << 16, 12 | firefox: 3 << 16 | 5 << 8, 13 | opera: 10 << 16 | 5 << 8, 14 | }, 15 | code: Deno.core.encode(` 16 | @import "foo.css"; 17 | @import "bar.css" print; 18 | @import "baz.css" supports(display: grid); 19 | .foo { 20 | composes: bar; 21 | composes: baz from "baz.css"; 22 | color: pink; 23 | } 24 | .bar { 25 | color: red; 26 | background: url(test.jpg); 27 | } 28 | `), 29 | drafts: { 30 | nesting: true, 31 | }, 32 | cssModules: true, 33 | analyzeDependencies: true, 34 | }); 35 | 36 | print(Deno.core.decode(result.code)); 37 | print(JSON.stringify(result.exports)); 38 | print(JSON.stringify(result.dependencies)); 39 | -------------------------------------------------------------------------------- /src/napi_get_value_string_utf16.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_string_utf16( 7 | env: napi_env, 8 | value: napi_value, 9 | buf: *mut u16, 10 | bufsize: usize, 11 | result: *mut usize, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | 15 | let value: v8::Local = std::mem::transmute(value); 16 | 17 | if !value.is_string() && !value.is_string_object() { 18 | return Err(Error::StringExpected); 19 | } 20 | 21 | let v8str = value.to_string(env.scope).unwrap(); 22 | let string_len = v8str.length(); 23 | 24 | if buf.is_null() { 25 | *result = string_len; 26 | } else if bufsize != 0 { 27 | let buffer = std::slice::from_raw_parts_mut(buf, bufsize - 1); 28 | let copied = 29 | v8str.write(env.scope, buffer, 0, v8::WriteOptions::NO_NULL_TERMINATION); 30 | buf.offset(copied as isize).write(0); 31 | if !result.is_null() { 32 | *result = copied; 33 | } 34 | } else if !result.is_null() { 35 | *result = string_len; 36 | } 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /src/napi_create_async_work.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[repr(C)] 6 | pub struct AsyncWork { 7 | pub data: *mut c_void, 8 | pub execute: napi_async_execute_callback, 9 | pub complete: napi_async_complete_callback, 10 | } 11 | 12 | unsafe impl Send for AsyncWork {} 13 | unsafe impl Sync for AsyncWork {} 14 | 15 | #[napi_sym] 16 | fn napi_create_async_work( 17 | env: napi_env, 18 | async_resource: napi_value, 19 | async_resource_name: napi_value, 20 | execute: napi_async_execute_callback, 21 | complete: napi_async_complete_callback, 22 | data: *mut c_void, 23 | result: *mut napi_async_work, 24 | ) -> Result { 25 | let env = &mut *(env as *mut Env); 26 | let resource = if async_resource.is_null() { 27 | v8::Object::new(env.scope) 28 | } else { 29 | transmute(async_resource) 30 | }; 31 | 32 | let resource_name: v8::Local = transmute(async_resource_name); 33 | let mut work = AsyncWork { 34 | data, 35 | execute, 36 | complete, 37 | }; 38 | *result = transmute::, _>(Box::new(work)); 39 | Ok(()) 40 | } 41 | -------------------------------------------------------------------------------- /proc_macro/lib.rs: -------------------------------------------------------------------------------- 1 | use proc_macro::TokenStream; 2 | use quote::quote; 3 | 4 | #[proc_macro_attribute] 5 | pub fn napi_sym(_attr: TokenStream, item: TokenStream) -> TokenStream { 6 | let func = syn::parse::(item).expect("expected a function"); 7 | 8 | let name = &func.sig.ident; 9 | let block = &func.block; 10 | // TODO(@littledivy): make first argument &'a mut env::Env? 11 | let inputs = &func.sig.inputs; 12 | let output = &func.sig.output; 13 | let ret_ty = match output { 14 | syn::ReturnType::Default => panic!("expected a return type"), 15 | syn::ReturnType::Type(_, ty) => quote! { #ty }, 16 | }; 17 | TokenStream::from(quote! { 18 | #[no_mangle] 19 | pub unsafe extern "C" fn #name(#inputs) -> napi_status { 20 | let mut inner = || -> #ret_ty { 21 | let result = #block; 22 | result 23 | }; 24 | let result = inner(); 25 | match result { 26 | Ok(_) => napi_ok, 27 | Err(err) => { 28 | let status: napi_status = err.into(); 29 | status 30 | }, 31 | } 32 | } 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 the napi-rusty-v8 authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/napi_get_value_string_latin1.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_string_latin1( 7 | env: napi_env, 8 | value: napi_value, 9 | buf: *mut u8, 10 | bufsize: usize, 11 | result: *mut usize, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | 15 | let value: v8::Local = std::mem::transmute(value); 16 | 17 | if !value.is_string() && !value.is_string_object() { 18 | return Err(Error::StringExpected); 19 | } 20 | 21 | let v8str = value.to_string(env.scope).unwrap(); 22 | let string_len = v8str.utf8_length(env.scope); 23 | 24 | if buf.is_null() { 25 | *result = string_len; 26 | } else if bufsize != 0 { 27 | let buffer = std::slice::from_raw_parts_mut(buf, bufsize - 1); 28 | let copied = v8str.write_one_byte( 29 | env.scope, 30 | buffer, 31 | 0, 32 | v8::WriteOptions::NO_NULL_TERMINATION, 33 | ); 34 | buf.offset(copied as isize).write(0); 35 | if !result.is_null() { 36 | *result = copied; 37 | } 38 | } else if !result.is_null() { 39 | *result = string_len; 40 | } 41 | 42 | Ok(()) 43 | } 44 | -------------------------------------------------------------------------------- /src/napi_define_properties.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::function::create_function; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_define_properties( 8 | env: napi_env, 9 | obj: napi_value, 10 | property_count: usize, 11 | properties: *const napi_property_descriptor, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | 15 | let object: v8::Local = std::mem::transmute(obj); 16 | let properties = std::slice::from_raw_parts(properties, property_count); 17 | 18 | for property in properties { 19 | let name_str = CStr::from_ptr(property.utf8name).to_str().unwrap(); 20 | let name = v8::String::new(env.scope, name_str).unwrap(); 21 | 22 | let method_ptr: *mut c_void = std::mem::transmute(property.method); 23 | 24 | if !method_ptr.is_null() { 25 | let function: v8::Local = { 26 | let function = 27 | create_function(env, Some(name_str), property.method, property.data); 28 | let value: v8::Local = function.into(); 29 | std::mem::transmute(value) 30 | }; 31 | object.set(env.scope, name.into(), function).unwrap(); 32 | } 33 | } 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /src/napi_get_cb_info.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::function::CallbackInfo; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_get_cb_info( 8 | env: napi_env, 9 | cbinfo: napi_callback_info, 10 | argc: *mut i32, 11 | argv: *mut napi_value, 12 | this_arg: *mut napi_value, 13 | cb_data: *mut *mut c_void, 14 | ) -> Result { 15 | let mut env = &mut *(env as *mut Env); 16 | 17 | let cbinfo: &CallbackInfo = &*(cbinfo as *const CallbackInfo); 18 | let args = &*(cbinfo.args as *const v8::FunctionCallbackArguments); 19 | 20 | if !cb_data.is_null() { 21 | *cb_data = cbinfo.cb_info; 22 | } 23 | 24 | if !this_arg.is_null() { 25 | let mut this: v8::Local = args.this().into(); 26 | *this_arg = std::mem::transmute(this); 27 | } 28 | 29 | let len = args.length(); 30 | let mut v_argc = len; 31 | if !argc.is_null() { 32 | v_argc = *argc; 33 | *argc = len; 34 | } 35 | 36 | if !argv.is_null() { 37 | let mut v_argv = std::slice::from_raw_parts_mut(argv, v_argc as usize); 38 | for i in 0..v_argc { 39 | let mut arg = args.get(i); 40 | v_argv[i as usize] = std::mem::transmute(arg); 41 | } 42 | } 43 | 44 | Ok(()) 45 | } 46 | -------------------------------------------------------------------------------- /src/napi_get_value_string_utf8.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_get_value_string_utf8( 7 | env: napi_env, 8 | value: napi_value, 9 | buf: *mut u8, 10 | bufsize: usize, 11 | result: *mut usize, 12 | ) -> Result { 13 | let mut env = &mut *(env as *mut Env); 14 | 15 | let value: v8::Local = std::mem::transmute(value); 16 | 17 | if !value.is_string() && !value.is_string_object() { 18 | return Err(Error::StringExpected); 19 | } 20 | 21 | let v8str = value.to_string(env.scope).unwrap(); 22 | let string_len = v8str.utf8_length(env.scope); 23 | 24 | if buf.is_null() { 25 | *result = string_len; 26 | } else if bufsize != 0 { 27 | let buffer = std::slice::from_raw_parts_mut(buf, bufsize - 1); 28 | let copied = v8str.write_utf8( 29 | env.scope, 30 | buffer, 31 | None, 32 | v8::WriteOptions::NO_NULL_TERMINATION 33 | | v8::WriteOptions::REPLACE_INVALID_UTF8, 34 | ); 35 | buf.offset(copied as isize).write(0); 36 | if !result.is_null() { 37 | *result = copied; 38 | } 39 | } else if !result.is_null() { 40 | *result = string_len; 41 | } 42 | 43 | Ok(()) 44 | } 45 | -------------------------------------------------------------------------------- /src/napi_create_dataview.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | use crate::util::get_array_buffer_ptr; 6 | 7 | #[napi_sym] 8 | fn napi_create_dataview( 9 | env: napi_env, 10 | len: usize, 11 | data: *mut *mut u8, 12 | byte_offset: usize, 13 | result: *mut napi_value, 14 | ) -> Result { 15 | let mut env = &mut *(env as *mut Env); 16 | let value = v8::ArrayBuffer::new(env.scope, len); 17 | if !data.is_null() { 18 | *data = get_array_buffer_ptr(value); 19 | } 20 | let context = env.scope.get_current_context(); 21 | let global = context.global(env.scope); 22 | let data_view_name = v8::String::new(env.scope, "DataView").unwrap(); 23 | let data_view = global.get(env.scope, data_view_name.into()).unwrap(); 24 | let data_view = v8::Local::::try_from(data_view).unwrap(); 25 | let byte_offset = v8::Number::new(env.scope, byte_offset as f64); 26 | let byte_length = v8::Number::new(env.scope, len as f64); 27 | let value = data_view 28 | .new_instance( 29 | env.scope, 30 | &[value.into(), byte_offset.into(), byte_length.into()], 31 | ) 32 | .unwrap(); 33 | let value: v8::Local = value.into(); 34 | *result = std::mem::transmute(value); 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /src/napi_typeof.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | pub fn get_value_type(value: v8::Local) -> Option { 6 | if value.is_undefined() { 7 | return Some(napi_undefined); 8 | } else if value.is_null() { 9 | return Some(napi_null); 10 | } else if value.is_external() { 11 | return Some(napi_external); 12 | } else if value.is_boolean() { 13 | return Some(napi_boolean); 14 | } else if value.is_number() { 15 | return Some(napi_number); 16 | } else if value.is_big_int() { 17 | return Some(napi_bigint); 18 | } else if value.is_string() { 19 | return Some(napi_string); 20 | } else if value.is_symbol() { 21 | return Some(napi_symbol); 22 | } else if value.is_function() { 23 | return Some(napi_function); 24 | } else if value.is_object() { 25 | return Some(napi_object); 26 | } else { 27 | return None; 28 | } 29 | } 30 | 31 | #[napi_sym] 32 | fn napi_typeof( 33 | env: napi_env, 34 | value: napi_value, 35 | result: *mut napi_valuetype, 36 | ) -> Result { 37 | let mut env = &mut *(env as *mut Env); 38 | if value.is_null() { 39 | *result = napi_undefined; 40 | return Ok(()); 41 | } 42 | let value: v8::Local = std::mem::transmute(value); 43 | let ty = get_value_type(value); 44 | if let Some(ty) = ty { 45 | *result = ty; 46 | Ok(()) 47 | } else { 48 | return Err(Error::InvalidArg); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/napi_create_external_arraybuffer.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | use deno_core::v8::BackingStore; 5 | use deno_core::v8::UniqueRef; 6 | 7 | pub type BackingStoreDeleterCallback = unsafe extern "C" fn( 8 | data: *mut c_void, 9 | byte_length: usize, 10 | deleter_data: *mut c_void, 11 | ); 12 | extern "C" { 13 | fn v8__ArrayBuffer__NewBackingStore__with_data( 14 | data: *mut c_void, 15 | byte_length: usize, 16 | deleter: BackingStoreDeleterCallback, 17 | deleter_data: *mut c_void, 18 | ) -> *mut BackingStore; 19 | } 20 | 21 | pub unsafe extern "C" fn backing_store_deleter_callback( 22 | data: *mut c_void, 23 | byte_length: usize, 24 | _deleter_data: *mut c_void, 25 | ) { 26 | let slice_ptr = ptr::slice_from_raw_parts_mut(data as *mut u8, byte_length); 27 | let b = Box::from_raw(slice_ptr); 28 | drop(b); 29 | } 30 | 31 | #[napi_sym] 32 | fn napi_create_external_arraybuffer( 33 | env: napi_env, 34 | data: *mut c_void, 35 | byte_length: usize, 36 | finalize_cb: napi_finalize, 37 | finalize_hint: *mut c_void, 38 | result: *mut napi_value, 39 | ) -> Result { 40 | let mut env = &mut *(env as *mut Env); 41 | let slice = std::slice::from_raw_parts(data as *mut u8, byte_length); 42 | // TODO: finalization 43 | let store: UniqueRef = 44 | std::mem::transmute(v8__ArrayBuffer__NewBackingStore__with_data( 45 | data, 46 | byte_length, 47 | backing_store_deleter_callback, 48 | finalize_hint, 49 | )); 50 | 51 | let ab = v8::ArrayBuffer::with_backing_store(env.scope, &store.make_shared()); 52 | let value: v8::Local = ab.into(); 53 | *result = std::mem::transmute(value); 54 | Ok(()) 55 | } 56 | -------------------------------------------------------------------------------- /src/env.rs: -------------------------------------------------------------------------------- 1 | use crate::ffi::*; 2 | use deno_core::v8; 3 | 4 | #[repr(C)] 5 | #[derive(Debug)] 6 | /// Env that is shared between all contexts in same native module. 7 | pub struct EnvShared { 8 | pub instance_data: *mut c_void, 9 | pub data_finalize: Option, 10 | pub data_finalize_hint: *mut c_void, 11 | pub napi_wrap: v8::Global, 12 | pub finalize: Option, 13 | pub finalize_hint: *mut c_void, 14 | pub filename: *const c_char, 15 | } 16 | 17 | impl EnvShared { 18 | pub fn new(napi_wrap: v8::Global) -> Self { 19 | Self { 20 | instance_data: std::ptr::null_mut(), 21 | data_finalize: None, 22 | data_finalize_hint: std::ptr::null_mut(), 23 | napi_wrap, 24 | finalize: None, 25 | finalize_hint: std::ptr::null_mut(), 26 | filename: std::ptr::null(), 27 | } 28 | } 29 | } 30 | 31 | #[repr(C)] 32 | #[derive(Debug)] 33 | pub struct Env<'a, 'b, 'c> { 34 | pub scope: &'a mut v8::ContextScope<'b, v8::HandleScope<'c>>, 35 | pub open_handle_scopes: usize, 36 | pub shared: *mut EnvShared, 37 | } 38 | 39 | unsafe impl Send for Env<'_, '_, '_> {} 40 | unsafe impl Sync for Env<'_, '_, '_> {} 41 | 42 | impl<'a, 'b, 'c> Env<'a, 'b, 'c> { 43 | pub fn new(scope: &'a mut v8::ContextScope<'b, v8::HandleScope<'c>>) -> Self { 44 | Self { 45 | scope, 46 | shared: std::ptr::null_mut(), 47 | open_handle_scopes: 0, 48 | } 49 | } 50 | 51 | pub fn with_new_scope( 52 | &self, 53 | scope: &'a mut v8::ContextScope<'b, v8::HandleScope<'c>>, 54 | ) -> Self { 55 | Self { 56 | scope, 57 | shared: self.shared, 58 | open_handle_scopes: self.open_handle_scopes, 59 | } 60 | } 61 | 62 | pub fn shared(&self) -> &EnvShared { 63 | unsafe { &*self.shared } 64 | } 65 | 66 | pub fn shared_mut(&self) -> &mut EnvShared { 67 | unsafe { &mut *self.shared } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/napi_create_typedarray.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use deno_core::v8; 4 | 5 | #[napi_sym] 6 | fn napi_create_typedarray( 7 | env: napi_env, 8 | ty: napi_typedarray_type, 9 | length: usize, 10 | arraybuffer: napi_value, 11 | byte_offset: usize, 12 | result: *mut napi_value, 13 | ) -> Result { 14 | let mut env = &mut *(env as *mut Env); 15 | let ab: v8::Local = std::mem::transmute(arraybuffer); 16 | let ab = v8::Local::::try_from(ab).unwrap(); 17 | let typedarray: v8::Local = match ty { 18 | napi_uint8_array => v8::Uint8Array::new(env.scope, ab, byte_offset, length) 19 | .unwrap() 20 | .into(), 21 | napi_uint8_clamped_array => { 22 | v8::Uint8ClampedArray::new(env.scope, ab, byte_offset, length) 23 | .unwrap() 24 | .into() 25 | } 26 | napi_int8_array => v8::Int8Array::new(env.scope, ab, byte_offset, length) 27 | .unwrap() 28 | .into(), 29 | napi_uint16_array => { 30 | v8::Uint16Array::new(env.scope, ab, byte_offset, length) 31 | .unwrap() 32 | .into() 33 | } 34 | napi_int16_array => v8::Int16Array::new(env.scope, ab, byte_offset, length) 35 | .unwrap() 36 | .into(), 37 | napi_uint32_array => { 38 | v8::Uint32Array::new(env.scope, ab, byte_offset, length) 39 | .unwrap() 40 | .into() 41 | } 42 | napi_int32_array => v8::Int32Array::new(env.scope, ab, byte_offset, length) 43 | .unwrap() 44 | .into(), 45 | napi_float32_array => { 46 | v8::Float32Array::new(env.scope, ab, byte_offset, length) 47 | .unwrap() 48 | .into() 49 | } 50 | napi_float64_array => { 51 | v8::Float64Array::new(env.scope, ab, byte_offset, length) 52 | .unwrap() 53 | .into() 54 | } 55 | napi_bigint64_array => { 56 | v8::BigInt64Array::new(env.scope, ab, byte_offset, length) 57 | .unwrap() 58 | .into() 59 | } 60 | napi_biguint64_array => { 61 | v8::BigUint64Array::new(env.scope, ab, byte_offset, length) 62 | .unwrap() 63 | .into() 64 | } 65 | _ => { 66 | return Err(Error::InvalidArg); 67 | } 68 | }; 69 | *result = std::mem::transmute(typedarray); 70 | Ok(()) 71 | } 72 | -------------------------------------------------------------------------------- /src/napi_define_class.rs: -------------------------------------------------------------------------------- 1 | use crate::env::Env; 2 | use crate::ffi::*; 3 | use crate::function::create_function_template; 4 | use deno_core::v8; 5 | 6 | #[napi_sym] 7 | fn napi_define_class( 8 | env: napi_env, 9 | utf8name: *const c_char, 10 | length: usize, 11 | constructor: napi_callback, 12 | callback_data: *mut c_void, 13 | property_count: usize, 14 | properties: *const napi_property_descriptor, 15 | result: *mut napi_value, 16 | ) -> Result { 17 | let mut env = &mut *(env as *mut Env); 18 | let name = std::ffi::CStr::from_ptr(utf8name).to_str().unwrap(); 19 | let tpl: v8::Local = std::mem::transmute( 20 | create_function_template(env, Some(name), constructor, callback_data), 21 | ); 22 | let napi_properties = std::slice::from_raw_parts(properties, property_count); 23 | for p in napi_properties { 24 | let name = if !p.utf8name.is_null() { 25 | let name_str = CStr::from_ptr(p.utf8name).to_str().unwrap(); 26 | v8::String::new(env.scope, name_str).unwrap() 27 | } else { 28 | std::mem::transmute(p.name) 29 | }; 30 | 31 | if !(p.method as *const c_void).is_null() { 32 | let function: v8::Local = std::mem::transmute( 33 | create_function_template(env, None, p.method, p.data), 34 | ); 35 | let proto = tpl.prototype_template(env.scope); 36 | proto.set(name.into(), function.into()); 37 | } else if !(p.getter as *const c_void).is_null() 38 | || !(p.setter as *const c_void).is_null() 39 | { 40 | let getter: Option> = 41 | if !(p.getter as *const c_void).is_null() { 42 | Some(std::mem::transmute(create_function_template( 43 | env, None, p.getter, p.data, 44 | ))) 45 | } else { 46 | None 47 | }; 48 | let setter: Option> = 49 | if !(p.setter as *const c_void).is_null() { 50 | Some(std::mem::transmute(create_function_template( 51 | env, None, p.setter, p.data, 52 | ))) 53 | } else { 54 | None 55 | }; 56 | 57 | let proto = tpl.prototype_template(env.scope); 58 | 59 | let base_name = CStr::from_ptr(p.utf8name).to_str().unwrap(); 60 | let getter_name = 61 | v8::String::new(env.scope, format!("get_{}", base_name).as_str()) 62 | .unwrap(); 63 | let setter_name = 64 | v8::String::new(env.scope, format!("set_{}", base_name).as_str()) 65 | .unwrap(); 66 | 67 | // TODO: use set_accessor & set_accessor_with_setter 68 | match (getter, setter) { 69 | (Some(getter), None) => { 70 | proto.set(getter_name.into(), getter.into()); 71 | } 72 | (Some(getter), Some(setter)) => { 73 | proto.set(getter_name.into(), getter.into()); 74 | proto.set(setter_name.into(), setter.into()); 75 | } 76 | (None, Some(setter)) => { 77 | proto.set(setter_name.into(), setter.into()); 78 | } 79 | (None, None) => unreachable!(), 80 | } 81 | } else { 82 | let proto = tpl.prototype_template(env.scope); 83 | proto.set(name.into(), std::mem::transmute(p.value)); 84 | } 85 | } 86 | 87 | let value: v8::Local = tpl.get_function(env.scope).unwrap().into(); 88 | *result = std::mem::transmute(value); 89 | Ok(()) 90 | } 91 | -------------------------------------------------------------------------------- /src/function.rs: -------------------------------------------------------------------------------- 1 | use crate::{env::Env, ffi::*}; 2 | use deno_core::v8; 3 | 4 | #[repr(C)] 5 | #[derive(Debug)] 6 | pub struct CallbackInfo { 7 | pub env: napi_env, 8 | pub cb: napi_callback, 9 | pub cb_info: napi_callback_info, 10 | pub args: *const c_void, 11 | } 12 | 13 | pub unsafe fn create_function<'a>( 14 | env: &'a mut Env, 15 | name: Option<&str>, 16 | cb: napi_callback, 17 | cb_info: napi_callback_info, 18 | ) -> v8::Local<'a, v8::Function> { 19 | let method_ptr = v8::External::new(env.scope, std::mem::transmute(cb)); 20 | let cb_info_ext = v8::External::new(env.scope, std::mem::transmute(cb_info)); 21 | let env_ptr = env as *mut _ as *mut c_void; 22 | let env_ext = v8::External::new(env.scope, env_ptr); 23 | 24 | let data_array = v8::Array::new_with_elements( 25 | env.scope, 26 | &[method_ptr.into(), cb_info_ext.into(), env_ext.into()], 27 | ); 28 | 29 | let function = v8::Function::builder( 30 | |handle_scope: &mut v8::HandleScope, 31 | args: v8::FunctionCallbackArguments, 32 | mut rv: v8::ReturnValue| { 33 | let context = v8::Context::new(handle_scope); 34 | let scope = &mut v8::ContextScope::new(handle_scope, context); 35 | 36 | let data = args.data().unwrap(); 37 | let data_array = v8::Local::::try_from(data).unwrap(); 38 | 39 | let method_ptr = v8::Local::::try_from( 40 | data_array.get_index(scope, 0).unwrap(), 41 | ) 42 | .unwrap(); 43 | let cb: napi_callback = 44 | unsafe { std::mem::transmute(method_ptr.value()) }; 45 | 46 | let cb_info_ptr = v8::Local::::try_from( 47 | data_array.get_index(scope, 1).unwrap(), 48 | ) 49 | .unwrap(); 50 | let cb_info: napi_callback_info = 51 | unsafe { std::mem::transmute(cb_info_ptr.value()) }; 52 | 53 | let env_ptr = v8::Local::::try_from( 54 | data_array.get_index(scope, 2).unwrap(), 55 | ) 56 | .unwrap(); 57 | let env_ptr = env_ptr.value() as *mut Env; 58 | 59 | let mut env = (&mut *(env_ptr)).with_new_scope(scope); 60 | let env_ptr = &mut env as *mut _ as *mut c_void; 61 | 62 | let mut info = CallbackInfo { 63 | env: env_ptr, 64 | cb, 65 | cb_info, 66 | args: &args as *const _ as *const c_void, 67 | }; 68 | 69 | let info_ptr = &mut info as *mut _ as *mut c_void; 70 | 71 | let value = unsafe { cb(env_ptr, info_ptr) }; 72 | let value = unsafe { std::mem::transmute(value) }; 73 | rv.set(value); 74 | }, 75 | ) 76 | .data(data_array.into()) 77 | .build(env.scope) 78 | .unwrap(); 79 | 80 | if let Some(name) = name { 81 | let v8str = v8::String::new(env.scope, name).unwrap(); 82 | function.set_name(v8str); 83 | } 84 | 85 | function 86 | } 87 | 88 | pub unsafe fn create_function_template<'a>( 89 | env: &'a mut Env, 90 | name: Option<&str>, 91 | cb: napi_callback, 92 | cb_info: napi_callback_info, 93 | ) -> v8::Local<'a, v8::FunctionTemplate> { 94 | let method_ptr = v8::External::new(env.scope, std::mem::transmute(cb)); 95 | let cb_info_ext = v8::External::new(env.scope, std::mem::transmute(cb_info)); 96 | let env_ptr = env as *mut _ as *mut c_void; 97 | let env_ext = v8::External::new(env.scope, env_ptr); 98 | 99 | let data_array = v8::Array::new_with_elements( 100 | env.scope, 101 | &[method_ptr.into(), cb_info_ext.into(), env_ext.into()], 102 | ); 103 | 104 | let function = v8::FunctionTemplate::builder( 105 | |handle_scope: &mut v8::HandleScope, 106 | args: v8::FunctionCallbackArguments, 107 | mut rv: v8::ReturnValue| { 108 | let context = v8::Context::new(handle_scope); 109 | let scope = &mut v8::ContextScope::new(handle_scope, context); 110 | 111 | let data = args.data().unwrap(); 112 | let data_array = v8::Local::::try_from(data).unwrap(); 113 | 114 | let method_ptr = v8::Local::::try_from( 115 | data_array.get_index(scope, 0).unwrap(), 116 | ) 117 | .unwrap(); 118 | let cb: napi_callback = 119 | unsafe { std::mem::transmute(method_ptr.value()) }; 120 | 121 | let cb_info_ptr = v8::Local::::try_from( 122 | data_array.get_index(scope, 1).unwrap(), 123 | ) 124 | .unwrap(); 125 | let cb_info: napi_callback_info = 126 | unsafe { std::mem::transmute(cb_info_ptr.value()) }; 127 | 128 | let env_ptr = v8::Local::::try_from( 129 | data_array.get_index(scope, 2).unwrap(), 130 | ) 131 | .unwrap(); 132 | let env_ptr = env_ptr.value() as *mut Env; 133 | 134 | let mut env = (&mut *(env_ptr)).with_new_scope(scope); 135 | let env_ptr = &mut env as *mut _ as *mut c_void; 136 | 137 | let mut info = CallbackInfo { 138 | env: env_ptr, 139 | cb, 140 | cb_info, 141 | args: &args as *const _ as *const c_void, 142 | }; 143 | 144 | let info_ptr = &mut info as *mut _ as *mut c_void; 145 | 146 | let value = unsafe { cb(env_ptr, info_ptr) }; 147 | let value = unsafe { std::mem::transmute(value) }; 148 | rv.set(value); 149 | }, 150 | ) 151 | .data(data_array.into()) 152 | .build(env.scope); 153 | 154 | if let Some(name) = name { 155 | let v8str = v8::String::new(env.scope, name).unwrap(); 156 | function.set_class_name(v8str); 157 | } 158 | 159 | function 160 | } 161 | -------------------------------------------------------------------------------- /src/ffi.rs: -------------------------------------------------------------------------------- 1 | pub use std::ffi::CStr; 2 | pub use std::mem::transmute; 3 | pub use std::os::raw::c_char; 4 | pub use std::os::raw::c_void; 5 | pub use std::ptr; 6 | 7 | pub type napi_status = i32; 8 | pub type napi_env = *mut c_void; 9 | pub type napi_value = *mut c_void; 10 | pub type napi_callback_info = *mut c_void; 11 | pub type napi_deferred = *mut c_void; 12 | pub type napi_ref = *mut c_void; 13 | pub type napi_threadsafe_function = *mut c_void; 14 | pub type napi_handle_scope = *mut c_void; 15 | pub type napi_escapable_handle_scope = *mut c_void; 16 | pub type napi_async_cleanup_hook_handle = *mut c_void; 17 | pub type napi_async_work = *mut c_void; 18 | 19 | pub const napi_ok: napi_status = 0; 20 | pub const napi_invalid_arg: napi_status = 1; 21 | pub const napi_object_expected: napi_status = 2; 22 | pub const napi_string_expected: napi_status = 3; 23 | pub const napi_name_expected: napi_status = 4; 24 | pub const napi_function_expected: napi_status = 5; 25 | pub const napi_number_expected: napi_status = 6; 26 | pub const napi_boolean_expected: napi_status = 7; 27 | pub const napi_array_expected: napi_status = 8; 28 | pub const napi_generic_failure: napi_status = 9; 29 | pub const napi_pending_exception: napi_status = 10; 30 | pub const napi_cancelled: napi_status = 11; 31 | pub const napi_escape_called_twice: napi_status = 12; 32 | pub const napi_handle_scope_mismatch: napi_status = 13; 33 | pub const napi_callback_scope_mismatch: napi_status = 14; 34 | pub const napi_queue_full: napi_status = 15; 35 | pub const napi_closing: napi_status = 16; 36 | pub const napi_bigint_expected: napi_status = 17; 37 | pub const napi_date_expected: napi_status = 18; 38 | pub const napi_arraybuffer_expected: napi_status = 19; 39 | pub const napi_detachable_arraybuffer_expected: napi_status = 20; 40 | pub const napi_would_deadlock: napi_status = 21; 41 | 42 | #[derive(Debug, Clone, PartialEq)] 43 | pub enum Error { 44 | InvalidArg, 45 | ObjectExpected, 46 | StringExpected, 47 | NameExpected, 48 | FunctionExpected, 49 | NumberExpected, 50 | BooleanExpected, 51 | ArrayExpected, 52 | GenericFailure, 53 | PendingException, 54 | Cancelled, 55 | EscapeCalledTwice, 56 | HandleScopeMismatch, 57 | CallbackScopeMismatch, 58 | QueueFull, 59 | Closing, 60 | BigIntExpected, 61 | DateExpected, 62 | ArrayBufferExpected, 63 | DetachableArraybufferExpected, 64 | WouldDeadlock, 65 | } 66 | 67 | pub type Result = std::result::Result<(), Error>; 68 | 69 | impl Into for Error { 70 | fn into(self) -> napi_status { 71 | match self { 72 | Error::InvalidArg => napi_invalid_arg, 73 | Error::ObjectExpected => napi_object_expected, 74 | Error::StringExpected => napi_string_expected, 75 | Error::NameExpected => napi_name_expected, 76 | Error::FunctionExpected => napi_function_expected, 77 | Error::NumberExpected => napi_number_expected, 78 | Error::BooleanExpected => napi_boolean_expected, 79 | Error::ArrayExpected => napi_array_expected, 80 | Error::GenericFailure => napi_generic_failure, 81 | Error::PendingException => napi_pending_exception, 82 | Error::Cancelled => napi_cancelled, 83 | Error::EscapeCalledTwice => napi_escape_called_twice, 84 | Error::HandleScopeMismatch => napi_handle_scope_mismatch, 85 | Error::CallbackScopeMismatch => napi_callback_scope_mismatch, 86 | Error::QueueFull => napi_queue_full, 87 | Error::Closing => napi_closing, 88 | Error::BigIntExpected => napi_bigint_expected, 89 | Error::DateExpected => napi_date_expected, 90 | Error::ArrayBufferExpected => napi_arraybuffer_expected, 91 | Error::DetachableArraybufferExpected => { 92 | napi_detachable_arraybuffer_expected 93 | } 94 | Error::WouldDeadlock => napi_would_deadlock, 95 | } 96 | } 97 | } 98 | 99 | pub type napi_valuetype = i32; 100 | 101 | pub const napi_undefined: napi_valuetype = 0; 102 | pub const napi_null: napi_valuetype = 1; 103 | pub const napi_boolean: napi_valuetype = 2; 104 | pub const napi_number: napi_valuetype = 3; 105 | pub const napi_string: napi_valuetype = 4; 106 | pub const napi_symbol: napi_valuetype = 5; 107 | pub const napi_object: napi_valuetype = 6; 108 | pub const napi_function: napi_valuetype = 7; 109 | pub const napi_external: napi_valuetype = 8; 110 | pub const napi_bigint: napi_valuetype = 9; 111 | 112 | pub type napi_threadsafe_function_release_mode = i32; 113 | 114 | pub const napi_tsfn_release: napi_threadsafe_function_release_mode = 0; 115 | pub const napi_tsfn_abortext: napi_threadsafe_function_release_mode = 1; 116 | 117 | pub type napi_threadsafe_function_call_mode = i32; 118 | 119 | pub const napi_tsfn_nonblocking: napi_threadsafe_function_call_mode = 0; 120 | pub const napi_tsfn_blocking: napi_threadsafe_function_call_mode = 1; 121 | 122 | pub type napi_key_collection_mode = i32; 123 | 124 | pub const napi_key_include_prototypes: napi_key_collection_mode = 0; 125 | pub const napi_key_own_only: napi_key_collection_mode = 1; 126 | 127 | pub type napi_key_filter = i32; 128 | 129 | pub const napi_key_all_properties: napi_key_filter = 0; 130 | pub const napi_key_writable: napi_key_filter = 1; 131 | pub const napi_key_enumerable: napi_key_filter = 1 << 1; 132 | pub const napi_key_configurable: napi_key_filter = 1 << 2; 133 | pub const napi_key_skip_strings: napi_key_filter = 1 << 3; 134 | pub const napi_key_skip_symbols: napi_key_filter = 1 << 4; 135 | 136 | pub type napi_key_conversion = i32; 137 | 138 | pub const napi_key_keep_numbers: napi_key_conversion = 0; 139 | pub const napi_key_numbers_to_strings: napi_key_conversion = 1; 140 | 141 | pub type napi_typedarray_type = i32; 142 | 143 | pub const napi_int8_array: napi_typedarray_type = 0; 144 | pub const napi_uint8_array: napi_typedarray_type = 1; 145 | pub const napi_uint8_clamped_array: napi_typedarray_type = 2; 146 | pub const napi_int16_array: napi_typedarray_type = 3; 147 | pub const napi_uint16_array: napi_typedarray_type = 4; 148 | pub const napi_int32_array: napi_typedarray_type = 5; 149 | pub const napi_uint32_array: napi_typedarray_type = 6; 150 | pub const napi_float32_array: napi_typedarray_type = 7; 151 | pub const napi_float64_array: napi_typedarray_type = 8; 152 | pub const napi_bigint64_array: napi_typedarray_type = 9; 153 | pub const napi_biguint64_array: napi_typedarray_type = 10; 154 | 155 | pub struct napi_type_tag { 156 | pub lower: u64, 157 | pub upper: u64, 158 | } 159 | 160 | pub type napi_callback = 161 | unsafe extern "C" fn(env: napi_env, info: napi_callback_info) -> napi_value; 162 | 163 | pub type napi_finalize = unsafe extern "C" fn( 164 | env: napi_env, 165 | data: *mut c_void, 166 | finalize_hint: *mut c_void, 167 | ); 168 | 169 | pub type napi_async_execute_callback = 170 | unsafe extern "C" fn(env: napi_env, data: *mut c_void); 171 | 172 | pub type napi_async_complete_callback = 173 | unsafe extern "C" fn(env: napi_env, status: napi_status, data: *mut c_void); 174 | 175 | pub type napi_threadsafe_function_call_js = unsafe extern "C" fn( 176 | env: napi_env, 177 | js_callback: napi_value, 178 | context: *mut c_void, 179 | data: *mut c_void, 180 | ); 181 | 182 | pub type napi_async_cleanup_hook = 183 | unsafe extern "C" fn(env: napi_env, data: *mut c_void); 184 | 185 | pub type napi_property_attributes = i32; 186 | 187 | pub const napi_default: napi_property_attributes = 0; 188 | pub const napi_writable: napi_property_attributes = 1 << 0; 189 | pub const napi_enumerable: napi_property_attributes = 1 << 1; 190 | pub const napi_configurable: napi_property_attributes = 1 << 2; 191 | pub const napi_static: napi_property_attributes = 1 << 10; 192 | pub const napi_default_method: napi_property_attributes = 193 | napi_writable | napi_configurable; 194 | pub const napi_default_jsproperty: napi_property_attributes = 195 | napi_enumerable | napi_configurable | napi_writable; 196 | 197 | #[repr(C)] 198 | #[derive(Copy, Clone, Debug)] 199 | pub struct napi_property_descriptor { 200 | pub utf8name: *const c_char, 201 | pub name: napi_value, 202 | pub method: napi_callback, 203 | pub getter: napi_callback, 204 | pub setter: napi_callback, 205 | pub value: napi_value, 206 | pub attributes: napi_property_attributes, 207 | pub data: *mut c_void, 208 | } 209 | 210 | #[repr(C)] 211 | #[derive(Debug)] 212 | pub struct napi_extended_error_info { 213 | pub error_message: *const c_char, 214 | pub engine_reserved: *mut c_void, 215 | pub engine_error_code: i32, 216 | pub status_code: napi_status, 217 | } 218 | 219 | #[repr(C)] 220 | #[derive(Debug)] 221 | pub struct napi_node_version { 222 | pub major: u32, 223 | pub minor: u32, 224 | pub patch: u32, 225 | pub release: *const c_char, 226 | } 227 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | #![allow(unused_mut)] 3 | #![allow(unused_variables)] 4 | #![allow(non_upper_case_globals)] 5 | #![allow(dead_code)] 6 | 7 | #[macro_use] 8 | extern crate napi_sym; 9 | 10 | use std::ffi::CString; 11 | 12 | use env::EnvShared; 13 | #[cfg(unix)] 14 | use libloading::os::unix::*; 15 | 16 | #[cfg(windows)] 17 | use libloading::os::windows::*; 18 | 19 | pub mod env; 20 | pub mod ffi; 21 | pub mod function; 22 | pub mod napi_add_env_cleanup_hook; 23 | pub mod napi_adjust_external_memory; 24 | pub mod napi_call_function; 25 | pub mod napi_call_threadsafe_function; 26 | pub mod napi_cancel_async_work; 27 | pub mod napi_close_escapable_handle_scope; 28 | pub mod napi_close_handle_scope; 29 | pub mod napi_coerce_to_bool; 30 | pub mod napi_coerce_to_number; 31 | pub mod napi_coerce_to_object; 32 | pub mod napi_coerce_to_string; 33 | pub mod napi_create_array_with_length; 34 | pub mod napi_create_arraybuffer; 35 | pub mod napi_create_async_work; 36 | pub mod napi_create_bigint_int64; 37 | pub mod napi_create_bigint_uint64; 38 | pub mod napi_create_bigint_words; 39 | pub mod napi_create_buffer; 40 | pub mod napi_create_buffer_copy; 41 | pub mod napi_create_dataview; 42 | pub mod napi_create_date; 43 | pub mod napi_create_double; 44 | pub mod napi_create_error; 45 | pub mod napi_create_external; 46 | pub mod napi_create_external_arraybuffer; 47 | pub mod napi_create_external_buffer; 48 | pub mod napi_create_function; 49 | pub mod napi_create_int32; 50 | pub mod napi_create_int64; 51 | pub mod napi_create_object; 52 | pub mod napi_create_promise; 53 | pub mod napi_create_range_error; 54 | pub mod napi_create_reference; 55 | pub mod napi_create_string_latin1; 56 | pub mod napi_create_string_utf16; 57 | pub mod napi_create_string_utf8; 58 | pub mod napi_create_symbol; 59 | pub mod napi_create_threadsafe_function; 60 | pub mod napi_create_type_error; 61 | pub mod napi_create_typedarray; 62 | pub mod napi_create_uint32; 63 | pub mod napi_define_class; 64 | pub mod napi_define_properties; 65 | pub mod napi_delete_async_work; 66 | pub mod napi_delete_element; 67 | pub mod napi_delete_property; 68 | pub mod napi_delete_reference; 69 | pub mod napi_detach_arraybuffer; 70 | pub mod napi_escape_handle; 71 | pub mod napi_fatal_error; 72 | pub mod napi_fatal_exception; 73 | pub mod napi_get_all_property_names; 74 | pub mod napi_get_and_clear_last_exception; 75 | pub mod napi_get_array_length; 76 | pub mod napi_get_arraybuffer_info; 77 | pub mod napi_get_boolean; 78 | pub mod napi_get_buffer_info; 79 | pub mod napi_get_cb_info; 80 | pub mod napi_get_dataview_info; 81 | pub mod napi_get_date_value; 82 | pub mod napi_get_element; 83 | pub mod napi_get_global; 84 | pub mod napi_get_instance_data; 85 | pub mod napi_get_last_error_info; 86 | pub mod napi_get_named_property; 87 | pub mod napi_get_new_target; 88 | pub mod napi_get_node_version; 89 | pub mod napi_get_null; 90 | pub mod napi_get_property; 91 | pub mod napi_get_property_names; 92 | pub mod napi_get_prototype; 93 | pub mod napi_get_reference_value; 94 | pub mod napi_get_typedarray_info; 95 | pub mod napi_get_undefined; 96 | pub mod napi_get_value_bigint_int64; 97 | pub mod napi_get_value_bigint_uint64; 98 | pub mod napi_get_value_bigint_words; 99 | pub mod napi_get_value_bool; 100 | pub mod napi_get_value_double; 101 | pub mod napi_get_value_external; 102 | pub mod napi_get_value_int32; 103 | pub mod napi_get_value_string_latin1; 104 | pub mod napi_get_value_string_utf16; 105 | pub mod napi_get_value_string_utf8; 106 | pub mod napi_get_value_uint32; 107 | pub mod napi_get_version; 108 | pub mod napi_has_element; 109 | pub mod napi_has_named_property; 110 | pub mod napi_has_property; 111 | pub mod napi_instanceof; 112 | pub mod napi_is_array; 113 | pub mod napi_is_arraybuffer; 114 | pub mod napi_is_buffer; 115 | pub mod napi_is_dataview; 116 | pub mod napi_is_date; 117 | pub mod napi_is_detached_arraybuffer; 118 | pub mod napi_is_error; 119 | pub mod napi_is_exception_pending; 120 | pub mod napi_is_promise; 121 | pub mod napi_is_typedarray; 122 | pub mod napi_module_register; 123 | pub mod napi_new_instance; 124 | pub mod napi_open_escapable_handle_scope; 125 | pub mod napi_open_handle_scope; 126 | pub mod napi_queue_async_work; 127 | pub mod napi_ref_threadsafe_function; 128 | pub mod napi_reference_ref; 129 | pub mod napi_reference_unref; 130 | pub mod napi_reject_deferred; 131 | pub mod napi_release_threadsafe_function; 132 | pub mod napi_remove_env_cleanup_hook; 133 | pub mod napi_remove_wrap; 134 | pub mod napi_resolve_deferred; 135 | pub mod napi_run_script; 136 | pub mod napi_set_element; 137 | pub mod napi_set_instance_data; 138 | pub mod napi_set_named_property; 139 | pub mod napi_set_property; 140 | pub mod napi_strict_equals; 141 | pub mod napi_throw; 142 | pub mod napi_throw_error; 143 | pub mod napi_throw_range_error; 144 | pub mod napi_throw_type_error; 145 | pub mod napi_typeof; 146 | pub mod napi_unref_threadsafe_function; 147 | pub mod napi_unwrap; 148 | pub mod napi_wrap; 149 | pub mod node_api_create_syntax_error; 150 | pub mod node_api_get_module_file_name; 151 | pub mod node_api_throw_syntax_error; 152 | pub mod util; 153 | 154 | use deno_core::JsRuntime; 155 | 156 | use crate::env::Env; 157 | use crate::ffi::*; 158 | use deno_core::v8; 159 | 160 | #[tokio::main] 161 | async fn main() { 162 | let mut runtime = JsRuntime::new(Default::default()); 163 | 164 | { 165 | let mut scope = &mut runtime.handle_scope(); 166 | let context = scope.get_current_context(); 167 | let inner_scope = &mut v8::ContextScope::new(scope, context); 168 | let global = context.global(inner_scope); 169 | 170 | let dlopen_func = v8::Function::builder( 171 | |handle_scope: &mut v8::HandleScope, 172 | args: v8::FunctionCallbackArguments, 173 | mut rv: v8::ReturnValue| { 174 | let context = v8::Context::new(handle_scope); 175 | let scope = &mut v8::ContextScope::new(handle_scope, context); 176 | 177 | let napi_wrap_name = v8::String::new(scope, "napi_wrap").unwrap(); 178 | let napi_wrap = v8::Private::new(scope, Some(napi_wrap_name)); 179 | let napi_wrap = v8::Local::new(scope, napi_wrap); 180 | let napi_wrap = v8::Global::new(scope, napi_wrap); 181 | 182 | let path = args.get(0).to_string(scope).unwrap(); 183 | let path = path.to_rust_string_lossy(scope); 184 | 185 | let mut exports = v8::Object::new(scope); 186 | 187 | // We need complete control over the env object's lifetime 188 | // so we'll use explicit allocation for it, so that it doesn't 189 | // die before the module itself. Using struct & their pointers 190 | // resulted in a use-after-free situation which turned out to be 191 | // unfixable, so here we are. 192 | let env_shared_ptr = unsafe { 193 | std::alloc::alloc(std::alloc::Layout::new::()) 194 | as *mut EnvShared 195 | }; 196 | let mut env_shared = EnvShared::new(napi_wrap); 197 | let cstr = CString::new(path.clone()).unwrap(); 198 | env_shared.filename = cstr.as_ptr(); 199 | std::mem::forget(cstr); 200 | unsafe { 201 | env_shared_ptr.write(env_shared); 202 | } 203 | 204 | let env_ptr = unsafe { 205 | std::alloc::alloc(std::alloc::Layout::new::()) as napi_env 206 | }; 207 | let mut env = Env::new(scope); 208 | env.shared = env_shared_ptr; 209 | unsafe { 210 | (env_ptr as *mut Env).write(env); 211 | } 212 | 213 | #[cfg(unix)] 214 | let flags = RTLD_LAZY; 215 | #[cfg(not(unix))] 216 | let flags = 0x00000008; 217 | 218 | #[cfg(unix)] 219 | let library = match unsafe { Library::open(Some(&path), flags) } { 220 | Ok(lib) => lib, 221 | Err(e) => { 222 | let message = v8::String::new(scope, &e.to_string()).unwrap(); 223 | let error = v8::Exception::type_error(scope, message); 224 | scope.throw_exception(error); 225 | return; 226 | } 227 | }; 228 | 229 | #[cfg(not(unix))] 230 | let library = match unsafe { Library::load_with_flags(&path, flags) } { 231 | Ok(lib) => lib, 232 | Err(e) => { 233 | let message = v8::String::new(scope, &e.to_string()).unwrap(); 234 | let error = v8::Exception::type_error(scope, message); 235 | scope.throw_exception(error); 236 | return; 237 | } 238 | }; 239 | 240 | napi_module_register::MODULE.with(|cell| { 241 | let slot = *cell.borrow(); 242 | match slot { 243 | Some(nm) => { 244 | let nm = unsafe { &*nm }; 245 | assert_eq!(nm.nm_version, 1); 246 | let exports = unsafe { 247 | (nm.nm_register_func)(env_ptr, std::mem::transmute(exports)) 248 | }; 249 | 250 | let exports: v8::Local = 251 | unsafe { std::mem::transmute(exports) }; 252 | rv.set(exports); 253 | } 254 | None => { 255 | // Initializer callback. 256 | let init = unsafe { 257 | library 258 | .get:: napi_value>(b"napi_register_module_v1") 262 | .expect("napi_register_module_v1 not found") 263 | }; 264 | 265 | unsafe { init(env_ptr, std::mem::transmute(exports)) }; 266 | rv.set(exports.into()); 267 | } 268 | } 269 | }); 270 | 271 | std::mem::forget(library); 272 | }, 273 | ) 274 | .build(inner_scope) 275 | .unwrap(); 276 | 277 | let dlopen_name = v8::String::new(inner_scope, "dlopen").unwrap(); 278 | 279 | global 280 | .set(inner_scope, dlopen_name.into(), dlopen_func.into()) 281 | .unwrap(); 282 | } 283 | 284 | let filename = std::env::args() 285 | .nth(1) 286 | .unwrap_or(String::from("./test/example.js")); 287 | let source_code = std::fs::read_to_string(&filename).unwrap(); 288 | 289 | runtime 290 | .execute_script("core.js", include_str!("core.js")) 291 | .unwrap(); 292 | 293 | match runtime.execute_script(&filename, &source_code) { 294 | Ok(_) => {} 295 | Err(e) => { 296 | eprintln!("{}", e); 297 | std::process::exit(1); 298 | } 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /example_module/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "0.7.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "convert_case" 16 | version = "0.5.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" 19 | 20 | [[package]] 21 | name = "ctor" 22 | version = "0.1.21" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" 25 | dependencies = [ 26 | "quote", 27 | "syn", 28 | ] 29 | 30 | [[package]] 31 | name = "example_module" 32 | version = "0.1.0" 33 | dependencies = [ 34 | "futures", 35 | "napi", 36 | "napi-build", 37 | "napi-derive", 38 | "tokio", 39 | ] 40 | 41 | [[package]] 42 | name = "futures" 43 | version = "0.3.19" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" 46 | dependencies = [ 47 | "futures-channel", 48 | "futures-core", 49 | "futures-executor", 50 | "futures-io", 51 | "futures-sink", 52 | "futures-task", 53 | "futures-util", 54 | ] 55 | 56 | [[package]] 57 | name = "futures-channel" 58 | version = "0.3.19" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" 61 | dependencies = [ 62 | "futures-core", 63 | "futures-sink", 64 | ] 65 | 66 | [[package]] 67 | name = "futures-core" 68 | version = "0.3.19" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" 71 | 72 | [[package]] 73 | name = "futures-executor" 74 | version = "0.3.19" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" 77 | dependencies = [ 78 | "futures-core", 79 | "futures-task", 80 | "futures-util", 81 | ] 82 | 83 | [[package]] 84 | name = "futures-io" 85 | version = "0.3.19" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" 88 | 89 | [[package]] 90 | name = "futures-macro" 91 | version = "0.3.19" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" 94 | dependencies = [ 95 | "proc-macro2", 96 | "quote", 97 | "syn", 98 | ] 99 | 100 | [[package]] 101 | name = "futures-sink" 102 | version = "0.3.19" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" 105 | 106 | [[package]] 107 | name = "futures-task" 108 | version = "0.3.19" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" 111 | 112 | [[package]] 113 | name = "futures-util" 114 | version = "0.3.19" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" 117 | dependencies = [ 118 | "futures-channel", 119 | "futures-core", 120 | "futures-io", 121 | "futures-macro", 122 | "futures-sink", 123 | "futures-task", 124 | "memchr", 125 | "pin-project-lite", 126 | "pin-utils", 127 | "slab", 128 | ] 129 | 130 | [[package]] 131 | name = "hermit-abi" 132 | version = "0.1.19" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 135 | dependencies = [ 136 | "libc", 137 | ] 138 | 139 | [[package]] 140 | name = "lazy_static" 141 | version = "1.4.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 144 | 145 | [[package]] 146 | name = "libc" 147 | version = "0.2.113" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" 150 | 151 | [[package]] 152 | name = "memchr" 153 | version = "2.4.1" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 156 | 157 | [[package]] 158 | name = "napi" 159 | version = "2.0.3" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "5cbca4762c2865296cf6c9b2252fc2d875f005d2903a148b4cd6206bb6f9a686" 162 | dependencies = [ 163 | "ctor", 164 | "lazy_static", 165 | "napi-sys", 166 | "tokio", 167 | "windows", 168 | ] 169 | 170 | [[package]] 171 | name = "napi-build" 172 | version = "1.2.1" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "ebd4419172727423cf30351406c54f6cc1b354a2cfb4f1dba3e6cd07f6d5522b" 175 | 176 | [[package]] 177 | name = "napi-derive" 178 | version = "2.0.7" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "c6978824526532976fe146f71fef50395840d64a6c1af9085a358bdfdd300c7d" 181 | dependencies = [ 182 | "convert_case", 183 | "napi-derive-backend", 184 | "proc-macro2", 185 | "quote", 186 | "syn", 187 | ] 188 | 189 | [[package]] 190 | name = "napi-derive-backend" 191 | version = "1.0.23" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "30623da375dd5a5cae5609b0f0b9915177c03b3dc23a8450cc7dcc14027eee25" 194 | dependencies = [ 195 | "convert_case", 196 | "once_cell", 197 | "proc-macro2", 198 | "quote", 199 | "regex", 200 | "syn", 201 | ] 202 | 203 | [[package]] 204 | name = "napi-sys" 205 | version = "2.1.0" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "8a385494dac3c52cbcacb393bb3b42669e7db8ab240c7ad5115f549eb061f2cc" 208 | 209 | [[package]] 210 | name = "num_cpus" 211 | version = "1.13.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 214 | dependencies = [ 215 | "hermit-abi", 216 | "libc", 217 | ] 218 | 219 | [[package]] 220 | name = "once_cell" 221 | version = "1.9.0" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" 224 | 225 | [[package]] 226 | name = "pin-project-lite" 227 | version = "0.2.8" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" 230 | 231 | [[package]] 232 | name = "pin-utils" 233 | version = "0.1.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 236 | 237 | [[package]] 238 | name = "proc-macro2" 239 | version = "1.0.36" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" 242 | dependencies = [ 243 | "unicode-xid", 244 | ] 245 | 246 | [[package]] 247 | name = "quote" 248 | version = "1.0.14" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" 251 | dependencies = [ 252 | "proc-macro2", 253 | ] 254 | 255 | [[package]] 256 | name = "regex" 257 | version = "1.5.4" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 260 | dependencies = [ 261 | "aho-corasick", 262 | "memchr", 263 | "regex-syntax", 264 | ] 265 | 266 | [[package]] 267 | name = "regex-syntax" 268 | version = "0.6.25" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 271 | 272 | [[package]] 273 | name = "slab" 274 | version = "0.4.5" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" 277 | 278 | [[package]] 279 | name = "syn" 280 | version = "1.0.85" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" 283 | dependencies = [ 284 | "proc-macro2", 285 | "quote", 286 | "unicode-xid", 287 | ] 288 | 289 | [[package]] 290 | name = "tokio" 291 | version = "1.15.0" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" 294 | dependencies = [ 295 | "num_cpus", 296 | "pin-project-lite", 297 | ] 298 | 299 | [[package]] 300 | name = "unicode-xid" 301 | version = "0.2.2" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 304 | 305 | [[package]] 306 | name = "windows" 307 | version = "0.29.0" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "aac7fef12f4b59cd0a29339406cc9203ab44e440ddff6b3f5a41455349fa9cf3" 310 | dependencies = [ 311 | "windows_aarch64_msvc", 312 | "windows_i686_gnu", 313 | "windows_i686_msvc", 314 | "windows_x86_64_gnu", 315 | "windows_x86_64_msvc", 316 | ] 317 | 318 | [[package]] 319 | name = "windows_aarch64_msvc" 320 | version = "0.29.0" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "c3d027175d00b01e0cbeb97d6ab6ebe03b12330a35786cbaca5252b1c4bf5d9b" 323 | 324 | [[package]] 325 | name = "windows_i686_gnu" 326 | version = "0.29.0" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "8793f59f7b8e8b01eda1a652b2697d87b93097198ae85f823b969ca5b89bba58" 329 | 330 | [[package]] 331 | name = "windows_i686_msvc" 332 | version = "0.29.0" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "8602f6c418b67024be2996c512f5f995de3ba417f4c75af68401ab8756796ae4" 335 | 336 | [[package]] 337 | name = "windows_x86_64_gnu" 338 | version = "0.29.0" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "f3d615f419543e0bd7d2b3323af0d86ff19cbc4f816e6453f36a2c2ce889c354" 341 | 342 | [[package]] 343 | name = "windows_x86_64_msvc" 344 | version = "0.29.0" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "11d95421d9ed3672c280884da53201a5c46b7b2765ca6faf34b0d71cf34a3561" 347 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.52" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" 10 | 11 | [[package]] 12 | name = "autocfg" 13 | version = "1.0.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 16 | 17 | [[package]] 18 | name = "bitflags" 19 | version = "1.3.2" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 22 | 23 | [[package]] 24 | name = "bytes" 25 | version = "1.1.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 28 | 29 | [[package]] 30 | name = "cfg-if" 31 | version = "1.0.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 34 | 35 | [[package]] 36 | name = "deno_core" 37 | version = "0.114.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "d8ddd27161918d0d0cc44ee5ff3b817b4c87e868922d63ee026f3e7c24f36131" 40 | dependencies = [ 41 | "anyhow", 42 | "futures", 43 | "indexmap", 44 | "libc", 45 | "log", 46 | "once_cell", 47 | "parking_lot", 48 | "pin-project", 49 | "serde", 50 | "serde_json", 51 | "serde_v8", 52 | "url", 53 | "v8", 54 | ] 55 | 56 | [[package]] 57 | name = "either" 58 | version = "1.6.1" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 61 | 62 | [[package]] 63 | name = "form_urlencoded" 64 | version = "1.0.1" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 67 | dependencies = [ 68 | "matches", 69 | "percent-encoding", 70 | ] 71 | 72 | [[package]] 73 | name = "fslock" 74 | version = "0.1.8" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "57eafdd0c16f57161105ae1b98a1238f97645f2f588438b2949c99a2af9616bf" 77 | dependencies = [ 78 | "libc", 79 | "winapi", 80 | ] 81 | 82 | [[package]] 83 | name = "futures" 84 | version = "0.3.19" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" 87 | dependencies = [ 88 | "futures-channel", 89 | "futures-core", 90 | "futures-executor", 91 | "futures-io", 92 | "futures-sink", 93 | "futures-task", 94 | "futures-util", 95 | ] 96 | 97 | [[package]] 98 | name = "futures-channel" 99 | version = "0.3.19" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" 102 | dependencies = [ 103 | "futures-core", 104 | "futures-sink", 105 | ] 106 | 107 | [[package]] 108 | name = "futures-core" 109 | version = "0.3.19" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" 112 | 113 | [[package]] 114 | name = "futures-executor" 115 | version = "0.3.19" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" 118 | dependencies = [ 119 | "futures-core", 120 | "futures-task", 121 | "futures-util", 122 | ] 123 | 124 | [[package]] 125 | name = "futures-io" 126 | version = "0.3.19" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" 129 | 130 | [[package]] 131 | name = "futures-macro" 132 | version = "0.3.19" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" 135 | dependencies = [ 136 | "proc-macro2", 137 | "quote", 138 | "syn", 139 | ] 140 | 141 | [[package]] 142 | name = "futures-sink" 143 | version = "0.3.19" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" 146 | 147 | [[package]] 148 | name = "futures-task" 149 | version = "0.3.19" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" 152 | 153 | [[package]] 154 | name = "futures-util" 155 | version = "0.3.19" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" 158 | dependencies = [ 159 | "futures-channel", 160 | "futures-core", 161 | "futures-io", 162 | "futures-macro", 163 | "futures-sink", 164 | "futures-task", 165 | "memchr", 166 | "pin-project-lite", 167 | "pin-utils", 168 | "slab", 169 | ] 170 | 171 | [[package]] 172 | name = "hashbrown" 173 | version = "0.11.2" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 176 | 177 | [[package]] 178 | name = "hermit-abi" 179 | version = "0.1.19" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 182 | dependencies = [ 183 | "libc", 184 | ] 185 | 186 | [[package]] 187 | name = "idna" 188 | version = "0.2.3" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 191 | dependencies = [ 192 | "matches", 193 | "unicode-bidi", 194 | "unicode-normalization", 195 | ] 196 | 197 | [[package]] 198 | name = "indexmap" 199 | version = "1.8.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" 202 | dependencies = [ 203 | "autocfg", 204 | "hashbrown", 205 | ] 206 | 207 | [[package]] 208 | name = "instant" 209 | version = "0.1.12" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 212 | dependencies = [ 213 | "cfg-if", 214 | ] 215 | 216 | [[package]] 217 | name = "itoa" 218 | version = "1.0.1" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" 221 | 222 | [[package]] 223 | name = "lazy_static" 224 | version = "1.4.0" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 227 | 228 | [[package]] 229 | name = "libc" 230 | version = "0.2.112" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" 233 | 234 | [[package]] 235 | name = "libloading" 236 | version = "0.7.3" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" 239 | dependencies = [ 240 | "cfg-if", 241 | "winapi", 242 | ] 243 | 244 | [[package]] 245 | name = "lock_api" 246 | version = "0.4.5" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" 249 | dependencies = [ 250 | "scopeguard", 251 | ] 252 | 253 | [[package]] 254 | name = "log" 255 | version = "0.4.14" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 258 | dependencies = [ 259 | "cfg-if", 260 | ] 261 | 262 | [[package]] 263 | name = "matches" 264 | version = "0.1.9" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 267 | 268 | [[package]] 269 | name = "memchr" 270 | version = "2.4.1" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 273 | 274 | [[package]] 275 | name = "mio" 276 | version = "0.7.14" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" 279 | dependencies = [ 280 | "libc", 281 | "log", 282 | "miow", 283 | "ntapi", 284 | "winapi", 285 | ] 286 | 287 | [[package]] 288 | name = "miow" 289 | version = "0.3.7" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 292 | dependencies = [ 293 | "winapi", 294 | ] 295 | 296 | [[package]] 297 | name = "napi-deno" 298 | version = "0.1.0" 299 | dependencies = [ 300 | "deno_core", 301 | "libloading", 302 | "napi_sym", 303 | "tokio", 304 | ] 305 | 306 | [[package]] 307 | name = "napi_sym" 308 | version = "0.0.0" 309 | dependencies = [ 310 | "proc-macro2", 311 | "quote", 312 | "syn", 313 | ] 314 | 315 | [[package]] 316 | name = "ntapi" 317 | version = "0.3.6" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 320 | dependencies = [ 321 | "winapi", 322 | ] 323 | 324 | [[package]] 325 | name = "num_cpus" 326 | version = "1.13.1" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 329 | dependencies = [ 330 | "hermit-abi", 331 | "libc", 332 | ] 333 | 334 | [[package]] 335 | name = "once_cell" 336 | version = "1.9.0" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" 339 | 340 | [[package]] 341 | name = "parking_lot" 342 | version = "0.11.2" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 345 | dependencies = [ 346 | "instant", 347 | "lock_api", 348 | "parking_lot_core", 349 | ] 350 | 351 | [[package]] 352 | name = "parking_lot_core" 353 | version = "0.8.5" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 356 | dependencies = [ 357 | "cfg-if", 358 | "instant", 359 | "libc", 360 | "redox_syscall", 361 | "smallvec", 362 | "winapi", 363 | ] 364 | 365 | [[package]] 366 | name = "percent-encoding" 367 | version = "2.1.0" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 370 | 371 | [[package]] 372 | name = "pin-project" 373 | version = "1.0.10" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" 376 | dependencies = [ 377 | "pin-project-internal", 378 | ] 379 | 380 | [[package]] 381 | name = "pin-project-internal" 382 | version = "1.0.10" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" 385 | dependencies = [ 386 | "proc-macro2", 387 | "quote", 388 | "syn", 389 | ] 390 | 391 | [[package]] 392 | name = "pin-project-lite" 393 | version = "0.2.8" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" 396 | 397 | [[package]] 398 | name = "pin-utils" 399 | version = "0.1.0" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 402 | 403 | [[package]] 404 | name = "proc-macro2" 405 | version = "1.0.36" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" 408 | dependencies = [ 409 | "unicode-xid", 410 | ] 411 | 412 | [[package]] 413 | name = "quote" 414 | version = "1.0.14" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" 417 | dependencies = [ 418 | "proc-macro2", 419 | ] 420 | 421 | [[package]] 422 | name = "redox_syscall" 423 | version = "0.2.10" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" 426 | dependencies = [ 427 | "bitflags", 428 | ] 429 | 430 | [[package]] 431 | name = "ryu" 432 | version = "1.0.9" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" 435 | 436 | [[package]] 437 | name = "scopeguard" 438 | version = "1.1.0" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 441 | 442 | [[package]] 443 | name = "serde" 444 | version = "1.0.133" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" 447 | dependencies = [ 448 | "serde_derive", 449 | ] 450 | 451 | [[package]] 452 | name = "serde_bytes" 453 | version = "0.11.5" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" 456 | dependencies = [ 457 | "serde", 458 | ] 459 | 460 | [[package]] 461 | name = "serde_derive" 462 | version = "1.0.133" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" 465 | dependencies = [ 466 | "proc-macro2", 467 | "quote", 468 | "syn", 469 | ] 470 | 471 | [[package]] 472 | name = "serde_json" 473 | version = "1.0.75" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79" 476 | dependencies = [ 477 | "indexmap", 478 | "itoa", 479 | "ryu", 480 | "serde", 481 | ] 482 | 483 | [[package]] 484 | name = "serde_v8" 485 | version = "0.25.0" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "f393dfbff517625ec0d87f449c8778f5645ebff9408f70988cf9a9ac33525934" 488 | dependencies = [ 489 | "serde", 490 | "serde_bytes", 491 | "v8", 492 | ] 493 | 494 | [[package]] 495 | name = "signal-hook-registry" 496 | version = "1.4.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 499 | dependencies = [ 500 | "libc", 501 | ] 502 | 503 | [[package]] 504 | name = "slab" 505 | version = "0.4.5" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" 508 | 509 | [[package]] 510 | name = "smallvec" 511 | version = "1.8.0" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" 514 | 515 | [[package]] 516 | name = "syn" 517 | version = "1.0.86" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" 520 | dependencies = [ 521 | "proc-macro2", 522 | "quote", 523 | "unicode-xid", 524 | ] 525 | 526 | [[package]] 527 | name = "tinyvec" 528 | version = "1.5.1" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" 531 | dependencies = [ 532 | "tinyvec_macros", 533 | ] 534 | 535 | [[package]] 536 | name = "tinyvec_macros" 537 | version = "0.1.0" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 540 | 541 | [[package]] 542 | name = "tokio" 543 | version = "1.15.0" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" 546 | dependencies = [ 547 | "bytes", 548 | "libc", 549 | "memchr", 550 | "mio", 551 | "num_cpus", 552 | "once_cell", 553 | "parking_lot", 554 | "pin-project-lite", 555 | "signal-hook-registry", 556 | "tokio-macros", 557 | "winapi", 558 | ] 559 | 560 | [[package]] 561 | name = "tokio-macros" 562 | version = "1.7.0" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" 565 | dependencies = [ 566 | "proc-macro2", 567 | "quote", 568 | "syn", 569 | ] 570 | 571 | [[package]] 572 | name = "unicode-bidi" 573 | version = "0.3.7" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" 576 | 577 | [[package]] 578 | name = "unicode-normalization" 579 | version = "0.1.19" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 582 | dependencies = [ 583 | "tinyvec", 584 | ] 585 | 586 | [[package]] 587 | name = "unicode-xid" 588 | version = "0.2.2" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 591 | 592 | [[package]] 593 | name = "url" 594 | version = "2.2.2" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 597 | dependencies = [ 598 | "form_urlencoded", 599 | "idna", 600 | "matches", 601 | "percent-encoding", 602 | "serde", 603 | ] 604 | 605 | [[package]] 606 | name = "v8" 607 | version = "0.36.0" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "506523e86ccc15982be412bdde87a142771c139e94a8ecedda1da051a079b81d" 610 | dependencies = [ 611 | "bitflags", 612 | "fslock", 613 | "lazy_static", 614 | "libc", 615 | "which", 616 | ] 617 | 618 | [[package]] 619 | name = "which" 620 | version = "4.2.2" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" 623 | dependencies = [ 624 | "either", 625 | "lazy_static", 626 | "libc", 627 | ] 628 | 629 | [[package]] 630 | name = "winapi" 631 | version = "0.3.9" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 634 | dependencies = [ 635 | "winapi-i686-pc-windows-gnu", 636 | "winapi-x86_64-pc-windows-gnu", 637 | ] 638 | 639 | [[package]] 640 | name = "winapi-i686-pc-windows-gnu" 641 | version = "0.4.0" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 644 | 645 | [[package]] 646 | name = "winapi-x86_64-pc-windows-gnu" 647 | version = "0.4.0" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 650 | -------------------------------------------------------------------------------- /test/parcel_optimizer_image.js: -------------------------------------------------------------------------------- 1 | const lib = dlopen( 2 | "./testdata/node_modules/@parcel/optimizer-image/parcel-image.darwin-arm64.node", 3 | ); 4 | 5 | // JPEG image data for `./test/parcel_optimizer_image.jpeg` 6 | // deno-fmt-ignore 7 | const original = new Uint8Array([ 8 | 255,216,255,219,0,132,0,8,6,6,7,6,5,8,7,7,7,9,9,8,10,12,20,13,12,11,11,12,25,18,19,15,20,29,26,31,30,29,26,28,28,32,36,46,39,32,34,44,35,28,28,40,55,41,44,48,49,52,52,52,31,39,57,61,56,50,60,46,51,52,50,1,9,9,9,12,11,12,24,13,13,24,50,33,28,33,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,255,192,0,17,8,0,224,0,224,3,1,34,0,2,17,1,3,17,1,255,196,1,162,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,250,255,218,0,12,3,1,0,2,17,3,17,0,63,0,215,127,135,62,31,104,157,90,40,138,158,184,184,148,126,66,165,212,60,1,163,106,119,210,223,221,162,73,115,47,14,255,0,104,149,75,109,1,71,3,0,112,0,233,219,53,176,47,34,61,25,79,227,74,110,61,197,85,152,28,250,124,53,240,226,255,0,203,180,103,235,113,55,248,212,223,240,174,188,55,255,0,62,54,191,247,246,111,241,173,175,56,211,126,210,105,234,35,24,252,57,240,207,252,249,219,255,0,223,233,255,0,248,170,97,248,111,225,181,233,99,109,255,0,129,23,31,252,85,110,153,155,208,211,76,167,251,191,173,26,129,140,191,14,252,51,187,97,176,182,59,191,233,234,228,99,255,0,31,167,159,134,190,23,143,231,146,214,202,53,29,162,187,184,144,143,192,72,49,249,214,212,55,179,91,190,248,220,33,246,92,212,207,123,44,248,243,221,156,14,133,84,6,31,78,42,90,99,71,60,60,11,225,24,154,57,45,52,86,243,227,112,232,237,117,48,10,70,48,66,239,61,197,61,60,39,161,37,130,217,127,100,90,189,186,200,102,219,36,147,159,156,128,51,204,153,206,0,239,93,42,166,153,36,91,94,234,234,51,234,209,169,31,248,237,65,42,91,143,185,117,230,127,192,25,105,36,187,141,152,35,193,190,24,255,0,160,14,157,255,0,125,79,255,0,199,42,84,240,119,134,7,95,15,216,31,248,28,223,252,114,180,227,13,35,97,20,177,244,3,53,32,182,157,142,4,19,183,252,0,213,88,70,72,240,127,133,63,232,91,176,255,0,190,165,255,0,226,233,195,193,254,20,255,0,161,114,195,243,151,255,0,139,171,210,25,35,125,142,17,91,251,164,96,211,76,184,25,56,3,220,26,44,5,81,224,239,10,127,208,183,99,255,0,125,201,255,0,197,210,255,0,194,27,225,51,211,195,182,31,247,212,159,252,93,88,251,66,228,12,156,154,83,52,141,247,118,15,194,157,128,174,60,31,225,33,183,119,134,244,230,255,0,190,207,243,99,74,124,37,225,86,27,27,195,150,34,60,231,96,105,2,231,24,232,26,166,18,63,252,245,165,60,244,147,245,165,202,4,11,225,63,8,227,7,195,186,105,31,237,134,35,245,99,79,255,0,132,111,194,11,211,194,250,47,254,3,255,0,245,234,76,131,211,105,250,10,80,71,168,166,162,5,83,225,223,10,229,149,124,49,163,16,221,55,90,169,199,226,121,253,106,172,190,19,240,212,167,43,225,237,53,7,162,194,171,90,185,95,239,138,112,97,253,255,0,210,142,80,50,147,194,186,37,187,43,219,232,182,49,77,30,10,72,145,0,202,65,206,84,130,49,248,85,213,178,136,116,137,127,22,111,95,173,77,189,127,189,82,3,71,42,1,130,5,217,179,11,143,199,252,105,171,97,108,27,43,10,134,245,220,223,252,85,60,204,15,240,154,4,137,159,226,165,200,128,65,101,23,153,206,63,28,250,125,106,85,130,49,255,0,44,211,254,251,147,255,0,138,164,243,211,253,191,206,131,56,254,237,28,136,46,103,170,191,241,100,125,26,159,177,63,188,106,45,235,253,227,72,101,30,102,207,47,228,245,239,86,4,227,203,61,31,60,227,173,46,87,210,171,53,196,109,191,141,188,246,254,95,253,122,105,186,136,103,45,140,12,159,97,64,22,203,47,183,30,244,211,34,231,239,47,231,84,140,241,171,133,64,193,88,255,0,10,18,57,239,159,233,64,186,92,125,201,49,233,176,250,208,5,205,224,156,100,115,239,72,36,255,0,100,127,223,85,92,182,225,133,66,1,255,0,100,96,255,0,133,57,121,164,4,254,99,122,26,103,218,61,191,95,254,189,51,203,95,238,255,0,58,112,31,236,15,200,119,164,2,249,200,87,56,27,253,113,86,83,83,189,136,126,234,121,84,127,215,67,252,142,69,64,112,6,72,92,82,130,115,159,151,30,148,1,162,186,254,162,83,100,144,193,48,255,0,166,171,145,250,99,249,85,57,167,105,14,69,133,146,159,246,68,128,126,141,253,41,129,151,212,126,116,237,203,253,225,249,210,176,12,88,206,55,149,69,39,166,9,56,163,203,30,159,248,233,255,0,61,169,219,191,119,138,103,156,115,140,255,0,227,162,168,9,4,75,254,207,229,83,45,163,77,247,74,159,164,209,143,253,154,170,153,79,60,244,255,0,100,82,121,133,128,39,229,207,35,29,232,3,75,251,30,245,190,236,12,223,238,58,31,235,81,29,46,242,63,191,107,56,255,0,128,102,168,135,231,28,15,192,84,169,123,50,244,154,84,250,18,42,117,2,71,129,215,239,67,40,250,161,168,142,204,145,184,241,86,6,171,126,157,46,231,252,27,255,0,173,79,26,222,162,6,62,210,92,14,187,163,82,15,230,40,212,10,184,62,134,148,47,251,45,87,14,173,47,241,193,98,255,0,91,127,254,189,40,213,34,63,123,79,182,147,253,208,87,249,81,112,42,43,15,203,143,188,41,217,79,51,59,71,231,83,54,161,102,126,238,148,87,60,159,244,166,28,254,2,171,75,112,173,254,174,216,71,255,0,109,75,127,58,119,1,73,95,81,249,253,105,71,149,232,127,58,168,198,97,213,199,52,245,222,79,14,79,25,233,84,5,13,242,250,143,243,248,208,64,113,201,36,99,60,156,126,153,197,14,137,242,102,23,227,174,87,173,59,30,92,123,12,12,220,131,184,103,219,219,244,161,129,16,65,30,249,11,6,30,129,191,196,154,113,140,141,217,145,88,3,146,71,82,113,215,61,123,31,202,156,99,80,192,20,228,114,48,125,186,144,79,211,138,152,41,79,187,30,62,138,15,175,244,63,206,149,192,135,97,216,66,56,39,119,32,1,207,233,197,75,26,102,62,6,115,250,255,0,156,82,52,50,160,224,178,133,24,25,94,57,56,231,252,105,145,249,166,53,32,50,227,169,34,134,192,153,84,255,0,125,255,0,63,254,189,60,35,129,149,102,35,212,55,249,246,168,68,110,6,75,96,30,41,124,175,44,229,203,59,122,249,188,115,245,164,34,101,3,145,243,111,29,79,97,79,168,132,97,75,101,144,127,8,207,97,233,211,158,189,105,118,159,81,250,127,133,3,21,89,51,157,193,151,208,28,212,133,215,56,197,49,66,47,83,249,10,81,141,219,179,199,173,0,59,205,30,139,64,144,122,39,235,77,37,23,27,134,51,211,61,233,201,229,224,145,142,61,40,1,1,92,227,122,231,158,222,156,31,230,63,58,24,71,129,215,7,24,244,52,198,49,144,142,35,193,95,148,115,244,206,63,28,84,167,63,39,222,224,224,115,64,13,219,147,129,206,58,251,211,6,195,146,3,115,192,56,231,161,231,61,135,24,255,0,245,213,251,77,54,227,80,96,177,196,100,3,248,186,1,249,245,173,139,127,8,204,234,175,115,63,149,142,118,160,220,71,226,122,126,20,174,7,52,74,239,206,56,160,74,131,210,187,101,240,158,152,189,86,98,253,159,121,207,110,148,217,188,37,99,39,250,150,146,30,221,115,69,192,227,6,1,193,102,206,49,140,119,166,239,79,70,231,218,183,46,188,49,125,8,65,26,172,235,159,224,56,56,250,30,43,38,84,150,222,70,142,101,42,227,130,165,112,84,251,129,66,98,34,220,167,162,103,241,168,252,224,122,70,69,57,100,64,248,92,21,245,24,199,242,244,35,243,165,4,179,109,12,219,189,23,175,233,244,170,2,63,48,129,147,211,214,154,211,48,234,8,165,114,77,194,16,199,105,206,254,14,73,207,4,28,241,223,168,52,255,0,41,114,128,179,142,191,120,226,157,208,200,247,72,58,150,57,233,207,74,23,121,144,224,109,192,238,126,188,126,180,241,176,244,115,249,154,87,30,92,123,135,80,55,16,56,205,43,129,89,145,31,255,0,217,167,52,100,28,146,114,125,249,169,64,135,56,59,1,224,124,190,221,186,125,57,164,87,70,36,24,192,43,219,111,255,0,88,81,112,12,149,27,90,82,79,60,238,254,157,63,253,126,212,140,70,9,50,19,201,83,150,35,167,92,255,0,42,92,38,112,200,7,213,72,239,81,224,30,124,163,242,140,177,35,191,83,146,78,79,95,255,0,87,96,64,241,198,197,183,71,185,55,100,103,156,99,156,227,169,169,85,66,111,37,85,143,183,76,140,227,240,255,0,235,83,64,2,66,132,99,156,238,32,12,28,254,60,241,140,123,82,133,98,78,204,131,198,73,97,199,56,233,245,226,144,11,134,114,135,228,207,82,119,125,223,167,175,231,78,39,119,88,199,231,86,108,180,251,155,215,2,8,252,205,167,107,56,206,7,126,121,246,63,165,108,232,250,11,75,39,155,112,138,171,208,171,38,63,3,250,115,83,113,153,118,90,109,197,243,110,138,54,113,235,156,86,167,252,34,119,45,247,154,63,199,222,186,232,45,226,183,77,145,198,20,123,84,216,164,7,25,15,131,229,242,247,75,40,222,62,226,142,159,143,235,81,205,225,59,176,118,174,214,5,186,131,140,241,250,87,111,138,40,3,205,229,210,110,160,67,36,246,242,44,71,239,115,193,250,115,211,129,85,75,42,109,56,252,123,159,198,189,61,227,87,27,92,6,30,132,113,88,119,222,26,180,155,47,2,24,220,253,238,249,207,167,191,52,92,14,45,152,50,0,138,138,231,238,182,220,237,63,129,25,252,255,0,26,208,211,180,201,117,27,149,77,174,160,31,157,137,231,234,59,214,46,179,226,157,11,193,183,223,98,213,214,226,226,229,200,15,21,153,7,201,221,202,228,146,188,224,131,142,114,27,159,126,239,195,90,214,137,171,89,183,246,76,193,150,61,187,193,92,21,44,50,51,234,113,159,198,152,27,176,197,28,11,182,52,10,61,135,169,205,60,191,189,41,231,165,68,228,122,244,164,3,252,207,122,80,222,245,70,27,164,144,100,96,140,227,34,173,3,64,19,100,122,213,11,221,46,211,80,27,165,140,23,94,140,56,62,223,90,181,186,133,124,158,180,1,195,234,186,12,182,50,102,20,50,67,192,198,121,244,199,255,0,95,216,86,91,198,160,16,160,111,29,121,200,7,232,107,210,231,135,237,16,52,101,219,30,163,173,112,26,150,142,182,51,57,12,164,15,153,118,169,249,122,1,159,126,191,253,106,105,129,81,99,220,50,167,35,216,154,98,198,146,100,0,62,129,176,7,224,63,207,20,217,22,13,219,174,101,10,153,3,121,108,116,235,207,79,243,210,149,143,152,236,121,3,177,24,63,150,126,181,66,29,133,86,218,25,11,122,3,207,167,175,176,167,160,86,44,21,185,79,189,150,28,28,100,231,167,24,197,86,87,219,151,119,220,123,55,32,46,58,15,97,215,145,233,219,2,159,43,137,8,141,209,21,215,213,115,207,78,253,6,115,250,208,5,52,23,56,44,202,197,128,201,11,208,14,185,231,61,128,255,0,235,208,36,98,184,19,101,8,13,198,222,135,156,254,189,251,31,113,82,6,129,63,120,39,140,128,6,245,99,206,225,247,125,185,228,99,233,235,81,187,33,127,42,49,191,146,220,51,49,220,57,13,142,121,199,111,106,27,24,212,243,21,114,20,178,244,36,116,207,3,159,195,63,83,193,227,53,32,108,97,12,138,84,46,87,142,48,73,206,125,120,35,25,161,36,98,204,202,19,230,224,110,27,88,241,211,3,0,250,242,125,120,235,151,152,196,125,23,167,41,148,63,41,192,206,61,191,150,63,32,6,5,99,32,222,67,183,103,193,224,228,240,50,114,58,116,235,140,122,211,127,123,247,87,43,176,133,96,200,0,249,179,140,12,112,115,199,235,83,178,171,2,16,184,101,56,200,56,199,35,191,67,208,243,138,158,218,1,36,241,194,249,59,254,82,70,226,23,208,114,113,142,73,247,238,41,48,58,159,6,168,26,92,140,65,0,201,145,235,140,14,191,228,119,174,140,62,239,186,160,86,125,189,183,217,109,194,68,119,118,36,12,103,143,74,176,174,106,16,23,119,82,238,168,21,253,233,219,169,129,46,234,110,250,110,234,97,96,59,208,3,140,184,234,105,124,207,113,85,100,152,103,24,230,179,229,190,41,191,154,135,43,23,24,220,240,175,28,91,54,173,241,3,83,148,201,28,169,231,121,97,88,12,5,0,15,152,122,124,167,30,213,234,62,5,251,38,147,160,195,4,17,199,26,255,0,22,6,59,119,239,235,138,241,95,26,73,169,104,94,44,189,156,220,76,18,229,252,216,91,0,166,204,97,84,14,153,25,32,241,211,7,185,173,15,15,120,222,91,59,136,226,191,184,242,163,217,247,131,17,27,251,146,62,117,56,238,15,60,231,52,212,238,107,236,180,62,142,142,242,35,209,179,85,117,157,57,117,173,38,123,34,230,38,145,72,89,17,217,118,158,196,237,32,156,122,103,6,185,189,35,83,142,120,99,144,72,57,228,115,187,38,186,107,75,213,144,224,96,156,102,139,153,56,216,226,188,63,225,159,17,248,78,243,11,61,189,246,152,207,150,140,59,135,136,30,165,67,103,32,30,118,231,140,156,19,128,43,191,89,115,222,164,220,175,218,141,136,189,5,50,91,184,3,205,87,50,249,110,50,113,158,158,245,56,31,62,106,9,145,91,57,35,158,191,236,212,200,168,216,178,146,156,226,168,106,246,73,123,102,126,68,222,159,119,35,56,250,112,113,248,83,162,194,201,203,227,234,106,232,101,104,249,20,69,137,163,203,229,89,21,242,240,24,177,193,221,133,207,35,142,185,35,175,90,64,93,148,254,247,116,177,141,197,118,227,229,232,71,78,254,189,251,86,207,136,34,142,29,65,217,80,7,99,150,218,15,254,60,123,247,233,89,170,194,72,247,35,142,70,65,7,32,240,112,65,35,158,56,245,232,107,91,146,85,41,41,10,153,69,28,252,172,172,50,112,123,117,61,186,31,95,173,53,160,105,4,161,10,43,110,3,59,72,56,94,159,117,189,15,182,73,62,149,100,178,18,67,50,147,198,64,198,227,232,0,61,73,245,62,131,214,133,104,252,192,24,117,99,187,115,49,201,4,250,158,71,212,118,110,59,211,17,67,18,44,49,182,242,21,27,10,193,113,180,224,145,207,4,116,160,195,39,35,202,125,188,100,136,198,1,238,70,78,120,198,58,250,240,105,210,42,135,216,236,131,3,230,203,21,61,64,200,97,131,220,116,35,191,62,178,162,49,98,20,166,214,218,193,66,129,150,224,131,144,51,159,229,129,154,0,102,233,163,149,35,25,207,82,75,114,56,199,29,189,61,49,219,217,171,16,67,181,200,223,180,49,36,103,30,132,96,156,103,129,199,191,214,156,65,3,39,96,36,224,6,32,109,62,135,215,183,110,255,0,133,47,156,170,16,144,163,146,48,64,7,131,233,207,29,123,142,190,230,164,97,110,165,202,50,59,9,20,225,131,46,58,147,199,79,115,199,94,159,74,219,181,210,110,32,150,59,200,145,100,104,223,12,160,125,229,199,208,145,207,60,119,231,165,100,216,200,209,201,19,192,63,117,140,225,113,180,140,244,192,227,31,238,227,129,93,254,149,113,44,182,106,242,33,4,251,231,119,211,52,152,19,32,50,4,144,21,81,232,69,89,8,61,106,180,151,0,77,140,252,190,138,41,230,82,6,79,74,72,108,145,152,32,200,52,193,55,233,88,250,158,169,21,141,188,147,187,98,48,50,73,60,1,235,88,222,27,241,93,134,189,191,236,115,9,118,54,15,184,237,249,209,204,87,41,217,249,222,226,161,146,114,42,49,154,134,120,100,104,29,80,237,98,188,30,184,160,86,41,94,106,105,7,204,73,39,166,43,159,155,82,45,35,130,91,53,143,168,233,94,33,190,212,227,187,179,187,123,59,40,63,117,21,180,177,110,251,71,205,150,114,135,149,4,231,4,252,216,0,158,73,167,207,104,99,144,249,217,19,14,163,61,43,150,178,103,85,27,25,254,35,211,160,215,108,218,27,184,213,129,206,27,161,83,234,190,245,228,90,140,159,102,187,109,54,226,53,89,237,211,202,73,7,10,232,163,229,62,160,149,244,62,158,134,189,194,72,55,39,34,188,247,197,30,29,143,80,215,162,115,218,45,178,14,140,228,19,180,103,243,63,64,61,104,161,125,141,165,30,111,132,229,44,60,73,173,120,117,16,216,92,226,55,254,23,93,200,58,116,29,127,201,175,82,240,7,196,161,171,202,44,111,128,75,220,228,50,156,44,159,65,219,175,74,243,253,82,206,211,78,17,196,45,132,179,73,254,173,2,228,245,199,79,173,102,217,205,113,166,106,2,230,120,30,221,35,145,163,113,229,237,42,195,131,199,95,149,176,79,208,142,230,186,25,157,74,86,220,250,174,11,192,113,243,30,122,86,132,115,110,234,107,144,209,167,146,75,40,140,133,3,237,232,27,35,243,173,180,185,17,240,72,63,141,9,156,109,27,33,135,168,168,38,234,195,215,167,189,86,107,232,98,235,38,202,173,53,225,142,233,28,204,204,165,113,180,17,180,251,250,231,219,53,50,99,138,38,27,94,78,73,251,213,110,41,143,152,85,254,80,58,147,218,171,70,203,44,153,81,138,183,112,138,44,220,133,24,11,206,208,65,63,150,41,197,13,156,142,191,112,14,164,36,7,10,131,118,197,30,189,240,6,78,120,231,56,24,21,142,172,226,126,64,60,146,216,228,110,3,119,57,239,156,250,117,207,92,212,243,52,173,115,35,190,74,238,0,169,39,7,240,108,227,169,227,219,241,170,137,243,162,25,20,197,149,9,185,182,247,247,206,15,222,39,29,57,28,86,168,204,150,70,216,168,10,32,109,164,124,237,233,247,184,233,159,194,149,164,8,187,255,0,119,194,237,27,151,111,79,195,142,189,7,35,143,124,85,48,194,38,6,97,26,72,201,242,128,54,179,168,235,156,1,234,56,201,235,197,44,172,34,102,204,78,65,7,114,133,99,140,129,140,250,14,185,62,163,156,99,146,224,50,41,124,193,133,222,2,242,187,28,168,32,231,159,175,4,99,30,254,244,225,251,185,84,16,59,41,200,36,145,128,49,207,39,166,114,216,232,122,228,96,14,164,101,91,3,39,144,59,147,134,233,232,118,243,130,120,239,218,50,168,33,216,188,238,234,64,43,192,246,24,4,242,58,250,250,213,0,146,78,164,184,117,198,35,14,11,124,163,31,83,242,250,28,117,224,246,60,200,102,98,64,80,168,170,72,101,97,247,79,108,14,163,145,254,115,154,81,17,142,85,148,35,133,3,231,49,162,228,158,189,120,199,0,112,115,219,165,69,204,110,27,25,224,48,61,23,131,211,11,146,49,243,114,71,60,250,212,129,163,166,33,159,82,84,149,153,35,13,184,176,249,122,122,99,183,255,0,94,187,121,103,10,170,20,109,93,191,40,21,231,74,242,36,153,141,74,176,7,103,0,109,32,244,0,115,207,242,174,218,59,161,45,156,87,44,54,167,168,228,84,201,141,19,25,132,119,41,17,32,182,205,217,167,201,63,59,119,54,62,149,149,13,196,147,94,151,192,201,92,15,97,90,139,16,110,180,144,217,203,107,58,5,199,137,46,86,57,111,37,182,183,87,15,136,143,50,99,160,99,215,7,175,4,116,198,121,173,77,43,194,122,117,149,240,188,180,105,34,149,255,0,215,148,218,171,54,51,247,148,12,103,159,188,0,39,28,147,90,235,0,18,124,188,84,254,121,143,248,79,224,69,36,172,83,101,192,177,140,231,3,29,105,11,68,122,21,244,235,94,93,227,255,0,136,87,30,28,158,43,120,147,15,32,222,204,127,132,110,199,30,189,127,151,173,113,90,15,196,221,86,227,196,54,209,188,239,60,111,40,89,16,174,70,9,231,244,170,185,54,62,128,101,85,82,84,0,199,239,18,51,159,165,115,218,181,189,187,198,197,147,239,127,16,171,235,116,179,71,242,182,239,165,103,234,114,127,162,184,207,35,167,189,103,37,161,165,61,25,231,247,122,178,233,59,210,121,162,85,245,99,250,96,119,247,172,59,189,90,221,34,135,81,104,46,101,130,237,164,218,209,0,220,169,193,39,144,1,61,137,39,138,211,214,252,59,123,172,253,158,231,77,212,94,222,230,44,171,38,226,20,140,241,141,190,156,253,105,154,127,195,249,239,28,182,177,169,79,41,56,12,22,66,93,143,95,188,78,79,190,65,168,166,173,177,232,60,76,34,180,90,156,222,156,215,122,214,173,44,250,110,146,151,179,171,69,228,180,169,145,108,21,91,42,121,193,201,108,243,158,70,113,158,157,133,167,195,123,155,219,213,212,117,251,182,184,156,48,99,28,99,42,61,190,157,200,24,207,189,118,122,15,135,52,221,18,35,29,140,88,44,119,62,255,0,152,159,206,182,222,88,214,62,8,252,235,67,146,117,185,138,48,91,69,4,40,177,199,129,245,164,37,124,206,166,164,184,150,37,76,41,32,158,213,157,27,187,207,214,162,70,37,241,27,73,247,142,107,66,210,208,110,84,245,233,158,113,80,219,162,255,0,124,254,85,167,8,10,48,8,207,173,84,99,220,150,203,48,199,179,248,5,71,170,223,195,97,101,230,200,172,84,157,164,1,220,255,0,133,90,139,230,235,89,158,37,130,91,141,34,67,26,163,236,59,200,115,193,30,156,241,248,214,132,156,36,199,115,11,185,93,227,80,73,25,32,130,15,28,146,61,113,252,88,20,162,55,222,188,48,203,48,117,41,140,228,21,206,73,231,233,156,242,49,142,241,165,193,1,252,212,145,73,32,133,102,193,25,36,246,39,185,60,123,83,154,118,18,109,88,89,162,3,162,196,161,67,117,206,24,243,193,234,6,114,79,173,0,66,238,176,143,178,128,100,147,128,97,143,105,193,32,242,114,23,28,231,156,99,243,24,120,93,133,247,110,46,27,33,36,96,25,178,112,126,232,219,199,3,24,4,227,29,1,220,147,78,242,41,100,31,188,40,124,183,242,201,0,140,144,56,32,228,250,99,7,190,105,226,226,112,185,37,139,110,11,195,41,199,29,9,202,228,103,28,99,144,56,25,166,34,172,82,71,185,137,218,89,0,223,212,113,211,36,231,61,48,14,127,250,212,177,186,36,72,155,212,51,32,5,139,113,216,247,1,73,57,238,61,42,44,153,10,43,22,114,165,138,130,197,121,60,147,215,223,176,4,102,155,231,177,105,6,10,146,79,94,129,186,14,158,193,73,201,233,86,5,153,6,85,127,118,164,15,184,158,102,51,207,78,84,237,236,63,187,207,78,212,141,37,198,100,87,1,164,206,70,27,112,92,231,35,144,59,112,125,115,142,181,27,50,171,164,132,184,27,177,183,118,14,79,108,103,25,198,71,79,83,219,152,182,16,1,104,157,178,65,206,192,74,242,0,224,255,0,9,201,61,7,122,144,47,71,32,105,91,38,7,98,126,117,76,135,220,7,0,114,121,235,212,250,87,163,219,217,91,27,5,130,72,195,46,208,10,177,246,239,239,94,127,160,91,187,234,214,113,249,88,64,71,18,134,32,125,226,71,37,129,60,96,127,58,244,166,101,61,6,41,88,12,153,172,173,237,95,124,64,169,219,219,154,141,102,199,82,42,221,231,53,143,56,100,239,70,192,95,107,128,128,62,70,79,189,86,123,180,255,0,158,181,153,61,238,216,249,32,99,166,107,18,243,80,159,46,19,0,212,74,72,184,171,153,191,16,244,203,93,102,209,68,174,198,72,201,9,33,56,218,56,233,249,99,167,124,246,175,41,240,228,113,89,248,129,95,107,58,169,202,224,100,142,216,32,125,79,62,222,245,233,242,66,243,159,222,200,93,189,15,74,72,236,227,139,247,145,34,43,14,115,180,100,113,250,208,167,161,78,44,232,45,181,201,76,9,152,10,212,55,186,147,206,118,133,242,199,177,255,0,10,172,151,24,78,84,110,244,237,77,8,95,177,172,42,77,216,214,17,187,34,136,178,73,242,22,21,98,59,185,224,151,121,36,211,146,15,106,152,219,238,234,42,41,94,197,206,197,209,173,52,255,0,42,169,86,245,21,103,206,117,139,44,114,61,107,54,59,117,89,50,156,125,106,212,146,185,139,96,80,126,158,245,186,77,238,98,236,34,78,204,249,12,28,30,156,244,21,122,8,128,27,143,6,169,172,101,81,91,10,92,117,29,43,78,205,79,201,188,26,190,81,50,220,74,222,181,167,12,71,228,230,171,194,169,140,226,174,69,77,35,38,203,176,140,84,178,68,147,64,209,184,202,145,180,143,90,137,24,213,133,52,196,121,182,177,167,13,55,82,17,70,152,143,110,213,43,242,128,15,27,70,120,7,39,252,69,100,195,26,219,90,146,68,161,75,18,225,148,40,231,0,134,218,0,3,37,185,29,122,131,156,227,175,241,157,188,138,45,174,162,101,87,13,130,89,177,159,199,25,199,94,1,31,210,185,57,188,214,151,38,80,133,190,96,26,2,242,22,57,229,48,195,60,103,57,207,94,188,144,65,140,49,180,16,75,26,237,96,203,128,210,12,110,96,78,208,78,57,251,189,0,39,142,217,169,178,199,148,84,69,80,118,169,110,167,24,28,3,130,50,122,113,215,243,175,20,178,25,217,196,200,86,32,11,31,37,207,81,156,169,221,145,223,60,55,231,82,249,229,162,96,110,19,127,36,143,56,130,164,110,5,89,65,111,238,224,147,216,241,130,65,160,69,57,216,172,123,17,102,141,79,30,102,24,6,234,123,46,113,192,4,19,219,214,171,178,121,162,9,67,64,29,243,179,144,51,128,58,147,184,147,215,232,59,96,98,164,37,138,200,161,155,205,56,44,14,220,228,99,61,21,123,15,115,207,228,151,4,73,20,133,119,140,158,163,106,224,140,225,91,24,244,233,146,64,198,122,214,128,72,54,166,205,193,219,229,201,220,153,192,11,193,62,163,32,19,215,166,122,243,85,144,237,102,149,9,3,36,8,254,78,172,64,200,101,4,99,185,35,28,112,64,60,85,146,55,141,229,48,135,45,201,220,9,228,240,49,128,6,122,99,4,117,247,158,213,26,226,95,34,21,98,75,128,1,28,177,32,0,59,243,232,125,71,94,13,64,26,30,17,136,55,136,70,216,226,85,69,46,234,189,55,96,124,216,10,7,127,126,189,107,209,152,214,118,133,164,46,147,167,0,220,220,56,253,225,237,159,231,250,158,131,154,188,212,192,173,113,207,78,107,58,112,173,213,107,77,212,85,25,212,80,196,115,247,80,6,25,61,43,34,230,208,227,126,107,164,184,140,19,180,114,42,131,68,205,242,149,24,172,229,29,77,34,206,121,130,40,220,3,103,233,81,249,111,183,119,56,245,173,214,178,79,55,110,211,142,189,41,26,200,68,126,110,83,57,197,69,141,110,103,91,91,142,175,83,121,123,23,118,14,61,106,251,90,133,141,177,223,167,189,86,148,152,212,17,248,3,212,127,141,101,40,232,84,24,232,146,174,24,70,9,244,168,45,70,248,183,119,171,136,55,199,207,110,190,245,116,214,132,205,234,68,81,62,78,42,117,141,23,130,48,223,222,52,211,30,59,84,165,75,199,183,31,55,173,108,145,149,199,172,102,56,157,159,175,185,21,52,39,53,82,61,249,216,78,71,64,15,244,173,59,104,135,173,48,108,179,6,68,124,241,87,35,53,89,113,156,84,240,154,8,47,197,83,169,170,137,37,88,74,0,231,252,100,113,166,198,158,79,152,89,243,206,210,0,193,234,88,143,81,92,34,48,145,26,88,36,132,169,206,24,96,41,5,65,25,35,1,142,118,158,156,142,164,231,158,251,197,208,238,209,26,92,100,195,32,97,185,200,28,156,100,227,130,64,57,228,28,99,241,28,18,201,153,28,11,165,8,167,44,251,149,114,0,60,177,229,178,1,235,199,0,243,198,40,24,58,41,102,86,43,32,46,90,55,0,186,163,40,7,128,73,81,130,84,224,48,206,8,201,197,42,186,199,110,36,137,110,95,43,180,58,185,38,51,129,215,123,17,158,123,231,7,35,218,171,92,65,28,169,44,114,64,226,20,229,131,70,172,23,35,0,252,220,19,211,32,251,14,162,172,34,170,162,192,19,133,39,103,205,242,144,6,71,241,114,167,156,14,2,224,128,0,163,160,140,244,17,108,117,91,115,18,142,80,186,96,41,0,118,32,159,189,215,31,253,122,138,28,196,193,84,66,158,90,229,74,224,18,7,60,17,128,49,144,114,71,4,100,245,169,84,73,26,134,2,38,98,114,90,222,54,44,221,207,43,150,39,229,244,3,223,129,81,188,123,83,238,202,28,143,188,34,96,197,142,115,156,46,71,79,239,244,250,85,48,38,119,132,66,102,145,84,166,220,153,158,44,141,216,198,226,193,113,140,146,63,30,163,161,219,240,110,158,183,154,170,207,42,42,34,1,50,236,97,182,81,150,0,227,25,28,129,206,114,121,207,190,12,114,9,150,41,60,151,7,106,190,233,152,200,170,88,96,156,6,218,164,114,189,56,35,25,57,25,236,60,5,110,209,71,119,59,58,2,216,95,45,112,172,190,133,130,241,158,59,118,3,210,132,7,111,41,253,222,42,155,57,169,37,151,222,171,171,134,143,4,138,104,68,82,202,222,134,169,75,35,122,26,183,37,83,145,132,95,120,131,67,2,187,151,61,133,64,89,188,228,76,47,61,105,243,95,194,135,202,202,231,215,53,65,181,91,127,49,206,239,152,112,6,42,24,209,103,3,205,169,37,84,84,195,12,158,191,133,54,41,18,120,147,28,63,173,70,247,113,249,100,185,10,203,216,156,26,69,38,48,156,29,189,143,79,106,161,36,177,188,123,92,133,97,208,147,138,145,238,193,147,104,25,27,122,214,118,163,34,152,60,192,54,143,83,89,72,214,59,154,54,46,4,9,147,138,211,137,148,117,21,129,167,35,172,121,118,220,125,186,86,196,83,133,251,195,53,80,122,19,61,203,82,178,129,146,49,75,30,12,131,223,165,82,146,125,233,201,245,253,41,240,94,39,218,10,241,136,151,63,86,63,254,163,90,25,217,154,11,110,8,223,86,35,249,78,7,90,134,43,149,206,220,113,78,105,209,6,241,64,15,14,230,78,14,106,212,82,98,177,196,155,38,206,227,143,90,185,111,118,178,116,193,169,11,26,241,63,25,237,87,99,106,206,134,84,39,104,233,90,16,46,58,213,8,135,85,68,151,73,186,137,219,3,203,35,56,207,74,242,168,93,141,172,112,205,3,74,241,183,62,88,109,164,243,199,25,32,242,203,213,121,36,113,206,59,79,24,234,191,102,138,27,32,187,68,223,51,188,152,218,20,48,245,234,113,147,199,76,115,92,76,177,197,112,138,39,18,56,249,64,157,128,59,206,62,83,128,48,9,3,29,58,109,25,193,192,76,164,66,96,17,90,255,0,164,217,91,58,73,132,40,216,64,138,220,21,42,23,230,228,156,227,131,140,112,27,150,198,246,54,8,140,37,16,12,240,0,120,99,99,233,130,197,125,14,122,231,140,144,113,82,153,224,93,209,172,113,225,129,216,222,83,176,32,41,206,8,25,63,123,57,62,167,168,7,44,142,121,74,155,135,158,54,94,136,32,223,230,158,48,118,48,35,36,224,30,20,99,31,46,112,48,238,34,165,194,71,242,153,9,98,219,93,252,221,135,39,28,22,82,7,76,99,130,73,193,160,73,108,202,160,68,178,224,125,200,213,127,119,156,224,237,110,7,190,20,116,231,61,106,154,197,109,103,60,45,124,16,163,31,144,177,81,203,3,156,14,73,228,175,115,156,240,120,0,50,65,53,187,60,49,5,141,9,255,0,87,27,109,39,57,32,4,82,131,156,224,224,22,60,96,142,65,189,196,93,115,51,71,16,72,195,176,66,90,41,101,10,152,199,39,17,146,7,39,3,175,81,198,50,107,212,244,59,8,180,221,33,21,92,52,210,143,50,86,220,14,88,142,128,128,6,0,192,206,59,10,241,155,169,98,128,239,121,237,100,1,183,50,97,130,110,24,192,42,95,44,115,192,59,114,51,237,93,109,191,196,93,42,219,74,182,132,180,140,193,66,115,22,221,192,0,50,0,227,158,180,108,7,117,53,216,7,5,134,126,181,45,177,243,6,71,32,119,175,50,139,226,45,133,245,215,150,129,227,56,206,246,27,87,159,127,106,239,188,59,123,5,237,130,207,19,137,6,51,185,14,85,135,177,20,196,105,180,121,170,23,112,231,160,205,106,1,80,205,16,165,112,57,43,219,66,175,189,14,72,233,154,200,186,72,210,80,72,96,91,152,220,14,245,215,221,198,152,206,43,141,213,46,149,39,75,111,239,146,80,250,103,173,101,36,90,53,96,119,107,125,234,113,208,84,82,2,100,109,195,59,250,123,84,182,242,168,132,46,56,35,112,252,122,84,235,16,123,132,79,238,47,62,245,37,21,97,182,101,27,216,229,189,59,85,29,74,36,146,221,213,137,199,160,174,157,173,130,199,197,115,94,34,242,237,237,221,142,224,121,233,73,173,6,158,164,186,123,196,17,21,50,194,180,252,147,140,246,174,107,193,151,81,94,105,176,187,54,226,223,197,158,43,179,75,98,78,65,202,250,82,136,73,152,215,112,200,253,9,29,122,123,213,40,93,162,155,203,102,204,129,185,247,231,255,0,175,93,20,209,19,216,87,51,122,134,222,250,41,75,0,55,101,137,233,207,21,76,72,216,47,42,145,134,228,183,31,167,249,252,233,242,188,128,190,91,13,180,12,30,149,74,13,73,39,105,90,28,17,23,67,89,154,142,166,22,213,101,14,127,120,251,23,158,231,165,38,199,107,154,187,141,229,231,44,118,42,252,184,56,244,235,91,150,118,204,145,227,53,151,161,219,130,161,216,103,114,143,241,174,166,8,42,162,137,147,44,219,70,222,130,180,18,170,66,8,234,49,87,16,213,144,115,158,52,130,3,163,71,60,219,0,134,85,195,185,194,174,79,86,246,206,62,135,21,196,164,145,177,6,63,155,106,245,218,114,71,113,185,6,7,82,64,200,224,131,138,211,241,7,138,155,83,55,122,125,138,199,185,100,63,49,145,193,202,182,62,101,85,39,111,203,187,175,64,7,122,229,109,194,92,249,78,209,67,113,113,16,62,94,66,36,109,201,39,10,93,152,110,32,229,182,122,30,49,82,203,69,248,174,140,177,31,44,167,156,233,147,230,71,185,148,145,130,50,132,2,121,199,126,222,216,86,118,121,130,72,60,213,124,146,171,25,96,196,12,224,140,147,208,244,36,140,122,30,43,50,54,251,84,240,125,164,46,214,3,107,92,78,161,6,64,195,43,0,196,100,96,241,140,110,57,7,113,197,239,51,109,177,115,105,46,221,202,74,220,78,10,21,7,7,35,112,25,56,200,194,131,208,17,77,9,152,119,14,241,200,164,54,22,81,180,43,96,241,158,79,110,57,233,211,243,53,12,183,8,73,85,35,97,82,26,69,222,220,30,15,94,49,156,231,223,25,197,74,215,141,246,68,49,220,38,194,227,228,218,74,30,188,228,17,147,140,244,62,184,205,71,115,44,151,39,13,185,226,135,230,27,208,96,100,114,70,112,122,14,160,131,192,227,160,174,139,18,83,14,138,133,21,88,166,205,177,74,46,121,32,5,4,109,83,142,227,158,56,199,173,82,117,146,109,239,229,152,84,252,152,8,164,133,236,73,61,63,29,223,168,34,210,218,197,26,74,83,105,86,228,111,35,118,14,15,241,99,129,215,0,156,112,79,36,212,169,106,36,183,102,70,199,57,57,201,33,187,18,79,126,189,9,239,218,135,176,28,220,150,140,36,144,136,139,168,31,42,175,59,78,236,14,221,120,63,151,106,246,15,133,51,163,232,247,22,225,230,204,50,229,145,142,84,231,169,28,159,199,182,107,205,103,141,163,1,86,70,44,120,221,179,129,193,231,161,0,227,60,15,231,94,133,240,163,79,185,18,222,93,240,150,206,21,112,64,4,190,125,63,207,222,168,98,61,56,84,82,26,182,74,102,161,145,144,99,223,167,189,67,99,49,47,195,44,79,32,7,30,152,175,21,241,119,137,158,199,196,243,36,123,74,66,0,3,61,216,43,127,35,252,235,222,110,66,58,58,227,143,90,249,255,0,226,127,134,236,237,239,78,171,109,112,170,243,54,36,135,57,37,134,48,87,211,129,205,75,87,25,215,120,70,219,83,213,17,47,174,174,35,72,138,166,212,81,147,145,212,147,249,246,174,238,218,206,56,215,36,146,222,181,228,190,22,241,141,173,158,157,107,101,116,30,19,26,170,225,126,233,231,28,253,120,175,67,183,241,5,181,212,136,45,238,80,169,82,73,12,56,35,31,253,122,130,141,247,219,229,158,71,30,245,200,120,194,202,75,141,34,227,203,127,159,97,97,142,248,230,147,87,241,26,216,220,91,73,44,251,109,153,204,76,127,186,72,200,63,248,233,174,95,196,62,38,154,43,105,35,25,103,110,6,57,12,61,126,158,212,134,84,248,79,127,115,113,5,206,159,47,91,86,4,22,29,51,156,143,192,131,199,74,246,56,226,99,212,245,244,175,26,248,97,170,233,186,84,215,171,121,113,28,87,87,18,110,13,35,5,82,15,64,185,239,157,223,167,173,122,157,158,187,111,125,49,75,105,162,145,87,33,157,28,48,227,168,4,85,49,92,211,158,45,209,237,81,134,245,174,103,196,90,100,247,150,50,195,25,10,89,78,214,62,253,43,165,107,133,231,230,28,12,117,172,29,91,85,142,198,212,207,59,170,168,236,199,31,197,138,139,150,143,15,159,197,26,222,137,121,45,131,206,81,226,194,178,237,227,31,215,52,243,227,91,157,68,67,111,229,32,59,212,147,157,160,55,169,244,25,164,241,188,150,250,167,136,164,150,212,9,4,113,133,119,78,132,250,102,183,190,23,105,186,96,187,154,242,238,20,123,216,36,30,73,126,124,177,215,56,245,247,173,20,116,185,159,54,167,178,104,99,54,168,197,10,22,95,186,70,8,174,142,5,172,251,23,86,40,21,84,26,215,136,167,165,8,76,80,42,43,187,209,97,166,93,94,60,109,40,183,137,164,40,49,151,42,51,198,120,7,138,186,187,49,156,113,235,84,181,200,165,155,67,189,91,120,196,178,180,12,17,10,130,24,145,199,7,138,160,60,76,106,17,220,23,89,163,101,13,39,148,68,200,132,228,255,0,9,8,78,78,65,231,167,124,129,87,196,239,112,173,111,50,74,140,185,44,165,145,131,19,140,3,187,14,79,0,227,111,7,175,108,210,139,203,123,120,194,184,101,220,60,163,10,17,32,24,24,31,49,59,9,195,28,227,129,156,227,173,90,83,0,142,120,174,46,124,178,9,146,68,151,99,198,84,103,12,62,108,41,32,247,29,207,222,193,196,22,88,18,129,52,7,204,50,43,68,166,52,141,194,231,57,10,73,44,184,250,242,58,224,19,140,36,169,117,229,71,44,127,232,238,174,119,171,6,97,180,99,140,128,10,178,128,48,78,91,144,72,53,44,81,25,100,145,163,185,119,142,53,254,0,132,130,196,103,4,142,58,30,48,58,251,0,181,218,6,93,177,201,112,38,149,78,20,177,72,100,117,199,70,35,1,7,94,157,120,200,224,146,196,206,120,51,61,190,69,192,133,211,1,217,8,145,148,245,200,36,30,217,227,129,80,44,146,22,107,120,210,230,95,227,5,130,66,7,112,114,66,158,157,135,92,241,236,68,182,233,120,34,222,4,138,187,118,178,249,123,72,25,198,49,131,219,232,58,85,179,98,68,146,74,183,201,32,127,157,82,48,71,56,3,56,36,150,239,143,160,244,174,166,64,219,91,41,196,103,50,200,152,228,128,122,182,0,192,249,142,222,158,180,175,121,34,176,129,200,145,183,32,230,66,196,103,146,112,122,156,3,197,43,221,220,69,20,176,206,226,70,145,71,68,49,97,142,78,0,0,224,140,142,65,60,243,192,170,198,36,251,76,147,108,88,137,39,31,32,206,59,110,227,39,185,237,215,31,81,121,129,92,188,147,36,136,203,25,124,149,222,168,66,183,92,130,126,240,227,159,189,158,1,239,138,235,124,41,226,59,125,7,79,54,19,178,199,230,62,228,146,53,40,9,57,224,246,35,166,9,174,76,24,82,245,217,147,46,172,23,229,78,24,16,71,39,25,7,252,125,205,54,229,109,166,133,18,32,164,14,50,48,185,35,219,169,252,253,41,184,129,234,80,248,202,218,242,82,182,215,49,178,132,46,92,56,32,15,175,181,59,79,241,76,55,182,80,220,153,151,202,153,155,97,220,62,96,24,128,127,74,242,84,179,23,16,186,20,222,28,16,25,137,66,192,28,156,228,129,130,15,76,30,163,129,79,54,158,67,197,12,155,228,84,92,34,177,12,170,184,207,3,144,6,121,24,3,189,99,40,177,166,122,53,207,196,29,38,25,218,214,89,93,230,94,11,198,132,243,245,28,15,198,188,171,87,190,185,215,111,26,230,100,11,26,185,2,63,48,18,160,119,35,185,35,30,213,102,96,164,146,2,149,28,12,243,147,215,161,235,223,244,166,164,114,121,156,133,227,239,228,119,234,127,74,74,12,77,153,11,2,179,224,16,70,210,120,235,237,253,63,90,93,167,202,219,16,150,33,198,89,9,0,122,244,255,0,60,214,139,196,237,38,12,152,110,185,224,159,168,39,249,83,94,30,95,108,206,216,238,36,206,15,28,228,241,214,155,136,92,130,68,150,69,120,29,228,42,199,59,89,206,214,199,114,9,254,158,181,86,68,32,34,182,249,34,36,97,112,118,133,245,192,224,14,189,5,104,57,12,73,101,125,193,178,185,4,227,158,196,156,143,255,0,85,68,177,174,84,242,72,60,252,197,79,251,220,127,142,105,88,46,82,54,238,89,119,38,120,251,160,96,177,237,159,122,214,180,212,47,180,233,124,219,123,215,12,202,16,40,249,200,25,233,207,78,192,211,33,84,198,64,103,32,112,54,100,99,211,7,234,121,246,167,136,37,25,6,50,48,57,4,116,29,122,116,252,104,113,184,92,181,47,137,117,169,163,148,11,249,35,124,112,118,130,64,236,51,131,142,58,154,203,184,188,190,189,62,92,242,207,57,81,184,169,199,92,103,36,12,3,245,235,156,213,182,141,222,48,29,122,114,3,115,143,113,156,227,165,78,144,163,175,239,6,88,2,57,237,199,111,78,125,170,121,2,230,33,129,95,106,136,247,183,168,247,231,211,154,154,193,238,116,187,181,184,131,229,101,193,224,16,174,50,15,81,238,7,235,90,11,106,231,104,30,88,201,195,131,216,103,167,214,172,37,158,7,202,216,124,124,185,231,183,76,2,59,99,211,242,167,96,59,111,12,124,67,182,147,116,26,154,253,145,215,248,217,190,82,79,63,128,4,254,70,187,63,248,75,109,99,154,228,110,198,216,81,227,109,224,44,167,157,193,72,254,238,57,175,20,147,79,133,154,52,219,1,216,112,206,202,193,114,71,168,59,78,57,250,119,171,113,104,208,71,27,194,89,65,4,2,12,153,199,205,253,220,112,115,242,254,103,173,103,202,203,185,236,239,227,45,53,44,37,184,134,238,9,124,190,93,12,163,112,228,116,201,245,32,126,34,185,61,67,198,122,165,228,134,40,219,236,168,172,24,44,10,92,200,50,62,246,8,32,244,231,61,251,224,215,39,105,109,29,191,238,156,91,197,230,199,196,99,247,128,176,25,25,200,29,122,227,24,231,216,129,168,87,202,152,253,166,103,16,40,13,185,24,170,168,234,14,24,145,215,110,127,200,167,168,43,12,183,184,124,91,75,25,125,165,151,247,132,32,67,131,144,73,216,9,63,46,48,122,241,219,164,144,153,68,77,36,113,74,167,59,11,136,247,182,220,224,54,209,157,192,99,168,57,39,25,83,142,42,93,91,92,36,203,12,22,167,32,126,238,226,24,3,99,24,200,109,195,35,146,196,16,58,113,200,226,173,195,109,110,10,92,132,143,118,207,49,153,112,143,140,250,2,9,224,18,8,245,36,96,208,144,16,190,163,118,85,98,138,68,125,139,147,13,197,187,64,0,92,109,1,9,36,231,57,220,8,10,20,142,245,98,205,66,222,52,158,65,70,102,47,23,147,46,200,242,122,29,129,126,83,156,18,74,156,30,123,230,164,66,145,68,194,105,174,118,69,16,73,119,66,207,144,8,206,224,221,65,10,71,29,15,35,214,161,197,183,217,99,151,251,50,67,30,216,216,58,156,198,14,6,8,66,122,147,221,65,56,39,39,147,150,38,103,72,214,241,93,36,251,226,73,128,80,118,46,208,70,112,58,129,232,6,113,235,205,71,37,195,36,131,228,83,230,100,168,28,228,30,220,245,206,79,0,227,143,97,81,69,19,75,117,36,142,242,202,74,130,12,146,100,131,159,112,59,99,143,231,65,183,141,238,24,172,11,26,242,173,211,39,251,220,99,235,235,212,87,81,12,173,28,141,121,113,185,226,68,27,246,179,237,12,27,158,231,39,7,60,124,187,187,210,207,111,105,56,222,247,14,21,6,25,99,156,96,103,219,29,179,233,235,199,53,106,59,123,123,101,10,158,102,51,242,169,206,14,65,60,1,199,224,0,57,53,4,161,132,141,49,145,80,240,8,0,134,80,64,200,83,213,120,252,113,154,67,43,205,17,16,18,87,204,99,38,216,200,81,198,59,114,10,244,0,244,197,58,56,163,39,107,40,89,8,25,17,199,156,40,0,117,24,201,228,228,100,143,214,172,64,169,26,175,149,14,119,46,88,19,143,82,75,13,220,124,184,24,3,176,235,87,35,181,180,183,149,238,102,183,137,158,67,128,196,96,41,11,146,2,158,156,12,208,228,5,8,194,198,55,20,144,32,96,72,115,242,169,56,249,143,66,58,15,127,165,71,35,67,59,143,44,164,102,67,128,239,185,67,241,192,224,103,144,64,4,12,12,227,35,173,77,121,120,146,224,164,37,72,251,167,149,82,84,240,27,146,121,4,243,142,139,216,212,49,172,141,19,57,70,18,48,83,184,129,200,0,99,161,3,191,249,197,45,196,65,178,69,136,190,48,202,51,134,24,25,199,181,68,209,153,165,27,75,56,228,21,60,100,31,80,122,143,175,173,92,154,217,225,27,252,230,59,142,11,28,49,207,92,101,112,56,31,90,139,205,242,139,150,142,71,231,130,67,124,196,116,201,98,0,235,233,233,142,166,134,4,14,161,193,203,124,163,25,36,115,252,234,69,113,243,174,92,163,30,89,144,17,145,236,120,7,129,211,214,170,56,2,97,114,138,232,164,149,96,91,203,61,118,240,71,94,190,213,57,204,145,5,242,228,13,146,190,102,211,149,35,174,210,217,29,168,176,7,151,28,103,24,101,220,50,119,125,227,129,130,125,185,161,196,50,59,130,3,38,118,147,216,19,233,158,217,171,96,127,163,148,14,66,21,203,6,192,36,156,142,71,78,189,241,138,164,45,161,109,129,144,70,139,128,27,111,32,253,123,126,157,234,64,122,170,201,12,74,35,249,84,242,234,164,103,57,227,249,84,82,31,221,100,229,228,7,29,120,4,96,140,251,115,254,122,155,18,35,194,135,231,253,218,112,9,81,148,199,3,159,169,61,187,85,168,145,221,49,33,105,50,6,205,196,62,87,62,216,237,206,7,168,160,10,171,104,100,154,56,163,202,13,164,252,170,83,113,193,199,7,35,111,63,158,42,101,180,99,25,24,57,76,6,114,163,60,30,122,115,159,240,169,69,176,222,192,183,150,225,113,128,65,76,123,228,113,208,244,20,244,181,151,108,83,73,114,129,92,46,255,0,55,39,0,16,66,142,120,206,241,207,160,30,134,165,177,140,88,20,66,172,60,173,197,136,86,111,189,208,227,4,130,0,57,57,199,95,151,233,82,173,163,39,149,18,140,224,101,190,98,161,1,206,88,14,135,25,29,186,84,242,193,254,142,162,85,87,83,129,150,59,188,204,142,65,219,129,198,58,49,28,227,29,241,90,43,123,85,148,50,219,161,231,228,119,81,185,64,198,8,118,39,62,195,29,170,88,14,251,50,92,66,18,43,146,204,171,179,114,54,210,132,30,3,18,79,29,72,231,177,28,115,155,80,67,44,86,198,51,40,158,53,98,98,121,16,121,136,24,112,62,95,189,140,103,119,29,7,28,26,95,44,239,142,103,141,152,169,25,103,96,91,105,28,141,202,6,58,140,244,201,81,215,56,169,82,17,107,116,194,214,55,67,40,206,216,223,121,5,114,84,237,99,200,232,56,32,115,208,96,98,75,44,124,146,2,34,14,174,192,150,253,238,3,31,151,39,28,99,167,228,195,142,115,74,247,13,12,191,102,72,228,216,199,116,147,18,81,119,28,238,203,12,30,192,18,73,228,231,62,145,249,112,220,60,140,67,157,195,115,230,40,247,128,31,175,205,184,96,21,60,115,142,163,6,158,100,22,147,189,189,207,154,34,3,228,136,140,46,222,8,101,98,56,228,176,227,25,29,168,2,97,3,58,60,155,81,193,24,140,252,132,2,64,31,54,112,65,99,183,167,25,30,153,52,151,98,104,99,19,221,169,88,129,57,120,93,144,32,199,222,42,167,144,54,142,123,115,215,53,94,75,107,41,236,146,40,35,149,134,62,88,99,77,192,142,155,125,134,121,4,17,142,185,198,225,80,69,4,130,44,144,161,128,14,99,148,22,37,250,130,204,170,14,115,156,252,184,24,24,232,73,118,38,229,205,178,90,198,69,180,114,52,65,182,28,182,236,146,48,85,115,156,231,167,204,61,106,63,62,120,212,8,227,120,209,198,88,180,64,161,108,144,55,108,207,206,113,212,231,57,246,168,163,6,72,162,105,30,224,57,144,171,132,118,193,198,74,226,65,130,49,242,241,144,78,211,244,19,75,0,184,180,45,21,179,202,231,59,227,138,64,197,137,37,72,34,64,7,3,36,252,202,120,31,123,20,236,35,255,217 9 | ]) 10 | 11 | /** 12 | * declare export function optimize(type: string, buffer: Buffer): Buffer; 13 | */ 14 | const optimized = lib.optimize( 15 | "jpeg", 16 | original, 17 | ); 18 | 19 | print(optimized.byteLength < original.byteLength); // true 20 | --------------------------------------------------------------------------------