1 use wasmtime::*; 2 3 #[test] 4 fn get_none() { 5 let mut store = Store::<()>::default(); 6 let ty = TableType::new(RefType::FUNCREF, 1, None); 7 let table = Table::new(&mut store, ty, Ref::Func(None)).unwrap(); 8 match table.get(&mut store, 0) { 9 Some(Ref::Func(None)) => {} 10 _ => panic!(), 11 } 12 assert!(table.get(&mut store, 1).is_none()); 13 } 14 15 #[test] 16 fn fill_wrong() { 17 let mut store = Store::<()>::default(); 18 let ty = TableType::new(RefType::FUNCREF, 1, None); 19 let table = Table::new(&mut store, ty, Ref::Func(None)).unwrap(); 20 assert_eq!( 21 table 22 .fill(&mut store, 0, Ref::Extern(None), 1) 23 .map_err(|e| e.to_string()) 24 .unwrap_err(), 25 "type mismatch: value does not match table element type" 26 ); 27 28 let ty = TableType::new(RefType::EXTERNREF, 1, None); 29 let table = Table::new(&mut store, ty, Ref::Extern(None)).unwrap(); 30 assert_eq!( 31 table 32 .fill(&mut store, 0, Ref::Func(None), 1) 33 .map_err(|e| e.to_string()) 34 .unwrap_err(), 35 "type mismatch: value does not match table element type" 36 ); 37 } 38 39 #[test] 40 fn copy_wrong() { 41 let mut store = Store::<()>::default(); 42 let ty = TableType::new(RefType::FUNCREF, 1, None); 43 let table1 = Table::new(&mut store, ty, Ref::Func(None)).unwrap(); 44 let ty = TableType::new(RefType::EXTERNREF, 1, None); 45 let table2 = Table::new(&mut store, ty, Ref::Extern(None)).unwrap(); 46 assert_eq!( 47 Table::copy(&mut store, &table1, 0, &table2, 0, 1) 48 .map_err(|e| e.to_string()) 49 .unwrap_err(), 50 "type mismatch: source table's element type does not match destination table's element type" 51 ); 52 } 53 54 #[test] 55 #[cfg_attr(miri, ignore)] 56 fn null_elem_segment_works_with_imported_table() -> Result<()> { 57 let mut store = Store::<()>::default(); 58 let ty = TableType::new(RefType::FUNCREF, 1, None); 59 let table = Table::new(&mut store, ty, Ref::Func(None))?; 60 let module = Module::new( 61 store.engine(), 62 r#" 63 (module 64 (import "" "" (table (;0;) 1 funcref)) 65 (func 66 i32.const 0 67 table.get 0 68 drop 69 ) 70 (start 0) 71 (elem (;0;) (i32.const 0) funcref (ref.null func)) 72 ) 73 "#, 74 )?; 75 Instance::new(&mut store, &module, &[table.into()])?; 76 Ok(()) 77 } 78 79 #[test] 80 fn i31ref_table_new() -> Result<()> { 81 let mut config = Config::new(); 82 config.wasm_function_references(true); 83 config.wasm_gc(true); 84 85 let engine = Engine::new(&config)?; 86 let mut store = Store::new(&engine, ()); 87 88 for (elem_ty, inits) in [ 89 ( 90 RefType::I31REF, 91 vec![ 92 Ref::Any(None), 93 AnyRef::from_i31(&mut store, I31::default()).into(), 94 ], 95 ), 96 ( 97 RefType::new(false, HeapType::I31), 98 vec![AnyRef::from_i31(&mut store, I31::default()).into()], 99 ), 100 ] { 101 let table_ty = TableType::new(elem_ty, 10, None); 102 for init in inits { 103 Table::new(&mut store, table_ty.clone(), init)?; 104 } 105 } 106 107 Ok(()) 108 } 109 110 #[test] 111 fn i31ref_table_get() -> Result<()> { 112 let mut config = Config::new(); 113 config.wasm_function_references(true); 114 config.wasm_gc(true); 115 116 let engine = Engine::new(&config)?; 117 let mut store = Store::new(&engine, ()); 118 119 for (elem_ty, inits) in [ 120 ( 121 RefType::I31REF, 122 vec![ 123 Ref::Any(None), 124 AnyRef::from_i31(&mut store, I31::default()).into(), 125 ], 126 ), 127 ( 128 RefType::new(false, HeapType::I31), 129 vec![AnyRef::from_i31(&mut store, I31::default()).into()], 130 ), 131 ] { 132 let table_ty = TableType::new(elem_ty, 10, None); 133 for init in inits { 134 let table = Table::new(&mut store, table_ty.clone(), init.clone())?; 135 for i in 0..10 { 136 let val = table.get(&mut store, i).unwrap(); 137 assert_eq!(init.is_null(), val.is_null()); 138 assert_eq!( 139 init.as_any() 140 .expect("is anyref") 141 .map(|a| a.as_i31(&store).expect("is in scope")), 142 val.as_any() 143 .expect("is anyref") 144 .map(|a| a.as_i31(&store).expect("is in scope")) 145 ) 146 } 147 } 148 } 149 150 Ok(()) 151 } 152 153 #[test] 154 fn i31ref_table_set() -> Result<()> { 155 let mut config = Config::new(); 156 config.wasm_function_references(true); 157 config.wasm_gc(true); 158 159 let engine = Engine::new(&config)?; 160 let mut store = Store::new(&engine, ()); 161 162 for (elem_ty, inits, vals) in [ 163 ( 164 RefType::I31REF, 165 vec![ 166 Ref::Any(None), 167 AnyRef::from_i31(&mut store, I31::default()).into(), 168 ], 169 vec![ 170 Ref::Any(None), 171 AnyRef::from_i31(&mut store, I31::wrapping_u32(42)).into(), 172 ], 173 ), 174 ( 175 RefType::new(false, HeapType::I31), 176 vec![AnyRef::from_i31(&mut store, I31::default()).into()], 177 vec![AnyRef::from_i31(&mut store, I31::wrapping_u32(42)).into()], 178 ), 179 ] { 180 let table_ty = TableType::new(elem_ty, 10, None); 181 for init in inits { 182 for expected in vals.clone() { 183 let table = Table::new(&mut store, table_ty.clone(), init.clone())?; 184 for i in 0..10 { 185 table.set(&mut store, i, expected.clone())?; 186 let actual = table.get(&mut store, i).unwrap(); 187 assert_eq!(expected.is_null(), actual.is_null()); 188 assert_eq!( 189 expected 190 .as_any() 191 .expect("is anyref") 192 .map(|a| a.as_i31(&store).expect("is in scope")), 193 actual 194 .as_any() 195 .expect("is anyref") 196 .map(|a| a.as_i31(&store).expect("is in scope")) 197 ) 198 } 199 } 200 } 201 } 202 203 Ok(()) 204 } 205 206 #[test] 207 fn i31ref_table_grow() -> Result<()> { 208 let mut config = Config::new(); 209 config.wasm_function_references(true); 210 config.wasm_gc(true); 211 212 let engine = Engine::new(&config)?; 213 let mut store = Store::new(&engine, ()); 214 215 for (elem_ty, init) in [ 216 (RefType::I31REF, Ref::Any(None)), 217 ( 218 RefType::new(false, HeapType::I31), 219 AnyRef::from_i31(&mut store, I31::default()).into(), 220 ), 221 ] { 222 let table_ty = TableType::new(elem_ty, 10, None); 223 let table = Table::new(&mut store, table_ty, init)?; 224 assert_eq!(table.size(&store), 10); 225 for i in 10..20 { 226 assert!(table.get(&mut store, i).is_none()); 227 } 228 let expected = I31::wrapping_u32(42); 229 let grow_val = AnyRef::from_i31(&mut store, expected); 230 table.grow(&mut store, 10, grow_val.into())?; 231 for i in 10..20 { 232 let actual = table.get(&mut store, i).unwrap(); 233 assert_eq!( 234 actual 235 .as_any() 236 .expect("is anyref") 237 .expect("is non null") 238 .as_i31(&store) 239 .expect("is in scope") 240 .expect("is i31"), 241 expected, 242 ); 243 } 244 assert!(table.get(&mut store, 20).is_none()); 245 } 246 247 Ok(()) 248 } 249 250 #[test] 251 fn i31ref_table_fill() -> Result<()> { 252 let mut config = Config::new(); 253 config.wasm_function_references(true); 254 config.wasm_gc(true); 255 256 let engine = Engine::new(&config)?; 257 let mut store = Store::new(&engine, ()); 258 259 let table_ty = TableType::new(RefType::I31REF, 10, None); 260 let table = Table::new(&mut store, table_ty, Ref::Any(None))?; 261 262 let expected = I31::wrapping_u32(42); 263 let fill_val = AnyRef::from_i31(&mut store, expected); 264 let dst = 3; 265 let len = 4; 266 table.fill(&mut store, dst, fill_val.into(), len)?; 267 268 for i in 0..dst { 269 let actual = table.get(&mut store, i).unwrap(); 270 assert!(actual.as_any().expect("is anyref").is_none()); 271 } 272 for i in dst..dst + len { 273 let actual = table.get(&mut store, i).unwrap(); 274 assert_eq!( 275 actual 276 .as_any() 277 .expect("is anyref") 278 .expect("is non null") 279 .as_i31(&store) 280 .expect("is in scope") 281 .expect("is i31"), 282 expected, 283 ); 284 } 285 for i in dst + len..10 { 286 let actual = table.get(&mut store, i).unwrap(); 287 assert!(actual.as_any().expect("is anyref").is_none()); 288 } 289 290 Ok(()) 291 } 292 293 #[test] 294 fn i31ref_table_copy() -> Result<()> { 295 let mut config = Config::new(); 296 config.wasm_function_references(true); 297 config.wasm_gc(true); 298 299 let engine = Engine::new(&config)?; 300 let mut store = Store::new(&engine, ()); 301 302 let table_ty = TableType::new(RefType::I31REF, 10, None); 303 let dst_table = Table::new(&mut store, table_ty.clone(), Ref::Any(None))?; 304 305 let expected = I31::wrapping_u32(42); 306 let init_val = AnyRef::from_i31(&mut store, expected); 307 let src_table = Table::new(&mut store, table_ty, init_val.into())?; 308 309 let dst_index = 1; 310 let src_index = 2; 311 let len = 3; 312 Table::copy( 313 &mut store, &dst_table, dst_index, &src_table, src_index, len, 314 )?; 315 316 for i in 0..dst_index { 317 let actual = dst_table.get(&mut store, i).unwrap(); 318 assert!(actual.as_any().expect("is anyref").is_none()); 319 } 320 for i in dst_index..dst_index + len { 321 let actual = dst_table.get(&mut store, i).unwrap(); 322 assert_eq!( 323 actual 324 .as_any() 325 .expect("is anyref") 326 .expect("is non null") 327 .as_i31(&store) 328 .expect("is in scope") 329 .expect("is i31"), 330 expected, 331 ); 332 } 333 for i in dst_index + len..10 { 334 let actual = dst_table.get(&mut store, i).unwrap(); 335 assert!(actual.as_any().expect("is anyref").is_none()); 336 } 337 338 Ok(()) 339 } 340 341 #[test] 342 fn host_table_keep_type_registration() -> Result<()> { 343 let engine = Engine::default(); 344 let mut store = Store::new(&engine, ()); 345 346 let ty = FuncType::new(&engine, [], []); 347 348 let t = Table::new( 349 &mut store, 350 TableType::new(RefType::new(true, HeapType::ConcreteFunc(ty)), 1, None), 351 Ref::Func(None), 352 )?; 353 354 { 355 let _ty2 = FuncType::new(&engine, [ValType::I32], [ValType::I32]); 356 let ty = t.ty(&store); 357 let fty = ty.element().heap_type().unwrap_concrete_func(); 358 assert!(fty.params().len() == 0); 359 assert!(fty.results().len() == 0); 360 } 361 362 let ty = t.ty(&store); 363 let fty = ty.element().heap_type().unwrap_concrete_func(); 364 assert!(fty.params().len() == 0); 365 assert!(fty.results().len() == 0); 366 367 Ok(()) 368 } 369 370 #[test] 371 fn gc_store_with_table_initializers() -> Result<()> { 372 let mut config = Config::new(); 373 config.wasm_gc(true); 374 config.wasm_function_references(true); 375 let engine = Engine::new(&config)?; 376 377 let test = |wat: &str| -> Result<()> { 378 let module = Module::new(&engine, wat)?; 379 Instance::new(&mut Store::new(&engine, ()), &module, &[])?; 380 Ok(()) 381 }; 382 383 test("(module (table 1 i31ref))")?; 384 test("(module (table 1 i31ref (ref.i31 (i32.const 1))))")?; 385 test("(module (table 1 i31ref (ref.null i31)))")?; 386 387 Ok(()) 388 } 389