use rusty_jsc::{JSContext, JSValue};
use wasmer_types::{ExternType, Type};
use crate::{AsStoreMut, AsStoreRef, Extern, Function, Value, jsc::engine::IntoJSC};
pub trait AsJsc: Sized {
type DefinitionType;
fn as_jsc_value(&self, store: &impl AsStoreRef) -> JSValue;
fn from_jsc_value(
store: &mut impl AsStoreMut,
type_: &Self::DefinitionType,
value: &JSValue,
) -> Result<Self, JSValue>;
}
#[inline]
pub fn jsc_value_to_wasmer(context: &JSContext, ty: &Type, js_val: &JSValue) -> Value {
match ty {
Type::I32 => Value::I32(js_val.to_number(context).unwrap() as _),
Type::I64 => {
let number = if js_val.is_number(context) {
js_val.to_number(context).unwrap() as _
} else {
js_val
.to_string(context)
.unwrap()
.to_string()
.parse()
.unwrap()
};
Value::I64(number)
}
Type::F32 => Value::F32(js_val.to_number(context).unwrap() as _),
Type::F64 => Value::F64(js_val.to_number(context).unwrap()),
Type::V128 => {
let number = if js_val.is_number(context) {
js_val.to_number(context).unwrap() as _
} else {
js_val
.to_string(context)
.unwrap()
.to_string()
.parse()
.unwrap()
};
Value::V128(number)
}
Type::ExternRef | Type::FuncRef | Type::ExceptionRef => unimplemented!(
"The type `{:?}` is not yet supported in the JSC Function API",
ty
),
}
}
impl AsJsc for Value {
type DefinitionType = Type;
fn as_jsc_value(&self, store: &impl AsStoreRef) -> JSValue {
let engine = store.as_store_ref();
let context = engine.jsc().context();
match self {
Self::I32(i) => JSValue::number(context, *i as _),
Self::I64(i) => JSValue::string(context, (*i).to_string()),
Self::F32(f) => JSValue::number(context, *f as _),
Self::F64(f) => JSValue::number(context, *f),
Self::V128(v) => JSValue::number(context, *v as _),
Self::FuncRef(Some(func)) => func.as_jsc().handle.function.clone().to_jsvalue(),
Self::FuncRef(None) => JSValue::null(context),
Self::ExternRef(_) => {
unimplemented!("ExternRefs are not yet supported in the JSC Function API",)
}
Self::ExceptionRef(_) => {
unimplemented!("ExceptionRefs are not yet supported in the JSC Function API",)
}
}
}
fn from_jsc_value(
store: &mut impl AsStoreMut,
type_: &Self::DefinitionType,
value: &JSValue,
) -> Result<Self, JSValue> {
let engine = store.as_store_ref();
let context = engine.jsc().context();
Ok(jsc_value_to_wasmer(context, type_, value))
}
}
impl AsJsc for Extern {
type DefinitionType = ExternType;
fn as_jsc_value(&self, _store: &impl AsStoreRef) -> JSValue {
match self {
Self::Memory(memory) => memory.as_jsc().handle.memory.clone().to_jsvalue(),
Self::Function(function) => function.as_jsc().handle.function.clone().to_jsvalue(),
Self::Table(table) => table.as_jsc().handle.table.clone().to_jsvalue(),
Self::Global(global) => global.as_jsc().handle.global.clone().to_jsvalue(),
Self::Tag(_) => unimplemented!("Tags are not yet supported in the JS Function API"),
}
}
fn from_jsc_value(
store: &mut impl AsStoreMut,
extern_type: &Self::DefinitionType,
val: &JSValue,
) -> Result<Self, JSValue> {
let engine = store.as_store_mut();
let context = engine.jsc().context();
match extern_type {
ExternType::Function(function_type) => {
let obj_val = val.to_object(context).unwrap();
Ok(Self::Function(Function::from_vm_extern(
store,
crate::vm::VMExternFunction::Jsc(
crate::backend::jsc::vm::VMExternFunction::new(
obj_val,
function_type.clone(),
),
),
)))
}
ExternType::Global(global_type) => {
let obj_val = val.to_object(context).unwrap();
Ok(Self::Global(crate::Global::from_vm_extern(
store,
crate::vm::VMExternGlobal::Jsc(crate::backend::jsc::vm::VMExternGlobal::new(
obj_val,
*global_type,
)),
)))
}
ExternType::Memory(memory_type) => {
let obj_val = val.to_object(context).unwrap();
Ok(Self::Memory(crate::Memory::from_vm_extern(
store,
crate::vm::VMExternMemory::Jsc(crate::backend::jsc::vm::VMExternMemory::new(
obj_val,
*memory_type,
)),
)))
}
ExternType::Table(table_type) => {
let obj_val = val.to_object(context).unwrap();
Ok(Self::Table(crate::Table::from_vm_extern(
store,
crate::vm::VMExternTable::Jsc(crate::backend::jsc::vm::VMExternTable::new(
obj_val,
*table_type,
)),
)))
}
ExternType::Tag(tag) => {
panic!("EH not supported in `jsc` rt")
}
}
}
}