Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ExternRef in wasmer-js #3224

Closed
wants to merge 7 commits into from
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 68 additions & 38 deletions lib/api/src/js/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::string::{String, ToString};

use wasmer_types::Type;

//use crate::ExternRef;
use crate::ExternRef;
use crate::js::externals::function::Function;

use super::store::{AsStoreMut, AsStoreRef};
Expand Down Expand Up @@ -33,7 +33,7 @@ pub enum Value {
F64(f64),

/// An `externref` value which can hold opaque data to the wasm instance itself.
//ExternRef(Option<ExternRef>),
ExternRef(Option<ExternRef>),

/// A first-class reference to a WebAssembly function.
FuncRef(Option<Function>),
Expand Down Expand Up @@ -80,7 +80,7 @@ impl Value {
Self::F32(_) => Type::F32,
Self::F64(_) => Type::F64,
Self::V128(_) => Type::V128,
//Self::ExternRef(_) => Type::ExternRef,
Self::ExternRef(_) => Type::ExternRef,
Self::FuncRef(_) => Type::FuncRef,
}
}
Expand All @@ -101,28 +101,27 @@ impl Value {
.unwrap_or(0_f64), //TODO is this correct?

Self::FuncRef(None) => 0_f64,
//Self::ExternRef(Some(ref e)) => unsafe { *e.address().0 } as .into_raw(),
//Self::ExternRef(None) => externref: 0 },
Self::ExternRef(Some(ref e)) => unsafe { *e.address().0 }.into_raw(),
Self::ExternRef(None) => 0_f64,
}
}

/// Converts a `f64` to a `Value`.
///
/// # Safety
///
pub unsafe fn from_raw(_store: &impl AsStoreRef, ty: Type, raw: f64) -> Self {
pub unsafe fn from_raw(store: &impl AsStoreRef, ty: Type, raw: f64) -> Self {
match ty {
Type::I32 => Self::I32(raw as _),
Type::I64 => Self::I64(raw as _),
Type::F32 => Self::F32(raw as _),
Type::F64 => Self::F64(raw),
Type::V128 => Self::V128(raw as _),
Type::FuncRef => todo!(),
Type::ExternRef => todo!(),
//Self::ExternRef(
//{
//VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(store, e)),
//),
Type::ExternRef => Self::ExternRef({
VMExternRef::from_raw(raw)
.map(|e| ExternRef::from_vm_externref(store, e))
}),
}
}

Expand All @@ -140,9 +139,9 @@ impl Value {
| Self::F32(_)
| Self::F64(_)
| Self::V128(_)
//| Self::ExternRef(None)
| Self::ExternRef(None)
| Self::FuncRef(None) => true,
//Self::ExternRef(Some(e)) => e.is_from_store(store),
Self::ExternRef(Some(e)) => e.is_from_store(store),
Self::FuncRef(Some(f)) => f.is_from_store(store),
}
}
Expand All @@ -154,7 +153,7 @@ impl Value {
(F32(f32) f32 unwrap_f32 *e)
(F64(f64) f64 unwrap_f64 *e)
(V128(u128) v128 unwrap_v128 *e)
//(ExternRef(&Option<ExternRef>) externref unwrap_externref e)
(ExternRef(&Option<ExternRef>) externref unwrap_externref e)
(FuncRef(&Option<Function>) funcref unwrap_funcref e)
}
}
Expand All @@ -167,8 +166,8 @@ impl fmt::Debug for Value {
Self::F32(v) => write!(f, "F32({:?})", v),
Self::F64(v) => write!(f, "F64({:?})", v),
Self::V128(v) => write!(f, "V128({:?})", v),
//Self::ExternRef(None) => write!(f, "Null ExternRef"),
//Self::ExternRef(Some(v)) => write!(f, "ExternRef({:?})", v),
Self::ExternRef(None) => write!(f, "Null ExternRef"),
Self::ExternRef(Some(v)) => write!(f, "ExternRef({:?})", v),
Self::FuncRef(None) => write!(f, "Null FuncRef"),
Self::FuncRef(Some(v)) => write!(f, "FuncRef({:?})", v),
}
Expand All @@ -183,7 +182,7 @@ impl ToString for Value {
Self::F32(v) => v.to_string(),
Self::F64(v) => v.to_string(),
Self::V128(v) => v.to_string(),
//Self::ExternRef(_) => "externref".to_string(),
Self::ExternRef(_) => "externref".to_string(),
Self::FuncRef(_) => "funcref".to_string(),
}
}
Expand Down Expand Up @@ -245,17 +244,17 @@ impl From<Option<Function>> for Value {
}
}

//impl From<ExternRef> for Value {
// fn from(val: ExternRef) -> Self {
// Self::ExternRef(Some(val))
// }
//}
//
//impl From<Option<ExternRef>> for Value {
// fn from(val: Option<ExternRef>) -> Self {
// Self::ExternRef(val)
// }
//}
impl From<ExternRef> for Value {
fn from(val: ExternRef) -> Self {
Self::ExternRef(Some(val))
}
}

impl From<Option<ExternRef>> for Value {
fn from(val: Option<ExternRef>) -> Self {
Self::ExternRef(val)
}
}

const NOT_I32: &str = "Value is not of Wasm type i32";
const NOT_I64: &str = "Value is not of Wasm type i64";
Expand Down Expand Up @@ -332,16 +331,47 @@ impl TryFrom<Value> for Option<Function> {
}
}

//impl TryFrom<Value> for Option<ExternRef> {
// type Error = &'static str;
//
// fn try_from(value: Value) -> Result<Self, Self::Error> {
// match value {
// Value::ExternRef(e) => Ok(e),
// _ => Err(NOT_EXTERNREF),
// }
// }
//}
impl TryFrom<Value> for Option<ExternRef> {
type Error = &'static str;

fn try_from(value: Value) -> Result<Self, Self::Error> {
match value {
Value::ExternRef(e) => Ok(e),
_ => Err("not an externref value"),
}
}
}

#[test]
fschutt marked this conversation as resolved.
Show resolved Hide resolved
fn get_set_externref_globals_via_api() -> anyhow::Result<()> {
use crate::{Store, Global, Value, ExternRef};

let mut store = Store::default();

// Initialize with a null externref.
let global = Global::new(
&mut store,
Value::ExternRef(None),
);
assert!(global.get(&mut store).unwrap_externref().is_none());

global.set(
&mut store,
Value::ExternRef(Some(ExternRef::new(&mut store, "hello".to_string()))),
)?;
let r = global.get(&mut store).unwrap_externref().unwrap();
assert_eq!(r.downcast(&store).unwrap(), "hello".to_string());

// Initialize with a non-null externref.
let global = Global::new(
&mut store,
Value::ExternRef(Some(ExternRef::new(&mut store, 42_i32))),
);
let r = global.get(&mut store).unwrap_externref().unwrap();
assert_eq!(r.downcast(&store).copied().unwrap(), 42_i32);

Ok(())
}

#[cfg(tests)]
mod tests {
Expand Down