diff --git a/libs/test/Cargo.toml b/libs/test/Cargo.toml index a77b3cc..46f9695 100644 --- a/libs/test/Cargo.toml +++ b/libs/test/Cargo.toml @@ -10,5 +10,5 @@ authors = ["Emile Fugulin "] [dependencies] futures = { version = "0.3" } -rquickjs = { version = ">=0.10,<0.12", features = ["macro", "futures"] } +rquickjs = { version = "0.14", features = ["macro", "futures"] } tokio = { version = "1", features = ["full"] } diff --git a/libs/test/src/lib.rs b/libs/test/src/lib.rs index f6df2c7..4144249 100644 --- a/libs/test/src/lib.rs +++ b/libs/test/src/lib.rs @@ -1,6 +1,5 @@ use rquickjs::{ AsyncContext, AsyncRuntime, CatchResultExt, CaughtError, Ctx, FromJs, Function, Module, Result, - async_with, function::IntoArgs, module::{Evaluated, ModuleDef}, promise::MaybePromise, @@ -15,18 +14,15 @@ where ctx.with(func); } -pub async fn test_async_with(func: F) +pub async fn test_async_with(func: F) where - F: for<'js> FnOnce(Ctx<'js>) -> std::pin::Pin + 'js>> - + Send, + F: for<'js> AsyncFnOnce(Ctx<'js>) -> R + Send, + R: Send + 'static, { let rt = AsyncRuntime::new().unwrap(); let ctx = AsyncContext::full(&rt).await.unwrap(); - async_with!(ctx => |ctx| { - func(ctx).await - }) - .await; + ctx.async_with(func).await; } pub async fn call_test<'js, T, A>(ctx: &Ctx<'js>, module: &Module<'js, Evaluated>, args: A) -> T diff --git a/libs/utils/Cargo.toml b/libs/utils/Cargo.toml index 1e9120e..cc227b2 100644 --- a/libs/utils/Cargo.toml +++ b/libs/utils/Cargo.toml @@ -9,4 +9,4 @@ repository = "https://github.com/rquickjs/rquickjs-extra" authors = ["Emile Fugulin "] [dependencies] -rquickjs = { version = ">=0.10,<0.12", features = ["array-buffer"] } +rquickjs = { version = "0.14", features = ["array-buffer"] } diff --git a/libs/utils/src/ffi/c_string.rs b/libs/utils/src/ffi/c_string.rs deleted file mode 100644 index 54f5a97..0000000 --- a/libs/utils/src/ffi/c_string.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::mem; -use std::{ffi::c_char, slice, str}; - -use rquickjs::{Error, Exception, Result, String, Value, qjs}; - -#[derive(Debug)] -pub struct CString<'js> { - ptr: *const c_char, - len: usize, - value: Value<'js>, -} - -#[allow(dead_code)] -impl<'js> CString<'js> { - pub fn from_string(string: String<'js>) -> Result { - let mut len = mem::MaybeUninit::uninit(); - let ptr = unsafe { - qjs::JS_ToCStringLen( - string.ctx().as_raw().as_ptr(), - len.as_mut_ptr(), - string.as_raw(), - ) - }; - if ptr.is_null() { - // Might not ever happen but I am not 100% sure - // so just incase check it. - return Err(Error::Unknown); - } - let len = unsafe { len.assume_init() }; - Ok(Self { - ptr, - len, - value: string.into_value(), - }) - } - - pub fn as_ptr(&self) -> *const c_char { - self.ptr - } - - pub fn len(&self) -> usize { - self.len - } - - pub fn is_empty(&self) -> bool { - self.len == 0 - } - - pub fn as_str(&self) -> Result<&str> { - let bytes = unsafe { slice::from_raw_parts(self.ptr as *const u8, self.len) }; - str::from_utf8(bytes) - .map_err(|_| Exception::throw_message(self.value.ctx(), "Invalid UTF-8")) - } -} - -impl Drop for CString<'_> { - fn drop(&mut self) { - unsafe { qjs::JS_FreeCString(self.value.ctx().as_raw().as_ptr(), self.ptr) }; - } -} diff --git a/libs/utils/src/ffi/c_vec.rs b/libs/utils/src/ffi/c_vec.rs deleted file mode 100644 index 1515f33..0000000 --- a/libs/utils/src/ffi/c_vec.rs +++ /dev/null @@ -1,39 +0,0 @@ -use rquickjs::{Result, TypedArray, Value}; - -use crate::result::ResultExt; - -#[derive(Debug)] -pub struct CVec<'js> { - ptr: *const u8, - len: usize, - #[allow(dead_code)] - value: Value<'js>, -} - -#[allow(dead_code)] -impl<'js> CVec<'js> { - pub fn from_array(array: TypedArray<'js, u8>) -> Result { - let raw = array.as_raw().or_throw(array.ctx())?; - Ok(Self { - ptr: raw.ptr.as_ptr(), - len: raw.len, - value: array.into_value(), - }) - } - - pub fn as_ptr(&self) -> *const u8 { - self.ptr - } - - pub fn len(&self) -> usize { - self.len - } - - pub fn is_empty(&self) -> bool { - self.len == 0 - } - - pub fn as_slice(&self) -> &[u8] { - unsafe { std::slice::from_raw_parts(self.ptr, self.len) } - } -} diff --git a/libs/utils/src/ffi/mod.rs b/libs/utils/src/ffi/mod.rs deleted file mode 100644 index 12c85c5..0000000 --- a/libs/utils/src/ffi/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub use self::c_string::CString; -pub use self::c_vec::CVec; - -mod c_string; -mod c_vec; diff --git a/libs/utils/src/lib.rs b/libs/utils/src/lib.rs index 7b16623..6f1915c 100644 --- a/libs/utils/src/lib.rs +++ b/libs/utils/src/lib.rs @@ -1,4 +1,3 @@ -pub mod ffi; pub mod module; pub mod result; pub mod sysinfo; diff --git a/modules/console/Cargo.toml b/modules/console/Cargo.toml index 6e93477..1fc6be1 100644 --- a/modules/console/Cargo.toml +++ b/modules/console/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Emile Fugulin "] [dependencies] log = { version = "0.4" } -rquickjs = { version = ">=0.10,<0.12", features = ["macro"] } +rquickjs = { version = "0.14", features = ["macro"] } [dev-dependencies] rquickjs-extra-test = { path = "../../libs/test" } diff --git a/modules/os/Cargo.toml b/modules/os/Cargo.toml index 8d2a4ee..048d612 100644 --- a/modules/os/Cargo.toml +++ b/modules/os/Cargo.toml @@ -12,7 +12,7 @@ authors = ["Emile Fugulin "] home = "0.5" num_cpus = "1" once_cell = "1" -rquickjs = { version = ">=0.10,<0.12", features = ["macro"] } +rquickjs = { version = "0.14", features = ["macro"] } rquickjs-extra-utils = { version = "0.2.1", path = "../../libs/utils" } [target.'cfg(unix)'.dependencies] @@ -24,6 +24,6 @@ windows-result = "0.3" windows-version = "0.1" [dev-dependencies] -rquickjs = { version = ">=0.10,<0.12", features = ["futures"] } +rquickjs = { version = "0.14", features = ["futures"] } rquickjs-extra-test = { path = "../../libs/test" } tokio = { version = "1", features = ["full"] } diff --git a/modules/os/src/lib.rs b/modules/os/src/lib.rs index 81e0eba..9b7d8e9 100644 --- a/modules/os/src/lib.rs +++ b/modules/os/src/lib.rs @@ -84,179 +84,167 @@ mod tests { #[tokio::test] async fn test_type() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "os") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "os") + .await + .unwrap(); + + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" import { type } from 'os'; export async function test() { return type() } "#, - ) - .await - .unwrap(); + ) + .await + .unwrap(); - let result = call_test::(&ctx, &module, ()).await; + let result = call_test::(&ctx, &module, ()).await; - assert!(result == "Linux" || result == "Windows_NT" || result == "Darwin"); - }) + assert!(result == "Linux" || result == "Windows_NT" || result == "Darwin"); }) .await; } #[tokio::test] async fn test_release() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "os") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "os") + .await + .unwrap(); + + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" import { release } from 'os'; export async function test() { return release() } "#, - ) - .await - .unwrap(); + ) + .await + .unwrap(); - let result = call_test::(&ctx, &module, ()).await; + let result = call_test::(&ctx, &module, ()).await; - assert!(!result.is_empty()); // Format is platform dependant - }) + assert!(!result.is_empty()); // Format is platform dependant }) .await; } #[tokio::test] async fn test_version() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "os") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "os") + .await + .unwrap(); + + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" import { version } from 'os'; export async function test() { return version() } "#, - ) - .await - .unwrap(); + ) + .await + .unwrap(); - let result = call_test::(&ctx, &module, ()).await; + let result = call_test::(&ctx, &module, ()).await; - assert!(!result.is_empty()); // Format is platform dependant - }) + assert!(!result.is_empty()); // Format is platform dependant }) .await; } #[tokio::test] async fn test_available_parallelism() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "os") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "os") + .await + .unwrap(); + + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" import { availableParallelism } from 'os'; export async function test() { return availableParallelism() } "#, - ) - .await - .unwrap(); + ) + .await + .unwrap(); - let result = call_test::(&ctx, &module, ()).await; + let result = call_test::(&ctx, &module, ()).await; - assert!(result > 0); - }) + assert!(result > 0); }) .await; } #[tokio::test] async fn test_eol() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "os") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "os") + .await + .unwrap(); + + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" import { EOL } from 'os'; export async function test() { return EOL } "#, - ) - .await - .unwrap(); + ) + .await + .unwrap(); - let result = call_test::(&ctx, &module, ()).await; - assert!(result == EOL); - }) + let result = call_test::(&ctx, &module, ()).await; + assert!(result == EOL); }) .await; } #[tokio::test] async fn test_arch() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "os") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "os") + .await + .unwrap(); + + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" import { arch } from 'os'; export async function test() { return arch() } "#, - ) - .await - .unwrap(); + ) + .await + .unwrap(); - let result = call_test::(&ctx, &module, ()).await; + let result = call_test::(&ctx, &module, ()).await; - assert!(!result.is_empty()); // Format is platform dependant - }) + assert!(!result.is_empty()); // Format is platform dependant }) .await; } diff --git a/modules/sqlite/Cargo.toml b/modules/sqlite/Cargo.toml index bbb1111..2c35b29 100644 --- a/modules/sqlite/Cargo.toml +++ b/modules/sqlite/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Emile Fugulin "] [dependencies] either = { version = "1" } -rquickjs = { version = ">=0.10,<0.12", features = [ +rquickjs = { version = "0.14", features = [ "array-buffer", "either", "macro", diff --git a/modules/sqlite/src/argument.rs b/modules/sqlite/src/argument.rs index 842a6f2..e11c93c 100644 --- a/modules/sqlite/src/argument.rs +++ b/modules/sqlite/src/argument.rs @@ -1,5 +1,4 @@ -use rquickjs::{Ctx, Exception, FromJs, Result, TypedArray}; -use rquickjs_extra_utils::ffi::{CString, CVec}; +use rquickjs::{CString, Ctx, Exception, FromJs, Result}; use rquickjs_extra_utils::result::ResultExt; use sqlx::Sqlite; use sqlx::query::Query; @@ -11,7 +10,7 @@ pub enum Argument<'js> { Integer(i64), Real(f64), Text(CString<'js>), - Blob(CVec<'js>), + Blob(Vec), } impl<'js> FromJs<'js> for Argument<'js> { @@ -27,12 +26,14 @@ impl<'js> FromJs<'js> for Argument<'js> { } else if let Some(string) = value.as_string() { return Ok(Argument::Text(CString::from_string(string.clone())?)); } else if let Some(object) = value.as_object() - && object.as_typed_array::().is_some() + && let Some(typed_array) = object.as_typed_array::() { - // Lifetime issue: https://github.com/DelSkayn/rquickjs/issues/356 - return Ok(Argument::Blob(CVec::from_array( - TypedArray::::from_value(value.clone()).or_throw(ctx)?, - )?)); + // SAFETY: We do not yield to the JS engine with the slice held. + let bytes = unsafe { typed_array.as_bytes() }; + let bytes = bytes + .ok_or_else(|| Exception::throw_type(ctx, "Typed array is detached"))? + .to_vec(); + return Ok(Argument::Blob(bytes)); } Err(Exception::throw_type( ctx, @@ -54,7 +55,7 @@ impl<'js> Argument<'js> { Argument::Null => query.try_bind::>(None).or_throw(ctx), Argument::Integer(int) => query.try_bind(*int).or_throw(ctx), Argument::Real(float) => query.try_bind(*float).or_throw(ctx), - Argument::Text(string) => query.try_bind(string.as_str()?).or_throw(ctx), + Argument::Text(string) => query.try_bind(string.as_str()).or_throw(ctx), Argument::Blob(blob) => query.try_bind(blob.as_slice()).or_throw(ctx), } } diff --git a/modules/sqlite/src/database.rs b/modules/sqlite/src/database.rs index a602b08..1f45799 100644 --- a/modules/sqlite/src/database.rs +++ b/modules/sqlite/src/database.rs @@ -47,66 +47,62 @@ mod tests { #[tokio::test] async fn test_database_exec() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "sqlite") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" - import { open } from "sqlite"; - - export async function test() { - const db = await open({ inMemory: true }); - await db.exec("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"); - await db.exec("INSERT INTO test (name) VALUES ('test');"); - return "ok"; - } - "#, - ) + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "sqlite") .await - .catch(&ctx) .unwrap(); - let result = call_test::(&ctx, &module, ()).await; - assert_eq!(result, "ok"); - }) + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" + import { open } from "sqlite"; + + export async function test() { + const db = await open({ inMemory: true }); + await db.exec("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"); + await db.exec("INSERT INTO test (name) VALUES ('test');"); + return "ok"; + } + "#, + ) + .await + .catch(&ctx) + .unwrap(); + + let result = call_test::(&ctx, &module, ()).await; + assert_eq!(result, "ok"); }) .await; } #[tokio::test] async fn test_database_close() { - test_async_with(|ctx| { - Box::pin(async move { - ModuleEvaluator::eval_rust::(ctx.clone(), "sqlite") - .await - .unwrap(); - - let module = ModuleEvaluator::eval_js( - ctx.clone(), - "test", - r#" - import { open } from "sqlite"; - - export async function test() { - const db = await open({ inMemory: true }); - await db.exec("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"); - await db.close(); - return "ok"; - } - "#, - ) + test_async_with(async |ctx| { + ModuleEvaluator::eval_rust::(ctx.clone(), "sqlite") .await - .catch(&ctx) .unwrap(); - let result = call_test::(&ctx, &module, ()).await; - assert_eq!(result, "ok"); - }) + let module = ModuleEvaluator::eval_js( + ctx.clone(), + "test", + r#" + import { open } from "sqlite"; + + export async function test() { + const db = await open({ inMemory: true }); + await db.exec("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"); + await db.close(); + return "ok"; + } + "#, + ) + .await + .catch(&ctx) + .unwrap(); + + let result = call_test::(&ctx, &module, ()).await; + assert_eq!(result, "ok"); }) .await; } diff --git a/modules/sqlite/src/statement.rs b/modules/sqlite/src/statement.rs index 0594698..880cabc 100644 --- a/modules/sqlite/src/statement.rs +++ b/modules/sqlite/src/statement.rs @@ -106,8 +106,7 @@ mod tests { #[tokio::test] async fn test_statement_all() { - test_async_with(|ctx| { - Box::pin(async move { + test_async_with(async |ctx| { ModuleEvaluator::eval_rust::(ctx.clone(), "sqlite") .await .unwrap(); @@ -135,15 +134,13 @@ mod tests { let result = call_test::(&ctx, &module, ()).await; assert_eq!(result, 2); - }) }) .await; } #[tokio::test] async fn test_statement_get() { - test_async_with(|ctx| { - Box::pin(async move { + test_async_with(async |ctx| { ModuleEvaluator::eval_rust::(ctx.clone(), "sqlite") .await .unwrap(); @@ -170,15 +167,13 @@ mod tests { let result = call_test::(&ctx, &module, ()).await; assert_eq!(result, 1); - }) }) .await; } #[tokio::test] async fn test_statement_run() { - test_async_with(|ctx| { - Box::pin(async move { + test_async_with(async |ctx| { ModuleEvaluator::eval_rust::(ctx.clone(), "sqlite") .await .unwrap(); @@ -204,7 +199,6 @@ mod tests { let result = call_test::(&ctx, &module, ()).await; assert_eq!(result, 2); - }) }) .await; } diff --git a/modules/timers/Cargo.toml b/modules/timers/Cargo.toml index bda1c43..606b95f 100644 --- a/modules/timers/Cargo.toml +++ b/modules/timers/Cargo.toml @@ -9,7 +9,7 @@ authors = ["Emile Fugulin "] [dependencies] log = { version = "0.4" } -rquickjs = { version = ">=0.10,<0.12", features = ["macro", "futures"] } +rquickjs = { version = "0.14", features = ["macro", "futures"] } tokio = { version = "1", features = ["sync", "time", "macros"] } [dev-dependencies] diff --git a/modules/timers/src/lib.rs b/modules/timers/src/lib.rs index 725b6e2..957fa1a 100644 --- a/modules/timers/src/lib.rs +++ b/modules/timers/src/lib.rs @@ -110,7 +110,6 @@ pub fn init(ctx: &Ctx<'_>) -> Result<()> { #[cfg(test)] mod tests { - use futures::FutureExt; use rquickjs::CatchResultExt; use rquickjs::promise::Promise; use rquickjs_extra_test::test_async_with; @@ -119,13 +118,12 @@ mod tests { #[tokio::test] async fn test_set_timeout() { - test_async_with(|ctx| { - async move { - init(&ctx).unwrap(); + test_async_with(async |ctx| { + init(&ctx).unwrap(); - let result = ctx - .eval::( - r#" + let result = ctx + .eval::( + r#" (async function(){ return new Promise((resolve, reject) => { @@ -135,30 +133,27 @@ mod tests { }); })() "#, - ) - .catch(&ctx) - .unwrap() - .into_future::() - .await - .catch(&ctx) - .unwrap(); - - assert_eq!("Hello World", result); - } - .boxed_local() + ) + .catch(&ctx) + .unwrap() + .into_future::() + .await + .catch(&ctx) + .unwrap(); + + assert_eq!("Hello World", result); }) .await } #[tokio::test] async fn test_set_interval() { - test_async_with(|ctx| { - async move { - init(&ctx).unwrap(); + test_async_with(async |ctx| { + init(&ctx).unwrap(); - let result = ctx - .eval::( - r#" + let result = ctx + .eval::( + r#" (async function(){ return new Promise((resolve, reject) => { @@ -171,17 +166,15 @@ mod tests { }); })() "#, - ) - .catch(&ctx) - .unwrap() - .into_future::() - .await - .catch(&ctx) - .unwrap(); - - assert_eq!(3, result); - } - .boxed_local() + ) + .catch(&ctx) + .unwrap() + .into_future::() + .await + .catch(&ctx) + .unwrap(); + + assert_eq!(3, result); }) .await } diff --git a/modules/url/Cargo.toml b/modules/url/Cargo.toml index 454db3f..09ab060 100644 --- a/modules/url/Cargo.toml +++ b/modules/url/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Emile Fugulin "] [dependencies] either = { version = "1" } -rquickjs = { version = ">=0.10,<0.12", features = ["either", "macro"] } +rquickjs = { version = "0.14", features = ["either", "macro"] } [dev-dependencies] rquickjs-extra-test = { path = "../../libs/test" }