use crate::js_utils::adapters::proxies::JsProxyInstanceId;
use crate::js_utils::adapters::{JsRealmAdapter, JsRuntimeAdapter};
use crate::js_utils::facades::{JsRuntimeFacade, JsRuntimeFacadeInner, JsValueType};
use crate::js_utils::JsError;
use crate::resolvable_future::ResolvableFuture;
use futures::Future;
use serde::Serialize;
use serde_json::Value;
use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Formatter};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use string_cache::DefaultAtom;
pub struct CachedJsObjectRef {
pub(crate) id: i32,
realm_id: String,
drop_action: Mutex<Option<Box<dyn FnOnce() + Send>>>,
}
pub struct CachedJsPromiseRef {
pub cached_object: CachedJsObjectRef,
}
pub struct CachedJsArrayRef {
pub cached_object: CachedJsObjectRef,
}
pub struct CachedJsFunctionRef {
pub cached_object: CachedJsObjectRef,
}
impl CachedJsObjectRef {
pub(crate) fn new<R: JsRealmAdapter + 'static>(realm: &R, obj: &R::JsValueAdapterType) -> Self {
let id = realm.js_cache_add(obj);
let rti_ref = realm.js_get_runtime_facade_inner();
let drop_id = id;
let drop_realm_name = realm.js_get_realm_id().to_string();
Self::new2(id, realm.js_get_realm_id().to_string(), move || {
if let Some(rti) = rti_ref.upgrade() {
rti.js_add_rt_task_to_event_loop_void(move |rt| {
if let Some(realm) = rt.js_get_realm(drop_realm_name.as_str()) {
realm.js_cache_dispose(drop_id);
}
})
}
})
}
fn new2<F: FnOnce() + Send + 'static>(id: i32, realm_name: String, drop_action: F) -> Self {
Self {
id,
realm_id: realm_name,
drop_action: Mutex::new(Some(Box::new(drop_action))),
}
}
pub async fn to_json_string<R: JsRuntimeFacadeInner + 'static>(
&self,
rti: &R,
) -> Result<String, JsError> {
let id = self.id;
let realm_name = self.realm_id.clone();
rti.js_add_rt_task_to_event_loop(move |rt| {
if let Some(realm) = rt.js_get_realm(realm_name.as_str()) {
realm.js_cache_with(id, |obj| realm.js_json_stringify(obj, None))
} else {
Err(JsError::new_str("no such realm"))
}
})
.await
}
pub async fn js_get_object<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
) -> Result<HashMap<String, JsValueFacade>, JsError> {
let id = self.id;
let realm_name = self.realm_id.clone();
rti.js_add_rt_task_to_event_loop(move |rt| {
if let Some(realm) = rt.js_get_realm(realm_name.as_str()) {
let mut ret = HashMap::new();
let results = realm.js_cache_with(id, |obj| {
realm.js_object_traverse(obj, |name, value| {
Ok((name.to_string(), realm.to_js_value_facade(value)))
})
})?;
for result in results {
ret.insert(result.0, result.1?);
}
Ok(ret)
} else {
Err(JsError::new_str("no such realm"))
}
})
.await
}
pub async fn js_get_serde_value<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
) -> Result<serde_json::Value, JsError> {
let id = self.id;
let realm_name = self.realm_id.clone();
rti.js_add_rt_task_to_event_loop(move |rt| {
if let Some(realm) = rt.js_get_realm(realm_name.as_str()) {
realm.js_cache_with(id, |obj| realm.js_value_adapter_to_serde_value(obj))
} else {
Err(JsError::new_str("no such realm"))
}
})
.await
}
pub fn with_obj_sync<
S: Send + 'static,
R: JsRuntimeFacadeInner,
C: FnOnce(&<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType, &<<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType as JsRealmAdapter>::JsValueAdapterType) -> S + Send + 'static,
>(
&self,
rti: &R,
consumer: C,
) -> Result<S, JsError>{
let id = self.id;
let realm_id = self.realm_id.clone();
rti.js_exe_rt_task_in_event_loop(move |rt| {
if let Some(realm) = rt.js_get_realm(realm_id.as_str()) {
Ok(realm.js_cache_with(id, |obj| consumer(realm, obj)))
} else {
Err(JsError::new_str("Realm was disposed"))
}
})
}
pub fn with_obj_void<
S: Send + 'static,
R: JsRuntimeFacadeInner,
C: FnOnce(&<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType, &<<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType as JsRealmAdapter>::JsValueAdapterType) -> S + Send + 'static,
>(
&self,
rti: &R,
consumer: C,
){
let id = self.id;
let realm_id = self.realm_id.clone();
rti.js_add_rt_task_to_event_loop_void(move |rt| {
if let Some(realm) = rt.js_get_realm(realm_id.as_str()) {
realm.js_cache_with(id, |obj| consumer(realm, obj));
} else {
log::error!("no such realm");
}
})
}
pub async fn with_obj<
S: Send + 'static,
R: JsRuntimeFacadeInner,
C: FnOnce(&<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType, &<<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType as JsRealmAdapter>::JsValueAdapterType) -> S + Send + 'static,
>(
&self,
rti: &R,
consumer: C,
) -> Result<S, JsError>{
let id = self.id;
let realm_id = self.realm_id.clone();
rti.js_add_rt_task_to_event_loop(move |rt| {
if let Some(realm) = rt.js_get_realm(realm_id.as_str()) {
Ok(realm.js_cache_with(id, |obj| consumer(realm, obj)))
} else {
Err(JsError::new_str("Realm was disposed"))
}
})
.await
}
}
impl Drop for CachedJsObjectRef {
fn drop(&mut self) {
let lck = &mut *self.drop_action.lock().unwrap();
if let Some(da) = lck.take() {
da();
}
}
}
impl CachedJsPromiseRef {
pub async fn js_get_serde_value<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
) -> Result<serde_json::Value, JsError> {
self.cached_object.js_get_serde_value(rti).await
}
pub async fn to_json_string<R: JsRuntimeFacadeInner + 'static>(
&self,
rti: &R,
) -> Result<String, JsError> {
self.cached_object.to_json_string(rti).await
}
pub async fn js_get_promise_result<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
) -> Result<Result<JsValueFacade, JsValueFacade>, JsError> {
let fut: ResolvableFuture<Result<Result<JsValueFacade, JsValueFacade>, JsError>> =
ResolvableFuture::new();
let resolver = fut.get_resolver();
let resolver1 = resolver.clone();
let resolver2 = resolver.clone();
self.cached_object.with_obj_void(rti, move |realm, obj| {
let res = || {
let then_func = realm.js_function_create(
"then",
move |realm, _this, args| {
let resolution = &args[0];
let send_res = match realm.to_js_value_facade(resolution) {
Ok(vf) => resolver1.resolve(Ok(Ok(vf))),
Err(conv_err) => resolver1.resolve(Err(conv_err)),
};
send_res
.map_err(|e| JsError::new_string(format!("could not send: {}", e)))?;
realm.js_undefined_create()
},
1,
)?;
let catch_func = realm.js_function_create(
"catch",
move |realm, _this, args| {
let rejection = &args[0];
let send_res = match realm.to_js_value_facade(rejection) {
Ok(vf) => resolver2.resolve(Ok(Err(vf))),
Err(conv_err) => resolver2.resolve(Err(conv_err)),
};
send_res
.map_err(|e| JsError::new_string(format!("could not send: {}", e)))?;
realm.js_undefined_create()
},
1,
)?;
realm.js_promise_add_reactions(obj, Some(then_func), Some(catch_func), None)?;
Ok(())
};
match res() {
Ok(_) => {}
Err(e) => match resolver.resolve(Err(e)) {
Ok(_) => {}
Err(e) => {
log::error!("failed to resolve 47643: {}", e);
}
},
}
});
fut.await
}
}
impl CachedJsArrayRef {
pub async fn js_get_serde_value<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
) -> Result<serde_json::Value, JsError> {
self.cached_object.js_get_serde_value(rti).await
}
pub async fn to_json_string<R: JsRuntimeFacadeInner + 'static>(
&self,
rti: &R,
) -> Result<String, JsError> {
self.cached_object.to_json_string(rti).await
}
pub async fn js_get_array<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
) -> Result<Vec<JsValueFacade>, JsError> {
self.cached_object
.with_obj(rti, |realm, arr| {
let mut vec: Vec<JsValueFacade> = vec![];
realm.js_array_traverse_mut(arr, |_index, element| {
vec.push(realm.to_js_value_facade(element)?);
Ok(())
})?;
Ok(vec)
})
.await?
}
}
impl CachedJsFunctionRef {
pub async fn js_get_serde_value<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
) -> Result<serde_json::Value, JsError> {
self.cached_object.js_get_serde_value(rti).await
}
pub fn js_invoke_function<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
args: Vec<JsValueFacade>,
) -> Pin<Box<dyn futures::Future<Output = Result<JsValueFacade, JsError>> + Send>> {
let cached_obj_id = self.cached_object.id;
let realm_id = self.cached_object.realm_id.clone();
rti.js_add_rt_task_to_event_loop(move |rt| {
if let Some(realm) = rt.js_get_realm(realm_id.as_str()) {
realm.js_cache_with(cached_obj_id, move |func_adapter| {
let mut adapter_args = vec![];
for arg in args {
adapter_args.push(realm.from_js_value_facade(arg)?);
}
let adapter_refs: Vec<&<<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType as JsRealmAdapter>::JsValueAdapterType> = adapter_args.iter().collect();
let val_adapter = realm.js_function_invoke(
None,
func_adapter,
&adapter_refs,
)?;
realm.to_js_value_facade(&val_adapter)
})
} else {
Ok(JsValueFacade::Null)
}
})
}
pub fn js_invoke_function_sync<R: JsRuntimeFacadeInner>(
&self,
rti: &R,
args: Vec<JsValueFacade>,
) -> Result<JsValueFacade, JsError> {
self.cached_object.with_obj_sync(rti, |realm, func_adapter| {
let mut adapter_args = vec![];
for arg in args {
adapter_args.push(realm.from_js_value_facade(arg)?);
}
let adapter_refs: Vec<&<<<<R as JsRuntimeFacadeInner>::JsRuntimeFacadeType as JsRuntimeFacade>::JsRuntimeAdapterType as JsRuntimeAdapter>::JsRealmAdapterType as JsRealmAdapter>::JsValueAdapterType> = adapter_args.iter().collect();
let val_adapter = realm.js_function_invoke(
None,
func_adapter,
&adapter_refs,
)?;
realm.to_js_value_facade(&val_adapter)
})?
}
}
pub enum TypedArrayType {
Uint8,
}
#[allow(clippy::type_complexity)]
pub enum JsValueFacade {
I32 {
val: i32,
},
F64 {
val: f64,
},
String {
val: DefaultAtom,
},
Boolean {
val: bool,
},
JsObject {
cached_object: CachedJsObjectRef,
},
JsPromise {
cached_promise: CachedJsPromiseRef,
},
JsArray {
cached_array: CachedJsArrayRef,
},
JsFunction {
cached_function: CachedJsFunctionRef,
},
Object {
val: HashMap<String, JsValueFacade>,
},
Array {
val: Vec<JsValueFacade>,
},
Promise {
producer: Mutex<
Option<Pin<Box<dyn Future<Output = Result<JsValueFacade, JsError>> + Send + 'static>>>,
>,
},
Function {
name: String,
arg_count: u32,
func: Arc<Box<dyn Fn(&[JsValueFacade]) -> Result<JsValueFacade, JsError> + Send + Sync>>,
},
JsError {
val: JsError,
},
ProxyInstance {
namespace: &'static [&'static str],
class_name: &'static str,
instance_id: JsProxyInstanceId,
},
TypedArray {
buffer: Vec<u8>,
array_type: TypedArrayType,
},
JsonStr {
json: String,
},
SerdeValue {
value: serde_json::Value,
},
Null,
Undefined,
}
impl JsValueFacade {
pub fn from_serializable<T: Serialize>(obj: &T) -> Result<Self, Box<dyn Error>> {
let json = serde_json::to_string(obj)?;
Ok(Self::JsonStr { json })
}
pub fn new_i32(val: i32) -> Self {
Self::I32 { val }
}
pub fn new_f64(val: f64) -> Self {
Self::F64 { val }
}
pub fn new_bool(val: bool) -> Self {
Self::Boolean { val }
}
pub fn new_str_atom(val: DefaultAtom) -> Self {
Self::String { val }
}
pub fn new_str(val: &str) -> Self {
Self::String {
val: DefaultAtom::from(val),
}
}
pub fn new_string(val: String) -> Self {
Self::String {
val: DefaultAtom::from(val),
}
}
pub fn new_callback<
F: Fn(&[JsValueFacade]) -> Result<JsValueFacade, JsError> + Send + Sync + 'static,
>(
callback: F,
) -> Self {
Self::Function {
name: "".to_string(),
arg_count: 0,
func: Arc::new(Box::new(callback)),
}
}
pub fn new_function<
F: Fn(&[JsValueFacade]) -> Result<JsValueFacade, JsError> + Send + Sync + 'static,
>(
name: &str,
function: F,
arg_count: u32,
) -> Self {
Self::Function {
name: name.to_string(),
arg_count,
func: Arc::new(Box::new(function)),
}
}
pub fn new_promise<T, R, P, M>(producer: P) -> Self
where
T: JsRealmAdapter,
P: Future<Output = Result<JsValueFacade, JsError>> + Send + 'static,
{
JsValueFacade::Promise {
producer: Mutex::new(Some(Box::pin(producer))),
}
}
pub fn is_i32(&self) -> bool {
matches!(self, JsValueFacade::I32 { .. })
}
pub fn is_f64(&self) -> bool {
matches!(self, JsValueFacade::F64 { .. })
}
pub fn is_bool(&self) -> bool {
matches!(self, JsValueFacade::Boolean { .. })
}
pub fn is_string(&self) -> bool {
matches!(self, JsValueFacade::String { .. })
}
pub fn get_i32(&self) -> i32 {
match self {
JsValueFacade::I32 { val } => *val,
_ => {
panic!("Not an i32");
}
}
}
pub fn get_f64(&self) -> f64 {
match self {
JsValueFacade::F64 { val } => *val,
_ => {
panic!("Not an f64");
}
}
}
pub fn get_bool(&self) -> bool {
match self {
JsValueFacade::Boolean { val } => *val,
_ => {
panic!("Not a boolean");
}
}
}
pub fn get_str(&self) -> &str {
match self {
JsValueFacade::String { val } => val,
_ => {
panic!("Not a string");
}
}
}
pub fn get_str_atom(&self) -> &DefaultAtom {
match self {
JsValueFacade::String { val } => val,
_ => {
panic!("Not a string");
}
}
}
pub fn is_null_or_undefined(&self) -> bool {
matches!(self, JsValueFacade::Null | JsValueFacade::Undefined)
}
pub fn get_value_type(&self) -> JsValueType {
match self {
JsValueFacade::I32 { .. } => JsValueType::I32,
JsValueFacade::F64 { .. } => JsValueType::F64,
JsValueFacade::String { .. } => JsValueType::String,
JsValueFacade::Boolean { .. } => JsValueType::Boolean,
JsValueFacade::JsObject { .. } => JsValueType::Object,
JsValueFacade::Null => JsValueType::Null,
JsValueFacade::Undefined => JsValueType::Undefined,
JsValueFacade::Object { .. } => JsValueType::Object,
JsValueFacade::Array { .. } => JsValueType::Array,
JsValueFacade::Promise { .. } => JsValueType::Promise,
JsValueFacade::Function { .. } => JsValueType::Function,
JsValueFacade::JsPromise { .. } => JsValueType::Promise,
JsValueFacade::JsArray { .. } => JsValueType::Array,
JsValueFacade::JsFunction { .. } => JsValueType::Function,
JsValueFacade::JsError { .. } => JsValueType::Error,
JsValueFacade::ProxyInstance { .. } => JsValueType::Object,
JsValueFacade::TypedArray { .. } => JsValueType::Object,
JsValueFacade::JsonStr { .. } => JsValueType::Object,
JsValueFacade::SerdeValue { value } => match value {
serde_json::Value::Null => JsValueType::Null,
serde_json::Value::Bool(_) => JsValueType::Boolean,
serde_json::Value::Number(_) => {
if value.is_i64() {
let num = value.as_i64().unwrap();
if num <= i32::MAX as i64 {
JsValueType::I32
} else {
JsValueType::F64
}
} else if value.is_f64() {
JsValueType::F64
} else {
let num = value.as_u64().unwrap();
if num <= i32::MAX as u64 {
JsValueType::I32
} else {
JsValueType::F64
}
}
}
serde_json::Value::String(_) => JsValueType::String,
serde_json::Value::Array(_) => JsValueType::Array,
serde_json::Value::Object(_) => JsValueType::Object,
},
}
}
pub fn stringify(&self) -> String {
match self {
JsValueFacade::I32 { val } => {
format!("I32: {}", val)
}
JsValueFacade::F64 { val } => {
format!("F64: {}", val)
}
JsValueFacade::String { val } => {
format!("String: {}", val)
}
JsValueFacade::Boolean { val } => {
format!("Boolean: {}", val)
}
JsValueFacade::JsObject { cached_object } => {
format!(
"JsObject: [{}.{}]",
cached_object.realm_id, cached_object.id
)
}
JsValueFacade::JsPromise { cached_promise } => {
format!(
"JsPromise: [{}.{}]",
cached_promise.cached_object.realm_id, cached_promise.cached_object.id
)
}
JsValueFacade::JsArray { cached_array } => {
format!(
"JsArray: [{}.{}]",
cached_array.cached_object.realm_id, cached_array.cached_object.id
)
}
JsValueFacade::JsFunction { cached_function } => {
format!(
"JsFunction: [{}.{}]",
cached_function.cached_object.realm_id, cached_function.cached_object.id
)
}
JsValueFacade::Object { val } => {
format!("Object: [len={}]", val.keys().len())
}
JsValueFacade::Array { val } => {
format!("Array: [len={}]", val.len())
}
JsValueFacade::Promise { .. } => "Promise".to_string(),
JsValueFacade::Function { .. } => "Function".to_string(),
JsValueFacade::Null => "Null".to_string(),
JsValueFacade::Undefined => "Undefined".to_string(),
JsValueFacade::JsError { val } => format!("{}", val),
JsValueFacade::ProxyInstance { .. } => "ProxyInstance".to_string(),
JsValueFacade::TypedArray { .. } => "TypedArray".to_string(),
JsValueFacade::JsonStr { json } => format!("JsonStr: '{}'", json),
JsValueFacade::SerdeValue { value } => format!("Serde value: {}", value),
}
}
pub async fn to_serde_value<R: JsRuntimeFacadeInner + 'static>(
&self,
rti: &R,
) -> Result<serde_json::Value, JsError> {
match self {
JsValueFacade::I32 { val } => Ok(serde_json::Value::from(*val)),
JsValueFacade::F64 { val } => Ok(serde_json::Value::from(*val)),
JsValueFacade::String { val } => Ok(serde_json::Value::from(val.to_string())),
JsValueFacade::Boolean { val } => Ok(serde_json::Value::from(*val)),
JsValueFacade::JsObject { cached_object } => {
cached_object.js_get_serde_value(rti).await
}
JsValueFacade::JsPromise { cached_promise } => {
cached_promise.js_get_serde_value(rti).await
}
JsValueFacade::JsArray { cached_array } => cached_array.js_get_serde_value(rti).await,
JsValueFacade::JsFunction { .. } => Ok(Value::Null),
JsValueFacade::Object { .. } => Ok(Value::Null),
JsValueFacade::Array { .. } => Ok(Value::Null),
JsValueFacade::Promise { .. } => Ok(Value::Null),
JsValueFacade::Function { .. } => Ok(Value::Null),
JsValueFacade::Null => Ok(Value::Null),
JsValueFacade::Undefined => Ok(Value::Null),
JsValueFacade::JsError { .. } => Ok(Value::Null),
JsValueFacade::ProxyInstance { .. } => Ok(Value::Null),
JsValueFacade::TypedArray { .. } => Ok(Value::Null),
JsValueFacade::JsonStr { json } => Ok(serde_json::from_str(json).unwrap()),
JsValueFacade::SerdeValue { value } => Ok(value.clone()),
}
}
pub async fn to_json_string<R: JsRuntimeFacadeInner + 'static>(
&self,
rti: &R,
) -> Result<String, JsError> {
match self {
JsValueFacade::I32 { val } => Ok(format!("{}", val)),
JsValueFacade::F64 { val } => Ok(format!("{}", val)),
JsValueFacade::String { val } => Ok(format!("'{}'", val.replace('\'', "\\'"))),
JsValueFacade::Boolean { val } => Ok(format!("{}", val)),
JsValueFacade::JsObject { cached_object } => cached_object.to_json_string(rti).await,
JsValueFacade::JsPromise { cached_promise } => cached_promise.to_json_string(rti).await,
JsValueFacade::JsArray { cached_array } => cached_array.to_json_string(rti).await,
JsValueFacade::JsFunction { .. } => Ok("function () {}".to_string()),
JsValueFacade::Object { .. } => Ok("{}".to_string()),
JsValueFacade::Array { .. } => Ok("{}".to_string()),
JsValueFacade::Promise { .. } => Ok("{}".to_string()),
JsValueFacade::Function { .. } => Ok("function () {}".to_string()),
JsValueFacade::Null => Ok("null".to_string()),
JsValueFacade::Undefined => Ok("undefined".to_string()),
JsValueFacade::JsError { val } => Ok(format!("'{}'", val)),
JsValueFacade::ProxyInstance { .. } => Ok("{}".to_string()),
JsValueFacade::TypedArray { .. } => Ok("[]".to_string()),
JsValueFacade::JsonStr { json } => Ok(json.clone()),
JsValueFacade::SerdeValue { value } => Ok(serde_json::to_string(value).unwrap()),
}
}
}
impl Debug for JsValueFacade {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.stringify().as_str())
}
}
pub trait JsValueConvertable {
fn to_js_value_facade(self) -> JsValueFacade;
}
impl JsValueConvertable for serde_json::Value {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::SerdeValue { value: self }
}
}
impl JsValueConvertable for bool {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::new_bool(self)
}
}
impl JsValueConvertable for i32 {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::new_i32(self)
}
}
impl JsValueConvertable for f64 {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::new_f64(self)
}
}
impl JsValueConvertable for &str {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::new_str(self)
}
}
impl JsValueConvertable for String {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::new_string(self)
}
}
impl JsValueConvertable for Vec<u8> {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::TypedArray {
buffer: self,
array_type: TypedArrayType::Uint8,
}
}
}
impl JsValueConvertable for Vec<JsValueFacade> {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::Array { val: self }
}
}
impl JsValueConvertable for HashMap<String, JsValueFacade> {
fn to_js_value_facade(self) -> JsValueFacade {
JsValueFacade::Object { val: self }
}
}
#[cfg(test)]
pub mod tests {
use crate::js_utils::facades::values::{CachedJsFunctionRef, CachedJsObjectRef, JsValueFacade};
use std::sync::Mutex;
#[test]
fn test_jsvf() {
fn test<A: Send + Sync>(_a: A) {}
test(JsValueFacade::Null);
test(JsValueFacade::JsFunction {
cached_function: CachedJsFunctionRef {
cached_object: CachedJsObjectRef {
id: 0,
realm_id: "".to_string(),
drop_action: Mutex::new(None),
},
},
})
}
}