Repository: wasmerio/wasmer (language: rust)

Issue:
Add V8 support to Wasmer
Following up from this discussion on Github: [https://github.com/wasmerio/wasmer/discussions/3839](https://github.com/wasmerio/wasmer/discussions/3839), and now that we support the `wasm_c_api` (via [https://github.com/wasmerio/wasmer/pull/4515](https://github.com/wasmerio/wasmer/pull/4515) ), we are now in a good step to fork `rusty_v8` (slightly) so it compiles with the wasm_c_api and can be used from Wasmer (`v8` feature)


Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 463eae8224e..a342ee99404 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4826,6 +4826,12 @@ dependencies = [
  "pest",
 ]
 
+[[package]]
+name = "seq-macro"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
+
 [[package]]
 name = "serde"
 version = "1.0.207"
@@ -6854,6 +6860,7 @@ dependencies = [
  "more-asserts",
  "rustc-demangle",
  "rusty_jsc",
+ "seq-macro",
  "serde",
  "serde-wasm-bindgen",
  "shared-buffer",
diff --git a/Cargo.toml b/Cargo.toml
index ece006d42f2..0334e6128f2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -165,6 +165,7 @@ default = [
 backend = []
 jsc = ["wasmer/jsc", "backend", "wat", "wasmer/std"]
 wamr = ["wasmer/wamr"]
+v8 = ["wasmer/v8"]
 wasmi = ["wasmer/wasmi"]
 engine = ["universal"]
 universal = []
diff --git a/Makefile b/Makefile
index 47ff178a935..3a5f92bb851 100644
--- a/Makefile
+++ b/Makefile
@@ -386,6 +386,9 @@ check-capi:
 
 build-wasmer:
 	$(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --release --manifest-path lib/cli/Cargo.toml $(compiler_features) --bin wasmer --locked
+	
+build-wasmer-v8:
+	$(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --release --manifest-path lib/cli/Cargo.toml --no-default-features --features="v8" --bin wasmer --locked
 
 build-wasmer-wamr:
 	$(CARGO_BINARY) build $(CARGO_TARGET_FLAG) --release --manifest-path lib/cli/Cargo.toml --no-default-features --features="wamr" --bin wasmer --locked
@@ -574,6 +577,11 @@ test-packages: test-stage-1-test-all test-stage-2-test-compiler-cranelift-nostd
 test-examples: test-stage-5-test-examples test-stage-6-test-examples-release
 
 
+test-v8: test-v8-api
+
+test-v8-api:
+	cargo nextest run --package=wasmer --release --features=v8 --no-default-features
+
 test-wamr: test-wamr-api
 
 test-wamr-api:
diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml
index 518ceb9a20b..2e1f5b41dca 100644
--- a/lib/api/Cargo.toml
+++ b/lib/api/Cargo.toml
@@ -38,6 +38,7 @@ wat = { version = "=1.216.0", optional = true }
 rustc-demangle = "0.1"
 shared-buffer = { workspace = true }
 wasmi_c_api = { version = "0.37.1", package = "wasmi_c_api_impl", optional = true }
+seq-macro = {version = "0.3.5", optional = true}
 
 # Dependencies and Development Dependencies for `sys`.
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
@@ -118,6 +119,7 @@ llvm = ["compiler", "wasmer-compiler-llvm"]
 engine = ["sys"]
 wamr = ["wasm-c-api", "std", "wat"]
 wasmi = ["wasm-c-api", "std", "wat", "dep:wasmi_c_api"]
+v8 = ["wasm-c-api", "std", "wat", "dep:seq-macro"]
 wasm-c-api = ["wasm-types-polyfill"]
 
 # - Deprecated features.
diff --git a/lib/api/build.rs b/lib/api/build.rs
index e24188ff77a..5351238438f 100644
--- a/lib/api/build.rs
+++ b/lib/api/build.rs
@@ -106,4 +106,78 @@ fn main() {
             .write_to_file(out_path.join("bindings.rs"))
             .expect("Couldn't write bindings");
     }
+
+    #[cfg(feature = "v8")]
+    {
+        use cmake::Config;
+        use std::{env, path::PathBuf};
+
+        let crate_root = env::var("CARGO_MANIFEST_DIR").unwrap();
+        let v8_cmake_dir = PathBuf::from(&crate_root)
+            .join("third_party")
+            .join("v8-cmake");
+
+        let mut fetch_submodules = std::process::Command::new("git");
+        fetch_submodules
+            .current_dir(crate_root)
+            .arg("submodule")
+            .arg("update")
+            .arg("--init");
+
+        let res = fetch_submodules.output();
+
+        if let Err(e) = res {
+            panic!("fetching submodules failed: {e}");
+        }
+
+        let dst = Config::new(v8_cmake_dir.clone())
+            .always_configure(true)
+            .generator("Ninja")
+            .define(
+                "CMAKE_BUILD_TYPE",
+                if cfg!(debug_assertions) {
+                    "RelWithDebInfo"
+                } else {
+                    "Release"
+                },
+            )
+            .build_target("wee8")
+            .build();
+
+        // Check output of `cargo build --verbose`, should see something like:
+        // -L native=/path/runng/target/debug/build/runng-sys-abc1234/out
+        // That contains output from cmake
+        println!(
+            "cargo:rustc-link-search=native={}",
+            dst.join("build").display()
+        );
+        println!("cargo:rustc-link-lib=wee8");
+        println!("cargo:rustc-link-lib=v8_initializers");
+        println!("cargo:rustc-link-lib=v8_libbase");
+        println!("cargo:rustc-link-lib=v8_base_without_compiler");
+        println!("cargo:rustc-link-lib=v8_compiler");
+        println!("cargo:rustc-link-lib=c++");
+        println!("cargo:rustc-link-lib=v8_libplatform");
+        println!("cargo:rustc-link-lib=v8_libsampler");
+        println!("cargo:rustc-link-lib=v8_snapshot");
+        println!("cargo:rustc-link-lib=v8_torque_generated");
+
+        let bindings = bindgen::Builder::default()
+            .header(
+                v8_cmake_dir
+                    .join("v8/third_party/wasm-api/wasm.h")
+                    .to_str()
+                    .unwrap(),
+            )
+            .derive_default(true)
+            .derive_debug(true)
+            .generate()
+            .expect("Unable to generate bindings for `v8`!");
+
+        let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
+
+        bindings
+            .write_to_file(out_path.join("bindings.rs"))
+            .expect("Couldn't write bindings");
+    }
 }
diff --git a/lib/api/src/c_api/as_c.rs b/lib/api/src/c_api/as_c.rs
index e3cd25f3db9..4ac660ba50b 100644
--- a/lib/api/src/c_api/as_c.rs
+++ b/lib/api/src/c_api/as_c.rs
@@ -1,9 +1,13 @@
 use crate::bindings::{
     wasm_extern_as_ref, wasm_func_as_ref, wasm_val_t, wasm_val_t__bindgen_ty_1,
-    wasm_valkind_enum_WASM_EXTERNREF, wasm_valkind_enum_WASM_F32, wasm_valkind_enum_WASM_F64,
-    wasm_valkind_enum_WASM_FUNCREF, wasm_valkind_enum_WASM_I32, wasm_valkind_enum_WASM_I64,
-    wasm_valkind_t, wasm_valtype_kind, wasm_valtype_t,
+    wasm_valkind_enum_WASM_F32, wasm_valkind_enum_WASM_F64, wasm_valkind_enum_WASM_FUNCREF,
+    wasm_valkind_enum_WASM_I32, wasm_valkind_enum_WASM_I64, wasm_valkind_t, wasm_valtype_kind,
+    wasm_valtype_t,
 };
+
+#[cfg(feature = "v8")]
+use crate::bindings::wasm_valkind_enum_WASM_ANYREF as wasm_valkind_enum_WASM_EXTERNREF;
+
 //use crate::js::externals::Function;
 // use crate::store::{Store, StoreObject};
 // use crate::js::RuntimeError;
@@ -35,6 +39,27 @@ pub trait AsC: Sized {
     ) -> Result<Self, Trap>;
 }
 
+#[cfg(feature = "v8")]
+#[inline]
+pub fn param_from_c(value: &wasm_val_t) -> Value {
+    match value.kind as u32 {
+        crate::bindings::wasm_valkind_enum_WASM_I32 => Value::I32(unsafe { value.of.i32_ }),
+        crate::bindings::wasm_valkind_enum_WASM_I64 => Value::I64(unsafe { value.of.i64_ }),
+        crate::bindings::wasm_valkind_enum_WASM_F32 => Value::F32(unsafe { value.of.f32_ }),
+        crate::bindings::wasm_valkind_enum_WASM_F64 => Value::F64(unsafe { value.of.f64_ }),
+        crate::bindings::wasm_valkind_enum_WASM_FUNCREF => {
+            Value::FuncRef(Some(Function(super::externals::function::Function {
+                handle: unsafe { value.of.ref_ as _ },
+            })))
+        }
+        crate::bindings::wasm_valkind_enum_WASM_ANYREF => {
+            panic!("ExternRefs are not currently supported through wasm_c_api")
+        }
+        _ => panic!("v8 curently does not support V128 values"),
+    }
+}
+
+#[cfg(any(feature = "wamr", feature = "wasmi"))]
 #[inline]
 pub fn param_from_c(value: &wasm_val_t) -> Value {
     match value.kind as u32 {
@@ -51,7 +76,15 @@ pub fn param_from_c(value: &wasm_val_t) -> Value {
             panic!("ExternRefs are not currently supported through wasm_c_api")
         }
 
-        _ => unimplemented!("V128 are not supported currently"),
+        _ => {
+            if cfg!(feature = "wamr") {
+                panic!("wamr currently does not support V128 values")
+            } else if cfg!(feature = "wamr") {
+                panic!("wasmi currently does not support V128 values")
+            } else {
+                panic!("this backend currently does not support V128 values")
+            }
+        }
     }
 }
 
@@ -99,7 +132,7 @@ pub fn result_to_value(param: &Value) -> wasm_val_t {
         }
     }
 
-    #[cfg(feature = "wasmi")]
+    #[cfg(any(feature = "wasmi", feature = "v8"))]
     {
         match param {
             Value::I32(val) => wasm_val_t {
@@ -144,7 +177,16 @@ pub fn type_to_c(type_: &Type) -> wasm_valkind_t {
         Type::F32 => wasm_valkind_enum_WASM_F32 as _,
         Type::F64 => wasm_valkind_enum_WASM_F64 as _,
         Type::FuncRef => wasm_valkind_enum_WASM_FUNCREF as _,
-        Type::ExternRef => wasm_valkind_enum_WASM_EXTERNREF as _,
+        Type::ExternRef => {
+            #[cfg(any(feature = "wasmi" , feature = "wamr"))]
+            {
+                crate::bindings::wasm_valkind_enum_WASM_EXTERNREF as _
+            }
+            #[cfg(feature = "v8")]
+            {
+                crate::bindings::wasm_valkind_enum_WASM_ANYREF as _
+            }
+        }
         Type::V128 => {
             #[cfg(feature = "wamr")]
             {
@@ -154,6 +196,10 @@ pub fn type_to_c(type_: &Type) -> wasm_valkind_t {
             {
                 panic!("wasmi does not support V128 kinds as of now");
             }
+            #[cfg(feature = "v8")]
+            {
+                panic!("v8 does not support V128 kinds as of now");
+            }
         }
     }
 }
@@ -189,4 +235,17 @@ pub fn valtype_to_type(type_: *const wasm_valtype_t) -> Type {
             type_
         ),
     }
+    #[cfg(feature = "v8")]
+    match type_ as u32 {
+        crate::bindings::wasm_valkind_enum_WASM_I32 => Type::I32,
+        crate::bindings::wasm_valkind_enum_WASM_I64 => Type::I64,
+        crate::bindings::wasm_valkind_enum_WASM_F32 => Type::F32,
+        crate::bindings::wasm_valkind_enum_WASM_F64 => Type::F64,
+        crate::bindings::wasm_valkind_enum_WASM_ANYREF => Type::ExternRef,
+        crate::bindings::wasm_valkind_enum_WASM_FUNCREF => Type::FuncRef,
+        _ => unreachable!(
+            "valtype {:?} has no matching valkind and therefore no matching wasmer_types::Type",
+            type_
+        ),
+    }
 }
diff --git a/lib/api/src/c_api/engine.rs b/lib/api/src/c_api/engine.rs
index 721c65c6c68..e8a933e00a2 100644
--- a/lib/api/src/c_api/engine.rs
+++ b/lib/api/src/c_api/engine.rs
@@ -6,14 +6,47 @@ pub(crate) struct CApiEngine {
     pub(crate) engine: *mut wasm_engine_t,
 }
 
+#[cfg(feature = "v8")]
+// A handle to an engine, which we want to unsafely mark as Sync.
+struct EngineCapsule(*mut wasm_engine_t);
+
+#[cfg(feature = "v8")]
+impl Drop for EngineCapsule {
+    fn drop(&mut self) {
+        unsafe { wasm_engine_delete(self.0) }
+    }
+}
+
+#[cfg(feature = "v8")]
+unsafe impl Sync for EngineCapsule {}
+
+#[cfg(feature = "v8")]
+unsafe impl Send for EngineCapsule {}
+
+#[cfg(feature = "v8")]
+static ENGINE: std::sync::OnceLock<std::sync::Mutex<EngineCapsule>> = std::sync::OnceLock::new();
+
 impl Default for CApiEngine {
+    #[cfg(not(feature = "v8"))]
     fn default() -> Self {
         let engine: *mut wasm_engine_t = unsafe { wasm_engine_new() };
         Self { engine }
     }
+
+    #[cfg(feature = "v8")]
+    fn default() -> Self {
+        let engine = ENGINE
+            .get_or_init(|| unsafe { std::sync::Mutex::new(EngineCapsule(wasm_engine_new())) });
+        let engine = unsafe { engine.lock().unwrap().0 };
+        Self { engine }
+    }
 }
 
 impl Drop for CApiEngine {
+    #[cfg(feature = "v8")]
+    fn drop(&mut self) {}
+
+    #[cfg(not(feature = "v8"))]
     fn drop(&mut self) {
         unsafe { wasm_engine_delete(self.engine) }
     }
diff --git a/lib/api/src/c_api/externals/function.rs b/lib/api/src/c_api/externals/function.rs
index 7953bff85af..7192383843e 100644
--- a/lib/api/src/c_api/externals/function.rs
+++ b/lib/api/src/c_api/externals/function.rs
@@ -37,6 +37,17 @@ use std::sync::Arc;
 
 use wasmer_types::{FunctionType, RawValue};
 
+#[cfg(any(feature = "wamr", feature = "wasmi"))]
+type CCallback = unsafe extern "C" fn(
+    *mut c_void,
+    *const wasm_val_vec_t,
+    *mut wasm_val_vec_t,
+) -> *mut wasm_trap_t;
+
+#[cfg(feature = "v8")]
+type CCallback =
+    unsafe extern "C" fn(*mut c_void, *const wasm_val_t, *mut wasm_val_t) -> *mut wasm_trap_t;
+
 #[derive(Clone, PartialEq)]
 pub struct Function {
     pub(crate) handle: VMFunction,
@@ -132,7 +143,7 @@ impl Function {
         let mut store = store.as_store_mut();
         let inner = store.inner.store.inner;
 
-        let callback = make_fn_callback(&func);
+        let callback: CCallback = make_fn_callback(&func, param_types.len());
 
         let mut callback_env: *mut FunctionCallbackEnv<'_, F> =
             Box::leak(Box::new(FunctionCallbackEnv {
@@ -201,11 +212,7 @@ impl Function {
         let mut store = store.as_store_mut();
         let inner = store.inner.store.inner;
 
-        let callback: unsafe extern "C" fn(
-            *mut c_void,
-            *const wasm_val_vec_t,
-            *mut wasm_val_vec_t,
-        ) -> *mut wasm_trap_t = unsafe { std::mem::transmute(func.function_callback()) };
+        let callback: CCallback = unsafe { std::mem::transmute(func.function_callback()) };
 
         let mut callback_env: *mut FunctionCallbackEnv<'_, F> =
             Box::into_raw(Box::new(FunctionCallbackEnv {
@@ -282,11 +289,7 @@ impl Function {
         let mut store = store.as_store_mut();
         let inner = store.inner.store.inner;
 
-        let callback: unsafe extern "C" fn(
-            *mut c_void,
-            *const wasm_val_vec_t,
-            *mut wasm_val_vec_t,
-        ) -> *mut wasm_trap_t = unsafe { std::mem::transmute(func.function_callback()) };
+        let callback: CCallback = unsafe { std::mem::transmute(func.function_callback()) };
 
         let mut callback_env: *mut FunctionCallbackEnv<'_, F> =
             Box::into_raw(Box::new(FunctionCallbackEnv {
@@ -357,40 +360,82 @@ impl Function {
         // unimplemented!();
         let store_mut = store.as_store_mut();
         // let wasm_func_param_arity(self.handle)
-        let mut wasm_params = params
-            .iter()
-            .map(result_to_value)
-            .collect::<Vec<_>>()
-            .into_boxed_slice();
-        let mut args = unsafe {
-            let mut vec = Default::default();
-            wasm_val_vec_new(&mut vec, wasm_params.len(), wasm_params.as_ptr());
-            vec
+
+        let mut args = {
+            #[cfg(any(feature = "wamr", feature = "wasmi"))]
+            unsafe {
+                let mut wasm_params = params
+                    .iter()
+                    .map(result_to_value)
+                    .collect::<Vec<_>>()
+                    .into_boxed_slice();
+                let mut vec = Default::default();
+                wasm_val_vec_new(&mut vec, wasm_params.len(), wasm_params.as_ptr());
+                vec
+            }
+            #[cfg(feature = "v8")]
+            {
+                let params = params.iter().map(result_to_value).collect::<Vec<_>>();
+
+                let ptr = params.as_ptr();
+
+                std::mem::forget(params);
+
+                ptr
+            }
         };
 
-        std::mem::forget(wasm_params);
         let size = unsafe { wasm_func_result_arity(self.handle) };
 
-        let mut results = unsafe {
-            let mut vec = Default::default();
-            wasm_val_vec_new_uninitialized(&mut vec, size);
-            vec
+        let mut results = {
+            #[cfg(any(feature = "wamr", feature = "wasmi"))]
+            unsafe {
+                let mut vec = Default::default();
+                wasm_val_vec_new_uninitialized(&mut vec, size);
+                vec
+            }
+
+            #[cfg(feature = "v8")]
+            {
+                let mut vec = Vec::with_capacity(size);
+                let ptr = vec.as_mut_ptr() as *mut wasm_val_t;
+
+                std::mem::forget(vec);
+
+                ptr
+            }
         };
 
-        let trap = unsafe { wasm_func_call(self.handle, &mut args, &mut results as *mut _) };
+        #[cfg(any(feature = "wamr", feature = "wasmi"))]
+        let trap = unsafe { wasm_func_call(self.handle, &mut args as _, &mut results as *mut _) };
+
+        #[cfg(feature = "v8")]
+        let trap = unsafe { wasm_func_call(self.handle, args as *const _, results as *mut _) };
 
         if !trap.is_null() {
             return Err(Into::<Trap>::into(trap).into());
         }
-        let results = unsafe { std::ptr::slice_from_raw_parts(results.data, results.size) };
 
-        Ok(unsafe {
-            (*results)
+        #[cfg(any(feature = "wamr", feature = "wasmi"))]
+        unsafe {
+            let results = std::ptr::slice_from_raw_parts(results.data, results.size);
+            return Ok((*results)
                 .into_iter()
                 .map(param_from_c)
                 .collect::<Vec<_>>()
-                .into_boxed_slice()
-        })
+                .into_boxed_slice());
+        }
+
+        #[cfg(feature = "v8")]
+        unsafe {
+            let results = Vec::from_raw_parts(results, size, size);
+
+            return Ok((results)
+                .iter()
+                .map(param_from_c)
+                .collect::<Vec<_>>()
+                .into_boxed_slice());
+        }
     }
 
     pub(crate) fn from_vm_extern(_store: &mut impl AsStoreMut, internal: VMFunction) -> Self {
@@ -414,75 +459,164 @@ impl Function {
     }
 }
 
-fn make_fn_callback<F, T: Send + 'static>(
-    func: &F,
-) -> unsafe extern "C" fn(*mut c_void, *const wasm_val_vec_t, *mut wasm_val_vec_t) -> *mut wasm_trap_t
+#[cfg(feature = "v8")]
+macro_rules! gen_v8_callback {
+    ($args:expr) => {{
+        unsafe extern "C" fn fn_callback<F, T: Send + 'static>(
+            env: *mut c_void,
+            args: *const wasm_val_t,
+            rets: *mut wasm_val_t,
+        ) -> *mut wasm_trap_t
+        where
+            F: Fn(FunctionEnvMut<'_, T>, &[Value]) -> Result<Vec<Value>, RuntimeError>
+                + 'static
+                + Send
+                + Sync,
+        {
+            let r: *mut (FunctionCallbackEnv<'_, F>) = env as _;
+
+            let mut store = (*r).store.as_store_mut();
+            let env_handle = (*r).env_handle.as_ref().unwrap().clone();
+            let mut fn_env = FunctionEnv::from_handle(env_handle).into_mut(&mut store);
+            let func: &F = &(*r).func;
+
+            let mut wasmer_args = vec![];
+
+            for i in 0..$args {
+                wasmer_args.push(param_from_c(&(*(args).wrapping_add(i)).clone()));
+            }
+
+            let result = panic::catch_unwind(AssertUnwindSafe(|| unsafe {
+                func(fn_env, wasmer_args.as_slice())
+            }));
+
+            match result {
+                Ok(Ok(native_results)) => {
+                    let mut c_results: Vec<wasm_val_t> = native_results
+                        .iter()
+                        .map(|r| crate::as_c::result_to_value(r))
+                        .collect();
+
+                    unsafe {
+                        for i in 0..c_results.len() {
+                            *((rets).wrapping_add(i)) = c_results[i]
+                        }
+                    }
+
+                    unsafe { std::ptr::null_mut() }
+                }
+
+                Ok(Err(e)) => {
+                    let trap: Trap = Trap::user(Box::new(e));
+                    unsafe { trap.into_wasm_trap(&mut store) }
+                }
+
+                Err(e) => {
+                    unimplemented!("host function panicked");
+                }
+            }
+        }
+
+        fn_callback::<F, T>
+    }};
+}
+
+fn make_fn_callback<F, T: Send + 'static>(func: &F, args: usize) -> CCallback
 where
     F: Fn(FunctionEnvMut<'_, T>, &[Value]) -> Result<Vec<Value>, RuntimeError>
         + 'static
         + Send
         + Sync,
 {
-    unsafe extern "C" fn fn_callback<F, T: Send + 'static>(
-        env: *mut c_void,
-        args: *const wasm_val_vec_t,
-        rets: *mut wasm_val_vec_t,
-    ) -> *mut wasm_trap_t
-    where
-        F: Fn(FunctionEnvMut<'_, T>, &[Value]) -> Result<Vec<Value>, RuntimeError>
-            + 'static
-            + Send
-            + Sync,
+    #[cfg(any(feature = "wamr", feature = "wasmi"))]
     {
-        let r: *mut (FunctionCallbackEnv<'_, F>) = env as _;
+        unsafe extern "C" fn fn_callback<F, T: Send + 'static>(
+            env: *mut c_void,
+            args: *const wasm_val_vec_t,
+            rets: *mut wasm_val_vec_t,
+        ) -> *mut wasm_trap_t
+        where
+            F: Fn(FunctionEnvMut<'_, T>, &[Value]) -> Result<Vec<Value>, RuntimeError>
+                + 'static
+                + Send
+                + Sync,
+        {
+            let r: *mut (FunctionCallbackEnv<'_, F>) = env as _;
 
-        let mut store = (*r).store.as_store_mut();
-        let env_handle = (*r).env_handle.as_ref().unwrap().clone();
-        let mut fn_env = FunctionEnv::from_handle(env_handle).into_mut(&mut store);
-        let func: &F = &(*r).func;
+            let mut store = (*r).store.as_store_mut();
+            let env_handle = (*r).env_handle.as_ref().unwrap().clone();
+            let mut fn_env = FunctionEnv::from_handle(env_handle).into_mut(&mut store);
+            let func: &F = &(*r).func;
 
-        let mut wasmer_args = vec![];
+            let mut wasmer_args = vec![];
 
-        for i in 0..(*args).size {
-            wasmer_args.push(param_from_c(&(*(*args).data.wrapping_add(i)).clone()));
-        }
+            for i in 0..(*args).size {
+                wasmer_args.push(param_from_c(&(*(*args).data.wrapping_add(i)).clone()));
+            }
 
-        let result = panic::catch_unwind(AssertUnwindSafe(|| unsafe {
-            func(fn_env, wasmer_args.as_slice())
-        }));
+            let result = panic::catch_unwind(AssertUnwindSafe(|| unsafe {
+                func(fn_env, wasmer_args.as_slice())
+            }));
 
-        match result {
-            Ok(Ok(native_results)) => {
-                let mut c_results: Vec<wasm_val_t> = native_results
-                    .iter()
-                    .map(|r| crate::as_c::result_to_value(r))
-                    .collect();
+            match result {
+                Ok(Ok(native_results)) => {
+                    let mut c_results: Vec<wasm_val_t> = native_results
+                        .iter()
+                        .map(|r| crate::as_c::result_to_value(r))
+                        .collect();
 
-                if c_results.len() != (*rets).size {
-                    panic!("when calling host function: number of observed results differ from wanted results")
-                }
+                    if c_results.len() != (*rets).size {
+                        panic!("when calling host function: number of observed results differ from wanted results")
+                    }
 
-                unsafe {
-                    for i in 0..(*rets).size {
-                        *((*rets).data.wrapping_add(i)) = c_results[i]
+                    unsafe {
+                        for i in 0..(*rets).size {
+                            *((*rets).data.wrapping_add(i)) = c_results[i]
+                        }
                     }
-                }
 
-                unsafe { std::ptr::null_mut() }
-            }
+                    unsafe { std::ptr::null_mut() }
+                }
 
-            Ok(Err(e)) => {
-                let trap: Trap = Trap::user(Box::new(e));
-                unsafe { trap.into_wasm_trap(&mut store) }
-            }
+                Ok(Err(e)) => {
+                    let trap: Trap = Trap::user(Box::new(e));
+                    unsafe { trap.into_wasm_trap(&mut store) }
+                }
 
-            Err(e) => {
-                unimplemented!("host function panicked");
+                Err(e) => {
+                    unimplemented!("host function panicked");
+                }
             }
         }
+
+        return fn_callback::<F, T>;
     }
 
-    fn_callback::<F, T>
+    #[cfg(feature = "v8")]
+    unsafe {
+        // Hacky: v8 uses an older version of the `wasm_c_api` header in which the signature for
+        // callbacks is different from that of wamr and wasmi: in v8, args (and returns) are of
+        // type `*const wasm_val_t` (instead of `wasm_val_vec_t`, which also contains the length of
+        // the vector), so we can't generate a single callback that at runtime gets the number of
+        // arguments to perform the call to the underlying function. Therefore, we need to generate
+        // different concrete callbacks for different signatures.
+
+        seq_macro::seq!(arg_num in 1..=26 {
+            let func = if args == 0 {
+                gen_v8_callback!(0)
+            }
+        #(
+             else if args == arg_num {
+                gen_v8_callback!(arg_num)
+             }
+        )*
+            else {
+                panic!("v8 callbacks for function with more than 26 parameters are not supported!");
+            };
+
+        });
+        return func;
+    }
 }
 
 impl fmt::Debug for Function {
@@ -515,6 +649,7 @@ macro_rules! impl_host_function {
                     /// This is a function that wraps the real host
                     /// function. Its address will be used inside the
                     /// runtime.
+                    #[cfg(any(feature = "wamr", feature = "wasmi"))]
                     unsafe extern "C" fn func_wrapper<$( $x, )* Rets, RetsAsResult, Func, T>(env: *mut c_void, args: *const wasm_val_vec_t, results: *mut wasm_val_vec_t) -> *mut wasm_trap_t
                     where
                         $( $x: FromToNativeWasmType, )*
@@ -585,6 +720,80 @@ macro_rules! impl_host_function {
                        }
 
 
+                    }
+
+                    #[cfg(feature = "v8")]
+                    unsafe extern "C" fn func_wrapper<$( $x, )* Rets, RetsAsResult, Func, T>(env: *mut c_void, args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t
+                    where
+                        $( $x: FromToNativeWasmType, )*
+                        Rets: WasmTypeList,
+                        RetsAsResult: IntoResult<Rets>,
+                        T: Send + 'static,
+                        Func: Fn(FunctionEnvMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static,
+                    {
+
+                        let r: *mut (FunctionCallbackEnv<'_, Func>) = env as _;
+                        let store = &mut (*r).store.as_store_mut();
+
+                        let mut i = 0;
+
+                       $(
+                           let c_arg = (*(args).wrapping_add(i)).clone();
+                           let wasmer_arg = crate::as_c::param_from_c(&c_arg);
+                           let raw_arg : RawValue = wasmer_arg.as_raw(store);
+                           let $x : $x = FromToNativeWasmType::from_native($x::Native::from_raw(store, raw_arg));
+
+                           i += 1;
+                        )*
+
+
+
+                        let env_handle = (*r).env_handle.as_ref().unwrap().clone();
+                        let mut fn_env = FunctionEnv::from_handle(env_handle).into_mut(store);
+                        let func: &Func = &(*r).func;
+
+                        let result = panic::catch_unwind(AssertUnwindSafe(|| unsafe {
+                            ((*r).func)(fn_env, $( $x, )* ).into_result()
+                        }));
+
+
+                       match result {
+                           Ok(Ok(result)) => {
+
+                               let types = Rets::wasm_types();
+                               let size = types.len();
+                                let mut native_results = result.into_array(store);
+                                let native_results = native_results.as_mut();
+
+                                let native_results: Vec<Value> = native_results.into_iter().enumerate()
+                                    .map(|(i, r)| Value::from_raw(store, types[i], r.clone()))
+                                    .collect();
+
+                                let mut c_results: Vec<wasm_val_t> = native_results.iter().map(|r| crate::as_c::result_to_value(r)).collect();
+
+                                if c_results.len() != size {
+                                    panic!("when calling host function: number of observed results differ from wanted results")
+                                }
+
+                                unsafe {
+                                    for i in 0..size {
+                                        *((results).wrapping_add(i)) = c_results[i]
+                                    }
+
+                                }
+
+                                unsafe { std::ptr::null_mut() }
+                           },
+                           Ok(Err(e)) => {
+                                let trap: Trap =  Trap::user(Box::new(e));
+                                unsafe { trap.into_wasm_trap(store) }
+                           },
+                           Err(e) => {
+                               unimplemented!("host function panicked");
+                           }
+                       }
+
+
                     }
 
                     func_wrapper::< $( $x, )* Rets, RetsAsResult, Self, T> as VMFunctionCallback
@@ -611,6 +820,7 @@ macro_rules! impl_host_function {
                     /// This is a function that wraps the real host
                     /// function. Its address will be used inside the
                     /// runtime.
+                    #[cfg(any(feature = "wamr", feature = "wasmi"))]
                     unsafe extern "C" fn func_wrapper<$( $x, )* Rets, RetsAsResult, Func>(env: *mut c_void, args: *const wasm_val_vec_t, results: *mut wasm_val_vec_t) -> *mut wasm_trap_t
                     where
                         $( $x: FromToNativeWasmType, )*
@@ -673,6 +883,72 @@ macro_rules! impl_host_function {
                         }
 
 
+                    }
+
+                    #[cfg(feature = "v8")]
+                    unsafe extern "C" fn func_wrapper<$( $x, )* Rets, RetsAsResult, Func>(env: *mut c_void, args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t
+                    where
+                        $( $x: FromToNativeWasmType, )*
+                        Rets: WasmTypeList,
+                        RetsAsResult: IntoResult<Rets>,
+                        Func: Fn($( $x , )*) -> RetsAsResult + 'static,
+                    {
+                        let mut r: *mut FunctionCallbackEnv<Func> = unsafe {std::mem::transmute(env)};
+                        let store = &mut (*r).store.as_store_mut();
+                        let mut i = 0;
+
+                        $(
+                            let c_arg = (*(args).wrapping_add(i)).clone();
+                            let wasmer_arg = crate::as_c::param_from_c(&c_arg);
+                            let raw_arg : RawValue = wasmer_arg.as_raw(store);
+                            let $x : $x = FromToNativeWasmType::from_native($x::Native::from_raw(store, raw_arg));
+
+                            i += 1;
+                        )*
+
+                        let result = panic::catch_unwind(AssertUnwindSafe(|| unsafe {
+                            ((*r).func)( $( $x, )* ).into_result()
+                        }));
+
+                        match result {
+                            Ok(Ok(result)) => {
+
+                                let types = Rets::wasm_types();
+                                let size = types.len();
+                                let mut native_results = result.into_array(store);
+                                let native_results = native_results.as_mut();
+
+                                let native_results: Vec<Value> = native_results.into_iter().enumerate()
+                                    .map(|(i, r)| Value::from_raw(store, types[i], r.clone()))
+                                    .collect();
+
+                                let mut c_results: Vec<wasm_val_t> = native_results.iter().map(|r| crate::as_c::result_to_value(r)).collect();
+
+                                if c_results.len() != size {
+                                    panic!("when calling host function: number of observed results differ from wanted results")
+                                }
+
+                                unsafe {
+                                    for i in 0..size {
+                                        *((results).wrapping_add(i)) = c_results[i]
+                                    }
+                                }
+
+                                 unsafe { std::ptr::null_mut() }
+                            },
+
+                            Ok(Err(e)) => {
+                                let trap: Trap =  Trap::user(Box::new(e));
+                                unsafe { trap.into_wasm_trap(store) }
+                                // unimplemented!("host function panicked");
+                            },
+
+                            Err(e) => {
+                                unimplemented!("host function panicked");
+                            }
+                        }
+
+
                     }
 
                     func_wrapper::< $( $x, )* Rets, RetsAsResult, Self > as VMFunctionCallback
diff --git a/lib/api/src/c_api/instance.rs b/lib/api/src/c_api/instance.rs
index f33c153d1dd..d7c498302be 100644
--- a/lib/api/src/c_api/instance.rs
+++ b/lib/api/src/c_api/instance.rs
@@ -48,35 +48,48 @@ impl InstanceHandle {
             }
         }
 
-        let mut imports = unsafe {
-            let mut vec = Default::default();
-            wasm_extern_vec_new(&mut vec, externs.len(), externs.as_ptr());
-            vec
-        };
-
-        std::mem::forget(externs);
-
         let mut trap: *mut wasm_trap_t = std::ptr::null_mut() as _;
 
         let instance = unsafe {
-            #[cfg(feature = "wamr")]
+            #[cfg(any(feature = "wasmi", feature = "wamr"))]
             {
-                let stack_size = 2 * 1024 * 1024;
-                let heap_size = 2 * 1024 * 1024;
+                let mut imports = unsafe {
+                    let mut vec = Default::default();
+                    wasm_extern_vec_new(&mut vec, externs.len(), externs.as_ptr());
+                    vec
+                };
+
+                std::mem::forget(externs);
+
+                #[cfg(feature = "wamr")]
+                {
+                    let stack_size = 2 * 1024 * 1024;
+                    let heap_size = 2 * 1024 * 1024;
+
+                    crate::bindings::wasm_instance_new_with_args(
+                        store,
+                        module,
+                        &mut imports,
+                        &mut trap,
+                        stack_size,
+                        heap_size,
+                    )
+                }
+                #[cfg(feature = "wasmi")]
+                {
+                    wasm_instance_new(store, module, &mut imports, &mut trap)
+                }
+            }
 
-                crate::bindings::wasm_instance_new_with_args(
+            #[cfg(feature = "v8")]
+            {
+                wasm_instance_new(
                     store,
                     module,
-                    &mut imports,
+                    externs.as_ptr() as *const *const _,
                     &mut trap,
-                    stack_size,
-                    heap_size,
                 )
             }
-            #[cfg(feature = "wasmi")]
-            {
-                wasm_instance_new(store, module, &mut imports, &mut trap)
-            }
         };
 
         if instance.is_null() {
@@ -148,7 +161,7 @@ impl Instance {
 
             return Self::new_by_index(&mut store, module, &externs);
         }
-        #[cfg(feature = "wasmi")]
+        #[cfg(any(feature = "wasmi", feature = "v8"))]
         {
             return Self::new_by_index(&mut store.as_store_mut(), module, &externs);
         }
diff --git a/lib/api/src/c_api/mod.rs b/lib/api/src/c_api/mod.rs
index 7035f19471d..b61a2f5b1fa 100644
--- a/lib/api/src/c_api/mod.rs
+++ b/lib/api/src/c_api/mod.rs
@@ -16,8 +16,8 @@ compile_error!(
 #[cfg(all(not(feature = "std"), not(feature = "core")))]
 compile_error!("Both the `std` and `core` features are disabled. Please enable one of them.");
 
-#[cfg(all(not(feature = "wamr"), not(feature = "wasmi")))]
-compile_error!("Both the `wamr` and `wasmi` features are disabled. Please enable one of them.");
+#[cfg(all(not(feature = "wamr"), not(feature = "wasmi"), not(feature = "v8")))]
+compile_error!("Features `wamr`, `wasmi` and `v8` are all disabled. Please enable one of them.");
 
 #[cfg(feature = "core")]
 pub(crate) extern crate alloc;
diff --git a/lib/api/src/c_api/module.rs b/lib/api/src/c_api/module.rs
index 914cfadbf21..7e760943e8b 100644
--- a/lib/api/src/c_api/module.rs
+++ b/lib/api/src/c_api/module.rs
@@ -49,7 +49,7 @@ impl ModuleHandle {
             lock: std::ptr::null_mut(),
         };
 
-        #[cfg(feature = "wasmi")]
+        #[cfg(any(feature = "wasmi", feature = "v8"))]
         let bytes = wasm_byte_vec_t {
             size: binary.len(),
             data: binary.as_ptr() as _,
diff --git a/lib/api/src/c_api/typed_function.rs b/lib/api/src/c_api/typed_function.rs
index 564e0233ad4..aae515d3c3c 100644
--- a/lib/api/src/c_api/typed_function.rs
+++ b/lib/api/src/c_api/typed_function.rs
@@ -33,10 +33,10 @@ macro_rules! impl_native_traits {
              Rets: WasmTypeList,
          {
              /// Call the typed func and return results.
-             #[allow(clippy::too_many_arguments)]
-             pub fn call(&self, mut store: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result<Rets, RuntimeError> where
-             $( $x: FromToNativeWasmType + NativeWasmTypeInto, )*
-             {
+            #[allow(clippy::too_many_arguments)]
+            pub fn call(&self, mut store: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result<Rets, RuntimeError> where
+            $( $x: FromToNativeWasmType + NativeWasmTypeInto, )*
+            {
 
                  // // let store_ptr = Value::I64(store.as_store_mut().as_raw() as _).as_jsvalue(store);
                  #[allow(unused_unsafe)]
@@ -48,21 +48,42 @@ macro_rules! impl_native_traits {
                      } ),* ]
                  };
 
-                 let mut params = unsafe {std::mem::zeroed()};
+                 let mut results = {
+                    #[cfg(any(feature = "wamr", feature = "wasmi"))]
+                    unsafe {
+                        let mut ret = std::mem::zeroed();
+                        wasm_val_vec_new_uninitialized(&mut ret, Rets::wasm_types().len());
+                        ret
+                    }
 
-                 unsafe {
-                     wasm_val_vec_new(&mut params, params_list.len(), params_list.as_ptr());
-                 }
+                    #[cfg(feature = "v8")]
+                    unsafe {
 
-                 let mut results = unsafe {std::mem::zeroed()};
+                        let rets_len = Rets::wasm_types().len();
+                        let mut vec = Vec::<crate::bindings::wasm_val_t>::with_capacity(rets_len);
+                        let ptr = vec.as_mut_ptr();
+                        std::mem::forget(vec);
+                        ptr as *mut _
+
+                    }
+                };
 
-                 unsafe {
-                     wasm_val_vec_new_uninitialized(&mut results, Rets::wasm_types().len())
-                 }
 
                  let func = unsafe { wasm_extern_as_func(self.func.to_vm_extern()) };
 
-                 let trap = unsafe { wasm_func_call(func, &params, &mut results) };
+                 let trap = {
+                    #[cfg(any(feature = "wamr", feature = "wasmi"))]
+                    unsafe {
+                        let mut params = std::mem::zeroed();
+                        wasm_val_vec_new(&mut params, params_list.len(), params_list.as_ptr());
+                        wasm_func_call(func, &params, &mut results)
+                    }
+
+                    #[cfg(feature = "v8")]
+                    unsafe {
+                        wasm_func_call(func, params_list.as_ptr() as *const _, results)
+                    }
+                 };
 
                  if !trap.is_null() {
                      unsafe {
@@ -71,30 +92,41 @@ macro_rules! impl_native_traits {
                      }
                 }
 
-                let mut rets_list_array = Rets::empty_array();
-                let mut_rets = rets_list_array.as_mut() as *mut [RawValue] as *mut RawValue;
+                #[cfg(feature = "v8")]
+                 unsafe {
+                    let rets_len = Rets::wasm_types().len();
+                    let mut results: *const [crate::bindings::wasm_val_t] = std::ptr::slice_from_raw_parts(results, rets_len);
 
-                match Rets::size() {
-                    0 => {},
-                    1 => unsafe {
-                        let val = (*results.data.wrapping_add(0)).clone();
-                        let val = param_from_c(&val);
-                        *mut_rets = val.as_raw(&mut store);
+                    unsafe {
+                        let results: Vec<_> = (*results).into_iter().map(|v| param_from_c(&v).as_raw(&mut store)).collect();
+                        Ok(unsafe {Rets::from_slice(store, &results).unwrap()})
                     }
-                    _n => {
-                        for (i, ret_type) in Rets::wasm_types().iter().enumerate() {
-                            unsafe {
-                                let val = (*results.data.wrapping_add(i)).clone();
-                                let val = param_from_c(&val);
-                                let slot = mut_rets.add(i);
-                                *slot = val.as_raw(&mut store);
+                 }
+
+                #[cfg(any(feature = "wamr", feature = "wasmi"))]
+                unsafe {
+                    let mut rets_list_array = Rets::empty_array();
+                    let mut_rets = rets_list_array.as_mut() as *mut [RawValue] as *mut RawValue;
+
+                    match Rets::size() {
+                        0 => {},
+                        1 => {
+                            let val = (*results.data.wrapping_add(0)).clone();
+                            let val = param_from_c(&val);
+                            *mut_rets = val.as_raw(&mut store);
+                        }
+                        _n => {
+                            for (i, ret_type) in Rets::wasm_types().iter().enumerate() {
+                                    let val = (*results.data.wrapping_add(i)).clone();
+                                    let val = param_from_c(&val);
+                                    let slot = mut_rets.add(i);
+                                    *slot = val.as_raw(&mut store);
                             }
                         }
                     }
-                }
-
-                Ok(unsafe { Rets::from_array(store, rets_list_array) })
 
+                    Ok(unsafe { Rets::from_array(store, rets_list_array) })
+                }
             }
         }
     };
diff --git a/lib/api/src/imports.rs b/lib/api/src/imports.rs
index 344bc24e28f..335ec09278b 100644
--- a/lib/api/src/imports.rs
+++ b/lib/api/src/imports.rs
@@ -462,6 +462,7 @@ mod test {
         };
 
         imports2.extend(&imports1);
+
         let _happy_dog_entry = imports2.get_export("dog", "happy").unwrap();
         /*
         assert!(
diff --git a/lib/api/third_party/v8-cmake b/lib/api/third_party/v8-cmake
new file mode 160000
index 00000000000..edd1821a164
--- /dev/null
+++ b/lib/api/third_party/v8-cmake
@@ -0,0 +1,1 @@
+Subproject commit edd1821a16421a159aa440ffd655bb2feb89e1d7
diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml
index 59e2eb0c7ed..9a1c3907f62 100644
--- a/lib/cli/Cargo.toml
+++ b/lib/cli/Cargo.toml
@@ -51,6 +51,7 @@ fuse = ["dep:fuse", "dep:time01", "dep:shared-buffer", "dep:rkyv"]
 backend = []
 coredump = ["wasm-coredump-builder"]
 sys = ["compiler", "wasmer-vm"]
+v8 = ["backend", "wasmer/v8"]
 wamr = ["backend", "wasmer/wamr"]
 wasmi = ["backend", "wasmer/wasmi"]
 jsc = ["backend", "wasmer/jsc", "wasmer/std"]
diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs
index e4633ac634b..d08b7736455 100644
--- a/lib/cli/src/bin/wasmer.rs
+++ b/lib/cli/src/bin/wasmer.rs
@@ -1,6 +1,6 @@
 #[cfg(not(feature = "backend"))]
 compile_error!(
-    "Either enable at least one backend, or compile the wasmer-headless binary instead.\nWith cargo, you can provide a compiler option with the --features flag.\n\nExample values:\n\n\t\t--features cranelift,singlepass\n\t\t--features jsc\n\t\t--features wamr\n\t\t--features wamr\n\n\n"
+    "Either enable at least one backend, or compile the wasmer-headless binary instead.\nWith cargo, you can provide a compiler option with the --features flag.\n\nExample values:\n\n\t\t--features cranelift,singlepass\n\t\t--features jsc\n\t\t--features wamr\n\t\t--features wamr\n\t\t--features v8\n\n\n"
 );
 
 fn main() {
diff --git a/lib/cli/src/commands/mod.rs b/lib/cli/src/commands/mod.rs
index f2f46c4e31c..38190bb5ebc 100644
--- a/lib/cli/src/commands/mod.rs
+++ b/lib/cli/src/commands/mod.rs
@@ -501,11 +501,17 @@ fn print_version(verbose: bool) -> Result<(), anyhow::Error> {
     }
 
     if cfg!(feature = "wasmi") {
-        // Can't use wamr and wasmi together as of now, but maybe we'll support more
+        // Can't use two different c_api backends together as of now, but maybe we'll support more
         // interepreters.
         interpreters.push("wasmi");
     }
 
-    println!("interpreter: {}", interpreters.join(","));
+    if cfg!(feature = "v8") {
+        // Can't use c_api backends together as of now, but maybe we'll support more
+        // interepreters.
+        interpreters.push("v8");
+    }
+
+    println!("c_api backend: {}", interpreters.join(","));
     Ok(())
 }
diff --git a/lib/cli/src/store.rs b/lib/cli/src/store.rs
index 3ca29d4acaf..47f9baff755 100644
--- a/lib/cli/src/store.rs
+++ b/lib/cli/src/store.rs
@@ -387,6 +387,7 @@ impl StoreOptions {
     feature = "compiler",
     feature = "jsc",
     feature = "wamr",
+    feature = "v8",
     feature = "wasmi"
 )))]
 impl StoreOptions {
@@ -405,7 +406,7 @@ impl StoreOptions {
 
 #[cfg(all(
     not(feature = "compiler"),
-    any(feature = "jsc", feature = "wamr", feature = "wasmi")
+    any(feature = "jsc", feature = "wamr", feature = "wasmi", feature = "v8")
 ))]
 impl StoreOptions {
     /// Get the store (headless engine)
diff --git a/lib/swift/Cargo.toml b/lib/swift/Cargo.toml
index 58c9540e5dd..2131bed56fc 100644
--- a/lib/swift/Cargo.toml
+++ b/lib/swift/Cargo.toml
@@ -11,7 +11,7 @@ name = "wasmer_swift"
 
 [dependencies]
 thiserror = "1"
-tokio = { version = "1.28.1", features = [ "rt" ], default_features = false }
+tokio = { version = "1.28.1", features = [ "rt" ], default-features = false }
 uniffi = "0.27"
 virtual-fs = { path = "../virtual-fs", version = "0.16.0", default-features = false, features = [
 	"webc-fs",


Test patch:
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index f80336eb270..bfc1f28d441 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -222,7 +222,13 @@ jobs:
             key: wasmi,
             build-cmd: 'make test-wasmi-api',
             name: 'Test API for wasmi feature'
+          },
+          {
+            key: v8,
+            build-cmd: 'make test-wasmi-v8',
+            name: 'Test API for v8 feature'
           }
+
         ]
         metadata: [
           {
@@ -246,6 +252,7 @@ jobs:
           toolchain: ${{ env.MSRV }}
       - name: Install Nextest
         uses: taiki-e/install-action@nextest
+
       - name: Test WAMR API 
         if: ${{ matrix.build-what.key == 'wamr' }}
         run: ${{ matrix.build-what.build-cmd }}
@@ -254,6 +261,10 @@ jobs:
         if: ${{ matrix.build-what.key == 'wasmi' }}
         run: ${{ matrix.build-what.build-cmd }}
 
+      - name: Test v8 API 
+        if: ${{ matrix.build-what.key == 'wasmi' }}
+        run: ${{ matrix.build-what.build-cmd }}
+
   test_build_docs_rs:
     name: Test build docs rs
     runs-on: ubuntu-22.04
@@ -906,29 +917,37 @@ jobs:
           CARGO_TARGET: ${{ matrix.target }}
           WAPM_DEV_TOKEN: ${{ secrets.WAPM_DEV_TOKEN }}
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-      - name: Test CLI integration (WAMR) 
-        shell: bash
-        run: |
-          export WASMER_PATH=`pwd`/target/${{ matrix.target }}/release/wasmer${{ matrix.exe }}
-          export WASMER_DIR=`pwd`/package && make test-integration-cli-wamr-ci
-        env:
-          TARGET: ${{ matrix.target }}
-          TARGET_DIR: target/${{ matrix.target }}/release
-          CARGO_TARGET: ${{ matrix.target }}
-          WAPM_DEV_TOKEN: ${{ secrets.WAPM_DEV_TOKEN }}
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          
+          # ---- 
+          # Note (xdoardo on 2024/10/07): 
+          # --- 
+          #  As of now the WAMR, WASMI (and V8) backends are not that mature enough. We will re-enable these tests 
+          #  when they've been used and matured. 
+          # ---- 
+          #
+          # - name: Test CLI integration (WAMR) 
+          #   shell: bash
+          #   run: |
+          #     export WASMER_PATH=`pwd`/target/${{ matrix.target }}/release/wasmer${{ matrix.exe }}
+          #     export WASMER_DIR=`pwd`/package && make test-integration-cli-wamr-ci
+          #   env:
+          #     TARGET: ${{ matrix.target }}
+          #     TARGET_DIR: target/${{ matrix.target }}/release
+          #     CARGO_TARGET: ${{ matrix.target }}
+          #     WAPM_DEV_TOKEN: ${{ secrets.WAPM_DEV_TOKEN }}
+          #     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
-      - name: Test CLI integration (WASMI) 
-        shell: bash
-        run: |
-          export WASMER_PATH=`pwd`/target/${{ matrix.target }}/release/wasmer${{ matrix.exe }}
-          export WASMER_DIR=`pwd`/package && make test-integration-cli-wasmi-ci
-        env:
-          TARGET: ${{ matrix.target }}
-          TARGET_DIR: target/${{ matrix.target }}/release
-          CARGO_TARGET: ${{ matrix.target }}
-          WAPM_DEV_TOKEN: ${{ secrets.WAPM_DEV_TOKEN }}
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          # - name: Test CLI integration (WASMI) 
+          #   shell: bash
+          #   run: |
+          #     export WASMER_PATH=`pwd`/target/${{ matrix.target }}/release/wasmer${{ matrix.exe }}
+          #     export WASMER_DIR=`pwd`/package && make test-integration-cli-wasmi-ci
+          #   env:
+          #     TARGET: ${{ matrix.target }}
+          #     TARGET_DIR: target/${{ matrix.target }}/release
+          #     CARGO_TARGET: ${{ matrix.target }}
+          #     WAPM_DEV_TOKEN: ${{ secrets.WAPM_DEV_TOKEN }}
+          #     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
 
   # there is another set of integration tests in 'wasmer-integration-tests' repo. Run those
diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs
index 67a5fc4e8f1..d5f84da09fa 100644
--- a/lib/api/tests/externals.rs
+++ b/lib/api/tests/externals.rs
@@ -411,7 +411,7 @@ fn function_new_dynamic() -> Result<(), String> {
     assert_eq!(function.ty(&store), function_type);
 
     // wasmi does not support V128 through its wasm_c_api bindings.
-    #[cfg(not(feature = "wasmi"))]
+    #[cfg(not(any(feature = "wasmi", feature = "v8")))]
     {
         // Using array signature
         let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
@@ -481,7 +481,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
     assert_eq!(function.ty(&store), function_type);
 
     // wasmi does not support V128 through its wasm_c_api bindings.
-    #[cfg(not(feature = "wasmi"))]
+    #[cfg(not(any(feature = "wasmi", feature = "v8")))]
     {
         // Using array signature
         let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
diff --git a/lib/api/tests/instance.rs b/lib/api/tests/instance.rs
index beddbd262c6..3704c0c5260 100644
--- a/lib/api/tests/instance.rs
+++ b/lib/api/tests/instance.rs
@@ -66,7 +66,7 @@ fn exports_work_after_multiple_instances_have_been_freed() -> Result<(), String>
 fn unit_native_function_env() -> Result<(), String> {
     let mut store = Store::default();
 
-    #[derive(Clone)]
+    #[derive(Clone, Debug)]
     struct Env {
         multiplier: u32,
     }
diff --git a/lib/api/tests/memory.rs b/lib/api/tests/memory.rs
index f29fddcd424..23881e7b781 100644
--- a/lib/api/tests/memory.rs
+++ b/lib/api/tests/memory.rs
@@ -6,6 +6,10 @@ use wasmer::{imports, Instance, Memory, MemoryLocation, MemoryType, Module, Stor
 
 #[test]
 #[cfg_attr(feature = "wasmi", ignore = "wasmi does not support threads")]
+#[cfg_attr(
+    feature = "v8",
+    ignore = "v8 does not currently support shared memory through wasm_c_api"
+)]
 fn test_shared_memory_atomics_notify_send() {
     let mut store = Store::default();
     let wat = r#"(module
diff --git a/lib/api/tests/module.rs b/lib/api/tests/module.rs
index 73ef59cefa7..2f21f158a81 100644
--- a/lib/api/tests/module.rs
+++ b/lib/api/tests/module.rs
@@ -277,6 +277,7 @@ fn calling_host_functions_with_negative_values_works() -> Result<(), String> {
 #[universal_test]
 #[cfg_attr(feature = "wamr", ignore = "wamr does not support custom sections")]
 #[cfg_attr(feature = "wasmi", ignore = "wasmi does not support custom sections")]
+#[cfg_attr(feature = "v8", ignore = "v8 does not support custom sections")]
 fn module_custom_sections() -> Result<(), String> {
     let store = Store::default();
     let custom_section_wasm_bytes = include_bytes!("simple-name-section.wasm");
diff --git a/tests/integration/cli/Cargo.toml b/tests/integration/cli/Cargo.toml
index cde7db1068d..21a911d77c4 100644
--- a/tests/integration/cli/Cargo.toml
+++ b/tests/integration/cli/Cargo.toml
@@ -39,5 +39,6 @@ wasmer-registry = { path = "../../../lib/registry", default-features = false }
 default = ["webc_runner"]
 webc_runner = []
 wamr = []
+v8 = []
 wasmi = []
 debug = []
diff --git a/tests/integration/cli/tests/create_exe.rs b/tests/integration/cli/tests/create_exe.rs
index 4511e343a32..2fbf782ae33 100644
--- a/tests/integration/cli/tests/create_exe.rs
+++ b/tests/integration/cli/tests/create_exe.rs
@@ -265,9 +265,11 @@ fn test_create_exe_with_precompiled_works_1() {
 // Ignored because of -lunwind linker issue on Windows
 // see https://github.com/wasmerio/wasmer/issues/3459
 // Also ignored on macOS because it's flaky
-#[cfg_attr(any(target_os = "windows", target_os = "macos"), ignore)]
+#[cfg_attr(
+    any(target_os = "windows", target_os = "macos"),
+    ignore = "See https://github.com/wasmerio/wasmer/issues/4285"
+)]
 #[test]
-#[ignore = "See https://github.com/wasmerio/wasmer/issues/4285"]
 fn create_exe_works() -> anyhow::Result<()> {
     let temp_dir = tempfile::tempdir()?;
     let operating_dir: PathBuf = temp_dir.path().to_owned();
diff --git a/tests/integration/cli/tests/run.rs b/tests/integration/cli/tests/run.rs
index 03851b70a01..4b8afb1b5ff 100644
--- a/tests/integration/cli/tests/run.rs
+++ b/tests/integration/cli/tests/run.rs
@@ -920,8 +920,8 @@ fn error_if_no_start_function_found() {
     ignore = "wasmer run-unstable segfaults on musl"
 )]
 #[cfg_attr(
-    feature = "wamr",
-    ignore = "wasmer using an interpreter backend only may not have the 'compile' command"
+    any(feature = "wamr", feature = "v8", feature = "wasmi"),
+    ignore = "wasmer using a c_api backend only may not have the 'compile' command"
 )]
 fn run_a_pre_compiled_wasm_file() {
     let temp = TempDir::new().unwrap();