You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
339 lines
10 KiB
339 lines
10 KiB
use wasmtime::*;
|
|
|
|
#[test]
|
|
fn get_none() {
|
|
let mut store = Store::<()>::default();
|
|
let ty = TableType::new(RefType::FUNCREF, 1, None);
|
|
let table = Table::new(&mut store, ty, Ref::Func(None)).unwrap();
|
|
match table.get(&mut store, 0) {
|
|
Some(Ref::Func(None)) => {}
|
|
_ => panic!(),
|
|
}
|
|
assert!(table.get(&mut store, 1).is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn fill_wrong() {
|
|
let mut store = Store::<()>::default();
|
|
let ty = TableType::new(RefType::FUNCREF, 1, None);
|
|
let table = Table::new(&mut store, ty, Ref::Func(None)).unwrap();
|
|
assert_eq!(
|
|
table
|
|
.fill(&mut store, 0, Ref::Extern(None), 1)
|
|
.map_err(|e| e.to_string())
|
|
.unwrap_err(),
|
|
"type mismatch: value does not match table element type"
|
|
);
|
|
|
|
let ty = TableType::new(RefType::EXTERNREF, 1, None);
|
|
let table = Table::new(&mut store, ty, Ref::Extern(None)).unwrap();
|
|
assert_eq!(
|
|
table
|
|
.fill(&mut store, 0, Ref::Func(None), 1)
|
|
.map_err(|e| e.to_string())
|
|
.unwrap_err(),
|
|
"type mismatch: value does not match table element type"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn copy_wrong() {
|
|
let mut store = Store::<()>::default();
|
|
let ty = TableType::new(RefType::FUNCREF, 1, None);
|
|
let table1 = Table::new(&mut store, ty, Ref::Func(None)).unwrap();
|
|
let ty = TableType::new(RefType::EXTERNREF, 1, None);
|
|
let table2 = Table::new(&mut store, ty, Ref::Extern(None)).unwrap();
|
|
assert_eq!(
|
|
Table::copy(&mut store, &table1, 0, &table2, 0, 1)
|
|
.map_err(|e| e.to_string())
|
|
.unwrap_err(),
|
|
"type mismatch: source table's element type does not match destination table's element type"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg_attr(miri, ignore)]
|
|
fn null_elem_segment_works_with_imported_table() -> Result<()> {
|
|
let mut store = Store::<()>::default();
|
|
let ty = TableType::new(RefType::FUNCREF, 1, None);
|
|
let table = Table::new(&mut store, ty, Ref::Func(None))?;
|
|
let module = Module::new(
|
|
store.engine(),
|
|
r#"
|
|
(module
|
|
(import "" "" (table (;0;) 1 funcref))
|
|
(func
|
|
i32.const 0
|
|
table.get 0
|
|
drop
|
|
)
|
|
(start 0)
|
|
(elem (;0;) (i32.const 0) funcref (ref.null func))
|
|
)
|
|
"#,
|
|
)?;
|
|
Instance::new(&mut store, &module, &[table.into()])?;
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn i31ref_table_new() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_function_references(true);
|
|
config.wasm_gc(true);
|
|
|
|
let engine = Engine::new(&config)?;
|
|
let mut store = Store::new(&engine, ());
|
|
|
|
for (elem_ty, inits) in [
|
|
(
|
|
RefType::I31REF,
|
|
vec![
|
|
Ref::Any(None),
|
|
AnyRef::from_i31(&mut store, I31::default()).into(),
|
|
],
|
|
),
|
|
(
|
|
RefType::new(false, HeapType::I31),
|
|
vec![AnyRef::from_i31(&mut store, I31::default()).into()],
|
|
),
|
|
] {
|
|
let table_ty = TableType::new(elem_ty, 10, None);
|
|
for init in inits {
|
|
Table::new(&mut store, table_ty.clone(), init)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn i31ref_table_get() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_function_references(true);
|
|
config.wasm_gc(true);
|
|
|
|
let engine = Engine::new(&config)?;
|
|
let mut store = Store::new(&engine, ());
|
|
|
|
for (elem_ty, inits) in [
|
|
(
|
|
RefType::I31REF,
|
|
vec![
|
|
Ref::Any(None),
|
|
AnyRef::from_i31(&mut store, I31::default()).into(),
|
|
],
|
|
),
|
|
(
|
|
RefType::new(false, HeapType::I31),
|
|
vec![AnyRef::from_i31(&mut store, I31::default()).into()],
|
|
),
|
|
] {
|
|
let table_ty = TableType::new(elem_ty, 10, None);
|
|
for init in inits {
|
|
let table = Table::new(&mut store, table_ty.clone(), init.clone())?;
|
|
for i in 0..10 {
|
|
let val = table.get(&mut store, i).unwrap();
|
|
assert_eq!(init.is_null(), val.is_null());
|
|
assert_eq!(
|
|
init.as_any()
|
|
.expect("is anyref")
|
|
.map(|a| a.as_i31(&store).expect("is in scope")),
|
|
val.as_any()
|
|
.expect("is anyref")
|
|
.map(|a| a.as_i31(&store).expect("is in scope"))
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn i31ref_table_set() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_function_references(true);
|
|
config.wasm_gc(true);
|
|
|
|
let engine = Engine::new(&config)?;
|
|
let mut store = Store::new(&engine, ());
|
|
|
|
for (elem_ty, inits, vals) in [
|
|
(
|
|
RefType::I31REF,
|
|
vec![
|
|
Ref::Any(None),
|
|
AnyRef::from_i31(&mut store, I31::default()).into(),
|
|
],
|
|
vec![
|
|
Ref::Any(None),
|
|
AnyRef::from_i31(&mut store, I31::wrapping_u32(42)).into(),
|
|
],
|
|
),
|
|
(
|
|
RefType::new(false, HeapType::I31),
|
|
vec![AnyRef::from_i31(&mut store, I31::default()).into()],
|
|
vec![AnyRef::from_i31(&mut store, I31::wrapping_u32(42)).into()],
|
|
),
|
|
] {
|
|
let table_ty = TableType::new(elem_ty, 10, None);
|
|
for init in inits {
|
|
for expected in vals.clone() {
|
|
let table = Table::new(&mut store, table_ty.clone(), init.clone())?;
|
|
for i in 0..10 {
|
|
table.set(&mut store, i, expected.clone())?;
|
|
let actual = table.get(&mut store, i).unwrap();
|
|
assert_eq!(expected.is_null(), actual.is_null());
|
|
assert_eq!(
|
|
expected
|
|
.as_any()
|
|
.expect("is anyref")
|
|
.map(|a| a.as_i31(&store).expect("is in scope")),
|
|
actual
|
|
.as_any()
|
|
.expect("is anyref")
|
|
.map(|a| a.as_i31(&store).expect("is in scope"))
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn i31ref_table_grow() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_function_references(true);
|
|
config.wasm_gc(true);
|
|
|
|
let engine = Engine::new(&config)?;
|
|
let mut store = Store::new(&engine, ());
|
|
|
|
for (elem_ty, init) in [
|
|
(RefType::I31REF, Ref::Any(None)),
|
|
(
|
|
RefType::new(false, HeapType::I31),
|
|
AnyRef::from_i31(&mut store, I31::default()).into(),
|
|
),
|
|
] {
|
|
let table_ty = TableType::new(elem_ty, 10, None);
|
|
let table = Table::new(&mut store, table_ty, init)?;
|
|
assert_eq!(table.size(&store), 10);
|
|
for i in 10..20 {
|
|
assert!(table.get(&mut store, i).is_none());
|
|
}
|
|
let expected = I31::wrapping_u32(42);
|
|
let grow_val = AnyRef::from_i31(&mut store, expected);
|
|
table.grow(&mut store, 10, grow_val.into())?;
|
|
for i in 10..20 {
|
|
let actual = table.get(&mut store, i).unwrap();
|
|
assert_eq!(
|
|
actual
|
|
.as_any()
|
|
.expect("is anyref")
|
|
.expect("is non null")
|
|
.as_i31(&store)
|
|
.expect("is in scope")
|
|
.expect("is i31"),
|
|
expected,
|
|
);
|
|
}
|
|
assert!(table.get(&mut store, 20).is_none());
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn i31ref_table_fill() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_function_references(true);
|
|
config.wasm_gc(true);
|
|
|
|
let engine = Engine::new(&config)?;
|
|
let mut store = Store::new(&engine, ());
|
|
|
|
let table_ty = TableType::new(RefType::I31REF, 10, None);
|
|
let table = Table::new(&mut store, table_ty, Ref::Any(None))?;
|
|
|
|
let expected = I31::wrapping_u32(42);
|
|
let fill_val = AnyRef::from_i31(&mut store, expected);
|
|
let dst = 3;
|
|
let len = 4;
|
|
table.fill(&mut store, dst, fill_val.into(), len)?;
|
|
|
|
for i in 0..dst {
|
|
let actual = table.get(&mut store, i).unwrap();
|
|
assert!(actual.as_any().expect("is anyref").is_none());
|
|
}
|
|
for i in dst..dst + len {
|
|
let actual = table.get(&mut store, i).unwrap();
|
|
assert_eq!(
|
|
actual
|
|
.as_any()
|
|
.expect("is anyref")
|
|
.expect("is non null")
|
|
.as_i31(&store)
|
|
.expect("is in scope")
|
|
.expect("is i31"),
|
|
expected,
|
|
);
|
|
}
|
|
for i in dst + len..10 {
|
|
let actual = table.get(&mut store, i).unwrap();
|
|
assert!(actual.as_any().expect("is anyref").is_none());
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn i31ref_table_copy() -> Result<()> {
|
|
let mut config = Config::new();
|
|
config.wasm_function_references(true);
|
|
config.wasm_gc(true);
|
|
|
|
let engine = Engine::new(&config)?;
|
|
let mut store = Store::new(&engine, ());
|
|
|
|
let table_ty = TableType::new(RefType::I31REF, 10, None);
|
|
let dst_table = Table::new(&mut store, table_ty.clone(), Ref::Any(None))?;
|
|
|
|
let expected = I31::wrapping_u32(42);
|
|
let init_val = AnyRef::from_i31(&mut store, expected);
|
|
let src_table = Table::new(&mut store, table_ty, init_val.into())?;
|
|
|
|
let dst_index = 1;
|
|
let src_index = 2;
|
|
let len = 3;
|
|
Table::copy(
|
|
&mut store, &dst_table, dst_index, &src_table, src_index, len,
|
|
)?;
|
|
|
|
for i in 0..dst_index {
|
|
let actual = dst_table.get(&mut store, i).unwrap();
|
|
assert!(actual.as_any().expect("is anyref").is_none());
|
|
}
|
|
for i in dst_index..dst_index + len {
|
|
let actual = dst_table.get(&mut store, i).unwrap();
|
|
assert_eq!(
|
|
actual
|
|
.as_any()
|
|
.expect("is anyref")
|
|
.expect("is non null")
|
|
.as_i31(&store)
|
|
.expect("is in scope")
|
|
.expect("is i31"),
|
|
expected,
|
|
);
|
|
}
|
|
for i in dst_index + len..10 {
|
|
let actual = dst_table.get(&mut store, i).unwrap();
|
|
assert!(actual.as_any().expect("is anyref").is_none());
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|