1 use wasmtime::*;
2
3 #[test]
get_none()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]
fill_wrong()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]
copy_wrong()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)]
null_elem_segment_works_with_imported_table() -> Result<()>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]
i31ref_table_new() -> Result<()>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]
i31ref_table_get() -> Result<()>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]
i31ref_table_set() -> Result<()>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]
i31ref_table_grow() -> Result<()>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]
i31ref_table_fill() -> Result<()>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]
i31ref_table_copy() -> Result<()>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]
host_table_keep_type_registration() -> Result<()>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]
gc_store_with_table_initializers() -> Result<()>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