From 463180450247e5b1ee567353b19798b17326c0ae Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 23 Oct 2024 11:14:33 -0300 Subject: [PATCH 1/7] feat(runtime): add a Cargo feature flag to enable the ffi API The `ffi` ext is difficult to cross compile (see https://github.com/denoland/rusty_v8/issues/1640) --- runtime/Cargo.toml | 29 ++++++++++++++++--- runtime/errors.rs | 60 ++++++++++++++++++++++++++++++---------- runtime/js/90_deno_ns.js | 5 ++-- runtime/lib.rs | 2 ++ runtime/shared.rs | 1 - runtime/snapshot.rs | 2 ++ runtime/web_worker.rs | 1 + runtime/worker.rs | 1 + 8 files changed, 79 insertions(+), 22 deletions(-) diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index fbf5d958114d7f..bdf402e8534fed 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -10,6 +10,7 @@ repository.workspace = true description = "Provides the deno runtime library" [features] +default = ["ffi"] # "fake" feature that allows to generate docs on docs.rs docsrs = [] # A feature that allows excluding `./js/99_main.js` from the exported extension. @@ -27,6 +28,8 @@ hmr = ["include_js_files_for_snapshotting"] # conditionally exclude the runtime source transpilation logic, and add an # assertion that a snapshot is provided. only_snapshotted_js_sources = ["include_js_files_for_snapshotting"] +# enable the FFI API +ffi = ["deno_ffi"] [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tokio_unstable)'] } @@ -49,7 +52,7 @@ deno_core.workspace = true deno_cron.workspace = true deno_crypto.workspace = true deno_fetch.workspace = true -deno_ffi.workspace = true +deno_ffi = { workspace = true, optional = true } deno_fs = { workspace = true, features = ["sync_fs"] } deno_http.workspace = true deno_io.workspace = true @@ -80,7 +83,7 @@ deno_core.workspace = true deno_cron.workspace = true deno_crypto.workspace = true deno_fetch.workspace = true -deno_ffi.workspace = true +deno_ffi = { workspace = true, optional = true } deno_fs = { workspace = true, features = ["sync_fs"] } deno_http.workspace = true deno_io.workspace = true @@ -108,7 +111,13 @@ http.workspace = true http-body-util.workspace = true hyper.workspace = true hyper-util.workspace = true -hyper_v014 = { workspace = true, features = ["server", "stream", "http1", "http2", "runtime"] } +hyper_v014 = { workspace = true, features = [ + "server", + "stream", + "http1", + "http2", + "runtime", +] } libc.workspace = true log.workspace = true netif = "0.1.6" @@ -130,7 +139,19 @@ uuid.workspace = true which.workspace = true [target.'cfg(windows)'.dependencies] -winapi = { workspace = true, features = ["commapi", "knownfolders", "mswsock", "objbase", "psapi", "shlobj", "tlhelp32", "winbase", "winerror", "winuser", "winsock2"] } +winapi = { workspace = true, features = [ + "commapi", + "knownfolders", + "mswsock", + "objbase", + "psapi", + "shlobj", + "tlhelp32", + "winbase", + "winerror", + "winuser", + "winsock2", +] } ntapi = "0.4.0" windows-sys.workspace = true diff --git a/runtime/errors.rs b/runtime/errors.rs index 869f97968e7857..2fa0a909a58184 100644 --- a/runtime/errors.rs +++ b/runtime/errors.rs @@ -32,12 +32,10 @@ use deno_crypto::GenerateKeyError; use deno_crypto::ImportKeyError; use deno_fetch::FetchError; use deno_fetch::HttpClientCreateError; -use deno_ffi::CallError; -use deno_ffi::CallbackError; -use deno_ffi::DlfcnError; -use deno_ffi::IRError; -use deno_ffi::ReprError; -use deno_ffi::StaticError; +#[cfg(feature = "ffi")] +use deno_ffi::{ + CallError, CallbackError, DlfcnError, IRError, ReprError, StaticError, +}; use deno_fs::FsOpsError; use deno_http::HttpError; use deno_http::HttpNextError; @@ -504,6 +502,7 @@ fn get_web_blob_error_class(e: &BlobError) -> &'static str { } } +#[cfg(feature = "ffi")] fn get_ffi_repr_error_class(e: &ReprError) -> &'static str { match e { ReprError::InvalidOffset => "TypeError", @@ -527,6 +526,7 @@ fn get_ffi_repr_error_class(e: &ReprError) -> &'static str { } } +#[cfg(feature = "ffi")] fn get_ffi_dlfcn_error_class(e: &DlfcnError) -> &'static str { match e { DlfcnError::RegisterSymbol { .. } => "Error", @@ -536,6 +536,7 @@ fn get_ffi_dlfcn_error_class(e: &DlfcnError) -> &'static str { } } +#[cfg(feature = "ffi")] fn get_ffi_static_error_class(e: &StaticError) -> &'static str { match e { StaticError::Dlfcn(e) => get_ffi_dlfcn_error_class(e), @@ -545,6 +546,7 @@ fn get_ffi_static_error_class(e: &StaticError) -> &'static str { } } +#[cfg(feature = "ffi")] fn get_ffi_callback_error_class(e: &CallbackError) -> &'static str { match e { CallbackError::Resource(e) => get_error_class_name(e).unwrap_or("Error"), @@ -553,6 +555,7 @@ fn get_ffi_callback_error_class(e: &CallbackError) -> &'static str { } } +#[cfg(feature = "ffi")] fn get_ffi_call_error_class(e: &CallError) -> &'static str { match e { CallError::IR(_) => "TypeError", @@ -1021,8 +1024,18 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { .map(get_web_stream_resource_error_class) }) .or_else(|| e.downcast_ref::().map(get_web_blob_error_class)) - .or_else(|| e.downcast_ref::().map(|_| "TypeError")) - .or_else(|| e.downcast_ref::().map(get_ffi_repr_error_class)) + .or_else(|| { + #[cfg(feature = "ffi")] + return e.downcast_ref::().map(|_| "TypeError"); + #[cfg(not(feature = "ffi"))] + None + }) + .or_else(|| { + #[cfg(feature = "ffi")] + return e.downcast_ref::().map(get_ffi_repr_error_class); + #[cfg(not(feature = "ffi"))] + None + }) .or_else(|| e.downcast_ref::().map(get_http_error)) .or_else(|| e.downcast_ref::().map(get_http_next_error)) .or_else(|| { @@ -1031,18 +1044,35 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { }) .or_else(|| e.downcast_ref::().map(get_fs_error)) .or_else(|| { - e.downcast_ref::() - .map(get_ffi_dlfcn_error_class) + #[cfg(feature = "ffi")] + return e + .downcast_ref::() + .map(get_ffi_dlfcn_error_class); + #[cfg(not(feature = "ffi"))] + None + }) + .or_else(|| { + #[cfg(feature = "ffi")] + return e + .downcast_ref::() + .map(get_ffi_static_error_class); + #[cfg(not(feature = "ffi"))] + None }) .or_else(|| { - e.downcast_ref::() - .map(get_ffi_static_error_class) + #[cfg(feature = "ffi")] + return e + .downcast_ref::() + .map(get_ffi_callback_error_class); + #[cfg(not(feature = "ffi"))] + None }) .or_else(|| { - e.downcast_ref::() - .map(get_ffi_callback_error_class) + #[cfg(feature = "ffi")] + return e.downcast_ref::().map(get_ffi_call_error_class); + #[cfg(not(feature = "ffi"))] + None }) - .or_else(|| e.downcast_ref::().map(get_ffi_call_error_class)) .or_else(|| e.downcast_ref::().map(get_tls_error_class)) .or_else(|| e.downcast_ref::().map(get_cron_error_class)) .or_else(|| e.downcast_ref::().map(get_canvas_error)) diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index fd2ac00f2004c0..5f8302c774f74e 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -10,7 +10,6 @@ import { import * as timers from "ext:deno_web/02_timers.js"; import * as httpClient from "ext:deno_fetch/22_http_client.js"; import * as console from "ext:deno_console/01_console.js"; -import * as ffi from "ext:deno_ffi/00_ffi.js"; import * as net from "ext:deno_net/01_net.js"; import * as tls from "ext:deno_net/02_tls.js"; import * as serve from "ext:deno_http/00_serve.ts"; @@ -30,6 +29,8 @@ import * as kv from "ext:deno_kv/01_db.ts"; import * as cron from "ext:deno_cron/01_cron.ts"; import * as webgpuSurface from "ext:deno_webgpu/02_surface.js"; +const ffi = await import("ext:deno_ffi/00_ffi.js").catch(() => ({})); + const denoNs = { Process: process.Process, run: process.run, @@ -169,7 +170,7 @@ denoNsUnstableById[unstableIds.kv] = { denoNsUnstableById[unstableIds.net] = { listenDatagram: net.createListenDatagram( op_net_listen_udp, - op_net_listen_unixpacket, + op_net_listen_unixpacket ), }; diff --git a/runtime/lib.rs b/runtime/lib.rs index f0b1129ce3cf50..6c28ec0579adfa 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -8,6 +8,7 @@ pub use deno_core; pub use deno_cron; pub use deno_crypto; pub use deno_fetch; +#[cfg(feature = "ffi")] pub use deno_ffi; pub use deno_fs; pub use deno_http; @@ -69,6 +70,7 @@ pub static UNSTABLE_GRANULAR_FLAGS: &[UnstableGranularFlag] = &[ show_in_help: true, id: 2, }, + #[cfg(feature = "ffi")] UnstableGranularFlag { name: deno_ffi::UNSTABLE_FEATURE_NAME, help_text: "Enable unstable FFI APIs", diff --git a/runtime/shared.rs b/runtime/shared.rs index 02dfd18719d0b8..723e26446f8b5b 100644 --- a/runtime/shared.rs +++ b/runtime/shared.rs @@ -26,7 +26,6 @@ extension!(runtime, deno_crypto, deno_broadcast_channel, deno_node, - deno_ffi, deno_net, deno_napi, deno_http, diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs index 041132f9714d57..ee32d814ef6211 100644 --- a/runtime/snapshot.rs +++ b/runtime/snapshot.rs @@ -55,6 +55,7 @@ impl deno_fetch::FetchPermissions for Permissions { } } +#[cfg(feature = "ffi")] impl deno_ffi::FfiPermissions for Permissions { fn check_partial_no_path( &mut self, @@ -278,6 +279,7 @@ pub fn create_runtime_snapshot( deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm( deno_broadcast_channel::InMemoryBroadcastChannel::default(), ), + #[cfg(feature = "ffi")] deno_ffi::deno_ffi::init_ops_and_esm::(), deno_net::deno_net::init_ops_and_esm::(None, None), deno_tls::deno_tls::init_ops_and_esm(), diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 04cd3305e56ad7..7b707c1373137a 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -464,6 +464,7 @@ impl WebWorker { deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm( services.broadcast_channel, ), + #[cfg(feature = "ffi")] deno_ffi::deno_ffi::init_ops_and_esm::(), deno_net::deno_net::init_ops_and_esm::( services.root_cert_store_provider.clone(), diff --git a/runtime/worker.rs b/runtime/worker.rs index 477d3b880c98de..0b26d96f36b105 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -379,6 +379,7 @@ impl MainWorker { deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm( services.broadcast_channel.clone(), ), + #[cfg(feature = "ffi")] deno_ffi::deno_ffi::init_ops_and_esm::(), deno_net::deno_net::init_ops_and_esm::( services.root_cert_store_provider.clone(), From 6ca9ceb4543b86ceb481e05b0750d14c76c301c9 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 23 Oct 2024 11:27:15 -0300 Subject: [PATCH 2/7] remove ffi from namespace wip --- runtime/js/90_deno_ns.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 5f8302c774f74e..a42c166f4cb9a2 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -29,8 +29,6 @@ import * as kv from "ext:deno_kv/01_db.ts"; import * as cron from "ext:deno_cron/01_cron.ts"; import * as webgpuSurface from "ext:deno_webgpu/02_surface.js"; -const ffi = await import("ext:deno_ffi/00_ffi.js").catch(() => ({})); - const denoNs = { Process: process.Process, run: process.run, @@ -125,11 +123,11 @@ const denoNs = { uid: os.uid, Command: process.Command, ChildProcess: process.ChildProcess, - dlopen: ffi.dlopen, - UnsafeCallback: ffi.UnsafeCallback, - UnsafePointer: ffi.UnsafePointer, - UnsafePointerView: ffi.UnsafePointerView, - UnsafeFnPointer: ffi.UnsafeFnPointer, + dlopen: null, + UnsafeCallback: null, + UnsafePointer: null, + UnsafePointerView: null, + UnsafeFnPointer: null, umask: fs.umask, HttpClient: httpClient.HttpClient, createHttpClient: httpClient.createHttpClient, From 0d4a0729b831929f3df1e87e66a846f98152fb93 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 23 Oct 2024 11:33:21 -0300 Subject: [PATCH 3/7] mock ffi --- runtime/js/00_ffi.js | 1 + runtime/js/90_deno_ns.js | 11 ++++++----- runtime/shared.rs | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 runtime/js/00_ffi.js diff --git a/runtime/js/00_ffi.js b/runtime/js/00_ffi.js new file mode 100644 index 00000000000000..879c51e6e4ced7 --- /dev/null +++ b/runtime/js/00_ffi.js @@ -0,0 +1 @@ +// mock FFI interface in case the `ffi` Cargo feature is not enabled diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index a42c166f4cb9a2..35dd3a62702b64 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -10,6 +10,7 @@ import { import * as timers from "ext:deno_web/02_timers.js"; import * as httpClient from "ext:deno_fetch/22_http_client.js"; import * as console from "ext:deno_console/01_console.js"; +import * as ffi from "ext:deno_ffi/00_ffi.js"; import * as net from "ext:deno_net/01_net.js"; import * as tls from "ext:deno_net/02_tls.js"; import * as serve from "ext:deno_http/00_serve.ts"; @@ -123,11 +124,11 @@ const denoNs = { uid: os.uid, Command: process.Command, ChildProcess: process.ChildProcess, - dlopen: null, - UnsafeCallback: null, - UnsafePointer: null, - UnsafePointerView: null, - UnsafeFnPointer: null, + dlopen: ffi.dlopen, + UnsafeCallback: ffi.UnsafeCallback, + UnsafePointer: ffi.UnsafePointer, + UnsafePointerView: ffi.UnsafePointerView, + UnsafeFnPointer: ffi.UnsafeFnPointer, umask: fs.umask, HttpClient: httpClient.HttpClient, createHttpClient: httpClient.createHttpClient, diff --git a/runtime/shared.rs b/runtime/shared.rs index 723e26446f8b5b..e549d924e1b066 100644 --- a/runtime/shared.rs +++ b/runtime/shared.rs @@ -12,6 +12,9 @@ use deno_core::ModuleName; use deno_core::SourceMapData; use std::path::Path; +#[cfg(not(feature = "ffi"))] +extension!(deno_ffi, esm = ["js/00_ffi.js"]); + extension!(runtime, deps = [ deno_webidl, @@ -26,6 +29,7 @@ extension!(runtime, deno_crypto, deno_broadcast_channel, deno_node, + deno_ffi, deno_net, deno_napi, deno_http, From e403b976cf4fa436438599012f6947cb69d9d461 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 23 Oct 2024 11:42:24 -0300 Subject: [PATCH 4/7] init mock ext --- runtime/snapshot.rs | 2 ++ runtime/web_worker.rs | 2 ++ runtime/worker.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs index ee32d814ef6211..db6668b0774951 100644 --- a/runtime/snapshot.rs +++ b/runtime/snapshot.rs @@ -281,6 +281,8 @@ pub fn create_runtime_snapshot( ), #[cfg(feature = "ffi")] deno_ffi::deno_ffi::init_ops_and_esm::(), + #[cfg(not(feature = "ffi"))] + crate::shared::deno_ffi::init_ops_and_esm(), deno_net::deno_net::init_ops_and_esm::(None, None), deno_tls::deno_tls::init_ops_and_esm(), deno_kv::deno_kv::init_ops_and_esm( diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 7b707c1373137a..d8ad13033aad9b 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -466,6 +466,8 @@ impl WebWorker { ), #[cfg(feature = "ffi")] deno_ffi::deno_ffi::init_ops_and_esm::(), + #[cfg(not(feature = "ffi"))] + crate::shared::deno_ffi::init_ops_and_esm(), deno_net::deno_net::init_ops_and_esm::( services.root_cert_store_provider.clone(), options.unsafely_ignore_certificate_errors.clone(), diff --git a/runtime/worker.rs b/runtime/worker.rs index 0b26d96f36b105..6c1293f0195743 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -381,6 +381,8 @@ impl MainWorker { ), #[cfg(feature = "ffi")] deno_ffi::deno_ffi::init_ops_and_esm::(), + #[cfg(not(feature = "ffi"))] + crate::shared::deno_ffi::init_ops_and_esm(), deno_net::deno_net::init_ops_and_esm::( services.root_cert_store_provider.clone(), options.unsafely_ignore_certificate_errors.clone(), From 02d1d3c718d9e6d6485fc3a033243e3cf855b2ff Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 23 Oct 2024 11:49:15 -0300 Subject: [PATCH 5/7] fix path --- runtime/{js => }/00_ffi.js | 0 runtime/shared.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename runtime/{js => }/00_ffi.js (100%) diff --git a/runtime/js/00_ffi.js b/runtime/00_ffi.js similarity index 100% rename from runtime/js/00_ffi.js rename to runtime/00_ffi.js diff --git a/runtime/shared.rs b/runtime/shared.rs index e549d924e1b066..0487c23359d5f4 100644 --- a/runtime/shared.rs +++ b/runtime/shared.rs @@ -13,7 +13,7 @@ use deno_core::SourceMapData; use std::path::Path; #[cfg(not(feature = "ffi"))] -extension!(deno_ffi, esm = ["js/00_ffi.js"]); +extension!(deno_ffi, esm = ["00_ffi.js"]); extension!(runtime, deps = [ From 330d1cec08c6b4fbd8622c4d2257af532ce082ad Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 23 Oct 2024 15:12:14 -0300 Subject: [PATCH 6/7] format --- runtime/Cargo.toml | 22 ++-------------------- runtime/errors.rs | 14 +++++++++++--- runtime/js/90_deno_ns.js | 2 +- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index bdf402e8534fed..2d4095684734b6 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -111,13 +111,7 @@ http.workspace = true http-body-util.workspace = true hyper.workspace = true hyper-util.workspace = true -hyper_v014 = { workspace = true, features = [ - "server", - "stream", - "http1", - "http2", - "runtime", -] } +hyper_v014 = { workspace = true, features = ["server", "stream", "http1", "http2", "runtime"] } libc.workspace = true log.workspace = true netif = "0.1.6" @@ -139,19 +133,7 @@ uuid.workspace = true which.workspace = true [target.'cfg(windows)'.dependencies] -winapi = { workspace = true, features = [ - "commapi", - "knownfolders", - "mswsock", - "objbase", - "psapi", - "shlobj", - "tlhelp32", - "winbase", - "winerror", - "winuser", - "winsock2", -] } +winapi = { workspace = true, features = ["commapi", "knownfolders", "mswsock", "objbase", "psapi", "shlobj", "tlhelp32", "winbase", "winerror", "winuser", "winsock2"] } ntapi = "0.4.0" windows-sys.workspace = true diff --git a/runtime/errors.rs b/runtime/errors.rs index 2fa0a909a58184..43dd7647ca80b2 100644 --- a/runtime/errors.rs +++ b/runtime/errors.rs @@ -33,9 +33,17 @@ use deno_crypto::ImportKeyError; use deno_fetch::FetchError; use deno_fetch::HttpClientCreateError; #[cfg(feature = "ffi")] -use deno_ffi::{ - CallError, CallbackError, DlfcnError, IRError, ReprError, StaticError, -}; +use deno_ffi::CallError; +#[cfg(feature = "ffi")] +use deno_ffi::CallbackError; +#[cfg(feature = "ffi")] +use deno_ffi::DlfcnError; +#[cfg(feature = "ffi")] +use deno_ffi::IRError; +#[cfg(feature = "ffi")] +use deno_ffi::ReprError; +#[cfg(feature = "ffi")] +use deno_ffi::StaticError; use deno_fs::FsOpsError; use deno_http::HttpError; use deno_http::HttpNextError; diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 35dd3a62702b64..fd2ac00f2004c0 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -169,7 +169,7 @@ denoNsUnstableById[unstableIds.kv] = { denoNsUnstableById[unstableIds.net] = { listenDatagram: net.createListenDatagram( op_net_listen_udp, - op_net_listen_unixpacket + op_net_listen_unixpacket, ), }; From f356d9d9abf344b18a30a02aec30c7c2ce35420e Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 24 Oct 2024 07:33:50 -0300 Subject: [PATCH 7/7] copyright --- runtime/00_ffi.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/00_ffi.js b/runtime/00_ffi.js index 879c51e6e4ced7..c0ab6643d7e268 100644 --- a/runtime/00_ffi.js +++ b/runtime/00_ffi.js @@ -1 +1,3 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + // mock FFI interface in case the `ffi` Cargo feature is not enabled