Upgrade wasm-tools crates, namely the component model (#4715)

* Upgrade wasm-tools crates, namely the component model

This commit pulls in the latest versions of all of the `wasm-tools`
family of crates. There were two major changes that happened in
`wasm-tools` in the meantime:

* bytecodealliance/wasm-tools#697 - this commit introduced a new API for
  more efficiently reading binary operators from a wasm binary. The old
  `Operator`-based reading was left in place, however, and continues to
  be what Wasmtime uses. I hope to update Wasmtime in a future PR to use
  this new API, but for now the biggest change is...

* bytecodealliance/wasm-tools#703 - this commit was a major update to
  the component model AST. This commit almost entirely deals with the
  fallout of this change.

The changes made to the component model were:

1. The `unit` type no longer exists. This was generally a simple change
   where the `Unit` case in a few different locations were all removed.
2. The `expected` type was renamed to `result`. This similarly was
   relatively lightweight and mostly just a renaming on the surface. I
   took this opportunity to rename `val::Result` to `val::ResultVal` and
   `types::Result` to `types::ResultType` to avoid clashing with the
   standard library types. The `Option`-based types were handled with
   this as well.
3. The payload type of `variant` and `result` types are now optional.
   This affected many locations that calculate flat type
   representations, ABI information, etc. The `#[derive(ComponentType)]`
   macro now specifically handles Rust-defined `enum` types which have
   no payload to the equivalent in the component model.
4. Functions can now return multiple parameters. This changed the
   signature of invoking component functions because the return value is
   now bound by `ComponentNamedList` (renamed from `ComponentParams`).
   This had a large effect in the tests, fuzz test case generation, etc.
5. Function types with 2-or-more parameters/results must uniquely name
   all parameters/results. This mostly affected the text format used
   throughout the tests.

I haven't added specifically new tests for multi-return but I changed a
number of tests to use it. Additionally I've updated the fuzzers to all
exercise multi-return as well so I think we should get some good
coverage with that.

* Update version numbers

* Use crates.io
This commit is contained in:
Alex Crichton
2022-08-17 11:17:34 -05:00
committed by GitHub
parent 3629bbbd55
commit 57dca934ad
46 changed files with 1425 additions and 1133 deletions

View File

@@ -8,6 +8,7 @@ use wasmtime::Store;
fn primitives() -> Result<()> {
let engine = super::engine();
let mut store = Store::new(&engine, ());
let mut output = [Val::Bool(false)];
for (input, ty, param) in [
(Val::Bool(true), "bool", Param(Type::U8, Some(0))),
@@ -34,9 +35,9 @@ fn primitives() -> Result<()> {
let component = Component::new(&engine, make_echo_component_with_params(ty, &[param]))?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_func(&mut store, "echo").unwrap();
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
}
// Sad path: type mismatch
@@ -48,7 +49,7 @@ fn primitives() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_func(&mut store, "echo").unwrap();
let err = func
.call_and_post_return(&mut store, &[Val::U64(42)])
.call_and_post_return(&mut store, &[Val::U64(42)], &mut output)
.unwrap_err();
assert!(err.to_string().contains("type mismatch"), "{err}");
@@ -62,6 +63,7 @@ fn primitives() -> Result<()> {
Val::Float64(3.14159265_f64.to_bits()),
Val::Float64(3.14159265_f64.to_bits()),
],
&mut output,
)
.unwrap_err();
@@ -72,13 +74,22 @@ fn primitives() -> Result<()> {
// Sad path: arity mismatch (too few)
let err = func.call_and_post_return(&mut store, &[]).unwrap_err();
let err = func
.call_and_post_return(&mut store, &[], &mut output)
.unwrap_err();
assert!(
err.to_string().contains("expected 1 argument(s), got 0"),
"{err}"
);
let err = func
.call_and_post_return(&mut store, &output, &mut [])
.unwrap_err();
assert!(
err.to_string().contains("expected 1 results(s), got 0"),
"{err}"
);
Ok(())
}
@@ -91,9 +102,9 @@ fn strings() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_func(&mut store, "echo").unwrap();
let input = Val::String(Box::from("hello, component!"));
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
assert_eq!(input, output);
let mut output = [Val::Bool(false)];
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output[0]);
Ok(())
}
@@ -112,9 +123,10 @@ fn lists() -> Result<()> {
Val::U32(79023439),
Val::U32(2084037802),
]))?;
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
let mut output = [Val::Bool(false)];
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
// Sad path: type mismatch
@@ -163,9 +175,10 @@ fn records() -> Result<()> {
.new_val([("D", Val::Bool(false)), ("E", Val::U32(2084037802))])?,
),
])?;
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
let mut output = [Val::Bool(false)];
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
// Sad path: type mismatch
@@ -198,7 +211,7 @@ fn records() -> Result<()> {
.unwrap_record()
.new_val([("D", Val::Bool(false)), ("E", Val::U32(2084037802))])?,
),
("F", Val::Unit),
("F", Val::Bool(true)),
])
.unwrap_err();
@@ -246,54 +259,62 @@ fn variants() -> Result<()> {
let ty = &func.params(&store)[0];
let input = ty
.unwrap_variant()
.new_val("B", Val::Float64(3.14159265_f64.to_bits()))?;
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
.new_val("B", Some(Val::Float64(3.14159265_f64.to_bits())))?;
let mut output = [Val::Bool(false)];
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
// Do it again, this time using case "C"
let component = Component::new(
&engine,
dbg!(make_echo_component_with_params(
make_echo_component_with_params(
r#"(variant (case "A" u32) (case "B" float64) (case "C" (record (field "D" bool) (field "E" u32))))"#,
&[
Param(Type::U8, Some(0)),
Param(Type::I64, Some(8)),
Param(Type::I32, Some(12)),
],
)),
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_func(&mut store, "echo").unwrap();
let ty = &func.params(&store)[0];
let c_type = &ty.unwrap_variant().cases().nth(2).unwrap().ty;
let c_type = &ty.unwrap_variant().cases().nth(2).unwrap().ty.unwrap();
let input = ty.unwrap_variant().new_val(
"C",
c_type
.unwrap_record()
.new_val([("D", Val::Bool(true)), ("E", Val::U32(314159265))])?,
Some(
c_type
.unwrap_record()
.new_val([("D", Val::Bool(true)), ("E", Val::U32(314159265))])?,
),
)?;
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
// Sad path: type mismatch
let err = ty
.unwrap_variant()
.new_val("B", Val::U64(314159265))
.new_val("B", Some(Val::U64(314159265)))
.unwrap_err();
assert!(err.to_string().contains("type mismatch"), "{err}");
let err = ty.unwrap_variant().new_val("B", None).unwrap_err();
assert!(
err.to_string().contains("expected a payload for case `B`"),
"{err}"
);
// Sad path: unknown case
let err = ty
.unwrap_variant()
.new_val("D", Val::U64(314159265))
.new_val("D", Some(Val::U64(314159265)))
.unwrap_err();
assert!(err.to_string().contains("unknown variant case"), "{err}");
let err = ty.unwrap_variant().new_val("D", None).unwrap_err();
assert!(err.to_string().contains("unknown variant case"), "{err}");
// Make sure we lift variants which have cases of different sizes with the correct alignment
@@ -323,13 +344,15 @@ fn variants() -> Result<()> {
let input = ty.unwrap_record().new_val([
(
"A",
a_type.unwrap_variant().new_val("A", Val::U32(314159265))?,
a_type
.unwrap_variant()
.new_val("A", Some(Val::U32(314159265)))?,
),
("B", Val::U32(628318530)),
])?;
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
Ok(())
}
@@ -350,9 +373,10 @@ fn flags() -> Result<()> {
let func = instance.get_func(&mut store, "echo").unwrap();
let ty = &func.params(&store)[0];
let input = ty.unwrap_flags().new_val(&["B", "D"])?;
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
let mut output = [Val::Bool(false)];
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
// Sad path: unknown flags
@@ -391,11 +415,10 @@ fn everything() -> Result<()> {
(field "U" float64)
(field "V" string)
(field "W" char)
(field "X" unit)
(field "Y" (tuple u32 u32))
(field "Z" (union u32 float64))
(field "AA" (option u32))
(field "BB" (expected string string))
(field "BB" (result string (error string)))
)"#,
&[
Param(Type::I32, Some(0)),
@@ -436,7 +459,7 @@ fn everything() -> Result<()> {
.map(|field| field.ty)
.collect::<Box<[component::Type]>>();
let (b_type, c_type, f_type, j_type, y_type, z_type, aa_type, bb_type) = (
&types[1], &types[2], &types[3], &types[4], &types[14], &types[15], &types[16], &types[17],
&types[1], &types[2], &types[3], &types[4], &types[13], &types[14], &types[15], &types[16],
);
let f_element_type = &f_type.unwrap_list().ty();
let input = ty.unwrap_record().new_val([
@@ -458,7 +481,7 @@ fn everything() -> Result<()> {
"J",
j_type
.unwrap_variant()
.new_val("L", Val::Float64(3.14159265_f64.to_bits()))?,
.new_val("L", Some(Val::Float64(3.14159265_f64.to_bits())))?,
),
("P", Val::S8(42)),
("Q", Val::S16(4242)),
@@ -468,7 +491,6 @@ fn everything() -> Result<()> {
("U", Val::Float64(3.14159265_f64.to_bits())),
("V", Val::String(Box::from("wow, nice types"))),
("W", Val::Char('🦀')),
("X", Val::Unit),
(
"Y",
y_type
@@ -488,13 +510,14 @@ fn everything() -> Result<()> {
(
"BB",
bb_type
.unwrap_expected()
.new_val(Ok(Val::String(Box::from("no problem"))))?,
.unwrap_result()
.new_val(Ok(Some(Val::String(Box::from("no problem")))))?,
),
])?;
let output = func.call_and_post_return(&mut store, &[input.clone()])?;
let mut output = [Val::Bool(false)];
func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
assert_eq!(input, output);
assert_eq!(input, output[0]);
Ok(())
}

View File

@@ -66,10 +66,10 @@ fn typecheck() -> Result<()> {
(func (export "take-string") (param string)
(canon lift (core func $i "take-string") (memory $i "memory") (realloc (func $i "realloc")))
)
(func (export "take-two-args") (param s32) (param (list u8))
(func (export "take-two-args") (param "a" s32) (param "b" (list u8))
(canon lift (core func $i "two-args") (memory $i "memory") (realloc (func $i "realloc")))
)
(func (export "ret-tuple") (result (tuple u8 s8))
(func (export "ret-tuple") (result "a" u8) (result "b" s8)
(canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
)
(func (export "ret-tuple1") (result (tuple u32))
@@ -96,29 +96,34 @@ fn typecheck() -> Result<()> {
let ret_tuple1 = instance.get_func(&mut store, "ret-tuple1").unwrap();
let ret_string = instance.get_func(&mut store, "ret-string").unwrap();
let ret_list_u8 = instance.get_func(&mut store, "ret-list-u8").unwrap();
assert!(thunk.typed::<(), u32, _>(&store).is_err());
assert!(thunk.typed::<(), (u32,), _>(&store).is_err());
assert!(thunk.typed::<(u32,), (), _>(&store).is_err());
assert!(thunk.typed::<(), (), _>(&store).is_ok());
assert!(tuple_thunk.typed::<(), (), _>(&store).is_err());
assert!(tuple_thunk.typed::<((),), (), _>(&store).is_ok());
assert!(tuple_thunk.typed::<((),), (), _>(&store).is_err());
assert!(tuple_thunk.typed::<((),), ((),), _>(&store).is_ok());
assert!(take_string.typed::<(), (), _>(&store).is_err());
assert!(take_string.typed::<(String,), (), _>(&store).is_ok());
assert!(take_string.typed::<(&str,), (), _>(&store).is_ok());
assert!(take_string.typed::<(&[u8],), (), _>(&store).is_err());
assert!(take_two_args.typed::<(), (), _>(&store).is_err());
assert!(take_two_args.typed::<(i32, &[u8]), u32, _>(&store).is_err());
assert!(take_two_args
.typed::<(i32, &[u8]), (u32,), _>(&store)
.is_err());
assert!(take_two_args.typed::<(u32, &[u8]), (), _>(&store).is_err());
assert!(take_two_args.typed::<(i32, &[u8]), (), _>(&store).is_ok());
assert!(ret_tuple.typed::<(), (), _>(&store).is_err());
assert!(ret_tuple.typed::<(), (u8,), _>(&store).is_err());
assert!(ret_tuple.typed::<(), (u8, i8), _>(&store).is_ok());
assert!(ret_tuple1.typed::<(), (u32,), _>(&store).is_ok());
assert!(ret_tuple1.typed::<(), u32, _>(&store).is_err());
assert!(ret_tuple1.typed::<(), ((u32,),), _>(&store).is_ok());
assert!(ret_tuple1.typed::<(), (u32,), _>(&store).is_err());
assert!(ret_string.typed::<(), (), _>(&store).is_err());
assert!(ret_string.typed::<(), WasmStr, _>(&store).is_ok());
assert!(ret_list_u8.typed::<(), WasmList<u16>, _>(&store).is_err());
assert!(ret_list_u8.typed::<(), WasmList<i8>, _>(&store).is_err());
assert!(ret_list_u8.typed::<(), WasmList<u8>, _>(&store).is_ok());
assert!(ret_string.typed::<(), (WasmStr,), _>(&store).is_ok());
assert!(ret_list_u8
.typed::<(), (WasmList<u16>,), _>(&store)
.is_err());
assert!(ret_list_u8.typed::<(), (WasmList<i8>,), _>(&store).is_err());
assert!(ret_list_u8.typed::<(), (WasmList<u8>,), _>(&store).is_ok());
Ok(())
}
@@ -262,140 +267,140 @@ fn integers() -> Result<()> {
// Zero can be returned as any integer
assert_eq!(
instance
.get_typed_func::<(), u8, _>(&mut store, "ret-u8")?
.get_typed_func::<(), (u8,), _>(&mut store, "ret-u8")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
assert_eq!(
instance
.get_typed_func::<(), i8, _>(&mut store, "ret-s8")?
.get_typed_func::<(), (i8,), _>(&mut store, "ret-s8")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
assert_eq!(
instance
.get_typed_func::<(), u16, _>(&mut store, "ret-u16")?
.get_typed_func::<(), (u16,), _>(&mut store, "ret-u16")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
assert_eq!(
instance
.get_typed_func::<(), i16, _>(&mut store, "ret-s16")?
.get_typed_func::<(), (i16,), _>(&mut store, "ret-s16")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
assert_eq!(
instance
.get_typed_func::<(), u32, _>(&mut store, "ret-u32")?
.get_typed_func::<(), (u32,), _>(&mut store, "ret-u32")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
assert_eq!(
instance
.get_typed_func::<(), i32, _>(&mut store, "ret-s32")?
.get_typed_func::<(), (i32,), _>(&mut store, "ret-s32")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
assert_eq!(
instance
.get_typed_func::<(), u64, _>(&mut store, "ret-u64")?
.get_typed_func::<(), (u64,), _>(&mut store, "ret-u64")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
assert_eq!(
instance
.get_typed_func::<(), i64, _>(&mut store, "ret-s64")?
.get_typed_func::<(), (i64,), _>(&mut store, "ret-s64")?
.call_and_post_return(&mut store, ())?,
0
(0,)
);
// Returning -1 should reinterpret the bytes as defined by each type.
assert_eq!(
instance
.get_typed_func::<(), u8, _>(&mut store, "retm1-u8")?
.get_typed_func::<(), (u8,), _>(&mut store, "retm1-u8")?
.call_and_post_return(&mut store, ())?,
0xff
(0xff,)
);
assert_eq!(
instance
.get_typed_func::<(), i8, _>(&mut store, "retm1-s8")?
.get_typed_func::<(), (i8,), _>(&mut store, "retm1-s8")?
.call_and_post_return(&mut store, ())?,
-1
(-1,)
);
assert_eq!(
instance
.get_typed_func::<(), u16, _>(&mut store, "retm1-u16")?
.get_typed_func::<(), (u16,), _>(&mut store, "retm1-u16")?
.call_and_post_return(&mut store, ())?,
0xffff
(0xffff,)
);
assert_eq!(
instance
.get_typed_func::<(), i16, _>(&mut store, "retm1-s16")?
.get_typed_func::<(), (i16,), _>(&mut store, "retm1-s16")?
.call_and_post_return(&mut store, ())?,
-1
(-1,)
);
assert_eq!(
instance
.get_typed_func::<(), u32, _>(&mut store, "retm1-u32")?
.get_typed_func::<(), (u32,), _>(&mut store, "retm1-u32")?
.call_and_post_return(&mut store, ())?,
0xffffffff
(0xffffffff,)
);
assert_eq!(
instance
.get_typed_func::<(), i32, _>(&mut store, "retm1-s32")?
.get_typed_func::<(), (i32,), _>(&mut store, "retm1-s32")?
.call_and_post_return(&mut store, ())?,
-1
(-1,)
);
assert_eq!(
instance
.get_typed_func::<(), u64, _>(&mut store, "retm1-u64")?
.get_typed_func::<(), (u64,), _>(&mut store, "retm1-u64")?
.call_and_post_return(&mut store, ())?,
0xffffffff_ffffffff
(0xffffffff_ffffffff,)
);
assert_eq!(
instance
.get_typed_func::<(), i64, _>(&mut store, "retm1-s64")?
.get_typed_func::<(), (i64,), _>(&mut store, "retm1-s64")?
.call_and_post_return(&mut store, ())?,
-1
(-1,)
);
// Returning 100000 should chop off bytes as necessary
let ret: u32 = 100000;
assert_eq!(
instance
.get_typed_func::<(), u8, _>(&mut store, "retbig-u8")?
.get_typed_func::<(), (u8,), _>(&mut store, "retbig-u8")?
.call_and_post_return(&mut store, ())?,
ret as u8,
(ret as u8,),
);
assert_eq!(
instance
.get_typed_func::<(), i8, _>(&mut store, "retbig-s8")?
.get_typed_func::<(), (i8,), _>(&mut store, "retbig-s8")?
.call_and_post_return(&mut store, ())?,
ret as i8,
(ret as i8,),
);
assert_eq!(
instance
.get_typed_func::<(), u16, _>(&mut store, "retbig-u16")?
.get_typed_func::<(), (u16,), _>(&mut store, "retbig-u16")?
.call_and_post_return(&mut store, ())?,
ret as u16,
(ret as u16,),
);
assert_eq!(
instance
.get_typed_func::<(), i16, _>(&mut store, "retbig-s16")?
.get_typed_func::<(), (i16,), _>(&mut store, "retbig-s16")?
.call_and_post_return(&mut store, ())?,
ret as i16,
(ret as i16,),
);
assert_eq!(
instance
.get_typed_func::<(), u32, _>(&mut store, "retbig-u32")?
.get_typed_func::<(), (u32,), _>(&mut store, "retbig-u32")?
.call_and_post_return(&mut store, ())?,
ret,
(ret,),
);
assert_eq!(
instance
.get_typed_func::<(), i32, _>(&mut store, "retbig-s32")?
.get_typed_func::<(), (i32,), _>(&mut store, "retbig-s32")?
.call_and_post_return(&mut store, ())?,
ret as i32,
(ret as i32,),
);
Ok(())
@@ -486,23 +491,24 @@ fn floats() -> Result<()> {
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let f32_to_u32 = instance.get_typed_func::<(f32,), u32, _>(&mut store, "f32-to-u32")?;
let f64_to_u64 = instance.get_typed_func::<(f64,), u64, _>(&mut store, "f64-to-u64")?;
let u32_to_f32 = instance.get_typed_func::<(u32,), f32, _>(&mut store, "u32-to-f32")?;
let u64_to_f64 = instance.get_typed_func::<(u64,), f64, _>(&mut store, "u64-to-f64")?;
let f32_to_u32 = instance.get_typed_func::<(f32,), (u32,), _>(&mut store, "f32-to-u32")?;
let f64_to_u64 = instance.get_typed_func::<(f64,), (u64,), _>(&mut store, "f64-to-u64")?;
let u32_to_f32 = instance.get_typed_func::<(u32,), (f32,), _>(&mut store, "u32-to-f32")?;
let u64_to_f64 = instance.get_typed_func::<(u64,), (f64,), _>(&mut store, "u64-to-f64")?;
assert_eq!(f32_to_u32.call(&mut store, (1.0,))?, 1.0f32.to_bits());
assert_eq!(f32_to_u32.call(&mut store, (1.0,))?, (1.0f32.to_bits(),));
f32_to_u32.post_return(&mut store)?;
assert_eq!(f64_to_u64.call(&mut store, (2.0,))?, 2.0f64.to_bits());
assert_eq!(f64_to_u64.call(&mut store, (2.0,))?, (2.0f64.to_bits(),));
f64_to_u64.post_return(&mut store)?;
assert_eq!(u32_to_f32.call(&mut store, (3.0f32.to_bits(),))?, 3.0);
assert_eq!(u32_to_f32.call(&mut store, (3.0f32.to_bits(),))?, (3.0,));
u32_to_f32.post_return(&mut store)?;
assert_eq!(u64_to_f64.call(&mut store, (4.0f64.to_bits(),))?, 4.0);
assert_eq!(u64_to_f64.call(&mut store, (4.0f64.to_bits(),))?, (4.0,));
u64_to_f64.post_return(&mut store)?;
assert_eq!(
u32_to_f32
.call(&mut store, (CANON_32BIT_NAN | 1,))?
.0
.to_bits(),
CANON_32BIT_NAN
);
@@ -510,19 +516,20 @@ fn floats() -> Result<()> {
assert_eq!(
u64_to_f64
.call(&mut store, (CANON_64BIT_NAN | 1,))?
.0
.to_bits(),
CANON_64BIT_NAN
CANON_64BIT_NAN,
);
u64_to_f64.post_return(&mut store)?;
assert_eq!(
f32_to_u32.call(&mut store, (f32::from_bits(CANON_32BIT_NAN | 1),))?,
CANON_32BIT_NAN
(CANON_32BIT_NAN,)
);
f32_to_u32.post_return(&mut store)?;
assert_eq!(
f64_to_u64.call(&mut store, (f64::from_bits(CANON_64BIT_NAN | 1),))?,
CANON_64BIT_NAN
(CANON_64BIT_NAN,)
);
f64_to_u64.post_return(&mut store)?;
@@ -551,18 +558,18 @@ fn bools() -> Result<()> {
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let u32_to_bool = instance.get_typed_func::<(u32,), bool, _>(&mut store, "u32-to-bool")?;
let bool_to_u32 = instance.get_typed_func::<(bool,), u32, _>(&mut store, "bool-to-u32")?;
let u32_to_bool = instance.get_typed_func::<(u32,), (bool,), _>(&mut store, "u32-to-bool")?;
let bool_to_u32 = instance.get_typed_func::<(bool,), (u32,), _>(&mut store, "bool-to-u32")?;
assert_eq!(bool_to_u32.call(&mut store, (false,))?, 0);
assert_eq!(bool_to_u32.call(&mut store, (false,))?, (0,));
bool_to_u32.post_return(&mut store)?;
assert_eq!(bool_to_u32.call(&mut store, (true,))?, 1);
assert_eq!(bool_to_u32.call(&mut store, (true,))?, (1,));
bool_to_u32.post_return(&mut store)?;
assert_eq!(u32_to_bool.call(&mut store, (0,))?, false);
assert_eq!(u32_to_bool.call(&mut store, (0,))?, (false,));
u32_to_bool.post_return(&mut store)?;
assert_eq!(u32_to_bool.call(&mut store, (1,))?, true);
assert_eq!(u32_to_bool.call(&mut store, (1,))?, (true,));
u32_to_bool.post_return(&mut store)?;
assert_eq!(u32_to_bool.call(&mut store, (2,))?, true);
assert_eq!(u32_to_bool.call(&mut store, (2,))?, (true,));
u32_to_bool.post_return(&mut store)?;
Ok(())
@@ -590,13 +597,13 @@ fn chars() -> Result<()> {
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let u32_to_char = instance.get_typed_func::<(u32,), char, _>(&mut store, "u32-to-char")?;
let char_to_u32 = instance.get_typed_func::<(char,), u32, _>(&mut store, "char-to-u32")?;
let u32_to_char = instance.get_typed_func::<(u32,), (char,), _>(&mut store, "u32-to-char")?;
let char_to_u32 = instance.get_typed_func::<(char,), (u32,), _>(&mut store, "char-to-u32")?;
let mut roundtrip = |x: char| -> Result<()> {
assert_eq!(char_to_u32.call(&mut store, (x,))?, x as u32);
assert_eq!(char_to_u32.call(&mut store, (x,))?, (x as u32,));
char_to_u32.post_return(&mut store)?;
assert_eq!(u32_to_char.call(&mut store, (x as u32,))?, x);
assert_eq!(u32_to_char.call(&mut store, (x as u32,))?, (x,));
u32_to_char.post_return(&mut store)?;
Ok(())
};
@@ -610,7 +617,7 @@ fn chars() -> Result<()> {
let u32_to_char = |store: &mut Store<()>| {
Linker::new(&engine)
.instantiate(&mut *store, &component)?
.get_typed_func::<(u32,), char, _>(&mut *store, "u32-to-char")
.get_typed_func::<(u32,), (char,), _>(&mut *store, "u32-to-char")
};
let err = u32_to_char(&mut store)?
.call(&mut store, (0xd800,))
@@ -656,7 +663,7 @@ fn tuple_result() -> Result<()> {
(type $result (tuple s8 u16 float32 float64))
(func (export "tuple")
(param s8) (param u16) (param float32) (param float64) (result $result)
(param "a" s8) (param "b" u16) (param "c" float32) (param "d" float64) (result $result)
(canon lift (core func $i "foo") (memory $i "memory"))
)
(func (export "invalid") (result $result)
@@ -672,12 +679,12 @@ fn tuple_result() -> Result<()> {
let input = (-1, 100, 3.0, 100.0);
let output = instance
.get_typed_func::<(i8, u16, f32, f64), (i8, u16, f32, f64), _>(&mut store, "tuple")?
.get_typed_func::<(i8, u16, f32, f64), ((i8, u16, f32, f64),), _>(&mut store, "tuple")?
.call_and_post_return(&mut store, input)?;
assert_eq!(input, output);
assert_eq!((input,), output);
let invalid_func =
instance.get_typed_func::<(), (i8, u16, f32, f64), _>(&mut store, "invalid")?;
instance.get_typed_func::<(), ((i8, u16, f32, f64),), _>(&mut store, "invalid")?;
let err = invalid_func.call(&mut store, ()).err().unwrap();
assert!(
err.to_string().contains("pointer out of bounds of memory"),
@@ -753,29 +760,29 @@ fn strings() -> Result<()> {
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let list8_to_str =
instance.get_typed_func::<(&[u8],), WasmStr, _>(&mut store, "list8-to-str")?;
instance.get_typed_func::<(&[u8],), (WasmStr,), _>(&mut store, "list8-to-str")?;
let str_to_list8 =
instance.get_typed_func::<(&str,), WasmList<u8>, _>(&mut store, "str-to-list8")?;
instance.get_typed_func::<(&str,), (WasmList<u8>,), _>(&mut store, "str-to-list8")?;
let list16_to_str =
instance.get_typed_func::<(&[u16],), WasmStr, _>(&mut store, "list16-to-str")?;
instance.get_typed_func::<(&[u16],), (WasmStr,), _>(&mut store, "list16-to-str")?;
let str_to_list16 =
instance.get_typed_func::<(&str,), WasmList<u16>, _>(&mut store, "str-to-list16")?;
instance.get_typed_func::<(&str,), (WasmList<u16>,), _>(&mut store, "str-to-list16")?;
let mut roundtrip = |x: &str| -> Result<()> {
let ret = list8_to_str.call(&mut store, (x.as_bytes(),))?;
let ret = list8_to_str.call(&mut store, (x.as_bytes(),))?.0;
assert_eq!(ret.to_str(&store)?, x);
list8_to_str.post_return(&mut store)?;
let utf16 = x.encode_utf16().collect::<Vec<_>>();
let ret = list16_to_str.call(&mut store, (&utf16[..],))?;
let ret = list16_to_str.call(&mut store, (&utf16[..],))?.0;
assert_eq!(ret.to_str(&store)?, x);
list16_to_str.post_return(&mut store)?;
let ret = str_to_list8.call(&mut store, (x,))?;
let ret = str_to_list8.call(&mut store, (x,))?.0;
assert_eq!(ret.iter(&store).collect::<Result<Vec<_>>>()?, x.as_bytes());
str_to_list8.post_return(&mut store)?;
let ret = str_to_list16.call(&mut store, (x,))?;
let ret = str_to_list16.call(&mut store, (x,))?.0;
assert_eq!(ret.iter(&store).collect::<Result<Vec<_>>>()?, utf16,);
str_to_list16.post_return(&mut store)?;
@@ -788,27 +795,29 @@ fn strings() -> Result<()> {
roundtrip("💝")?;
roundtrip("Löwe 老虎 Léopard")?;
let ret = list8_to_str.call(&mut store, (b"\xff",))?;
let ret = list8_to_str.call(&mut store, (b"\xff",))?.0;
let err = ret.to_str(&store).unwrap_err();
assert!(err.to_string().contains("invalid utf-8"), "{}", err);
list8_to_str.post_return(&mut store)?;
let ret = list8_to_str.call(&mut store, (b"hello there \xff invalid",))?;
let ret = list8_to_str
.call(&mut store, (b"hello there \xff invalid",))?
.0;
let err = ret.to_str(&store).unwrap_err();
assert!(err.to_string().contains("invalid utf-8"), "{}", err);
list8_to_str.post_return(&mut store)?;
let ret = list16_to_str.call(&mut store, (&[0xd800],))?;
let ret = list16_to_str.call(&mut store, (&[0xd800],))?.0;
let err = ret.to_str(&store).unwrap_err();
assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
list16_to_str.post_return(&mut store)?;
let ret = list16_to_str.call(&mut store, (&[0xdfff],))?;
let ret = list16_to_str.call(&mut store, (&[0xdfff],))?.0;
let err = ret.to_str(&store).unwrap_err();
assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
list16_to_str.post_return(&mut store)?;
let ret = list16_to_str.call(&mut store, (&[0xd800, 0xff00],))?;
let ret = list16_to_str.call(&mut store, (&[0xd800, 0xff00],))?.0;
let err = ret.to_str(&store).unwrap_err();
assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
list16_to_str.post_return(&mut store)?;
@@ -856,24 +865,24 @@ fn many_parameters() -> Result<()> {
)
(core instance $i (instantiate $m))
(type $result (tuple (list u8) u32))
(type $t (func
(param s8) ;; offset 0, size 1
(param u64) ;; offset 8, size 8
(param float32) ;; offset 16, size 4
(param u8) ;; offset 20, size 1
(param unit) ;; offset 21, size 0
(param s16) ;; offset 22, size 2
(param string) ;; offset 24, size 8
(param (list u32)) ;; offset 32, size 8
(param bool) ;; offset 40, size 1
(param bool) ;; offset 41, size 1
(param char) ;; offset 44, size 4
(param (list bool)) ;; offset 48, size 8
(param (list char)) ;; offset 56, size 8
(param (list string)) ;; offset 64, size 8
(param "p1" s8) ;; offset 0, size 1
(param "p2" u64) ;; offset 8, size 8
(param "p3" float32) ;; offset 16, size 4
(param "p4" u8) ;; offset 20, size 1
(param "p5" (tuple)) ;; offset 21, size 0
(param "p6" s16) ;; offset 22, size 2
(param "p7" string) ;; offset 24, size 8
(param "p8" (list u32)) ;; offset 32, size 8
(param "p9" bool) ;; offset 40, size 1
(param "pa" bool) ;; offset 41, size 1
(param "pb" char) ;; offset 44, size 4
(param "pc" (list bool)) ;; offset 48, size 8
(param "pd" (list char)) ;; offset 56, size 8
(param "pe" (list string)) ;; offset 64, size 8
(result $result)
(result "all-memory" (list u8))
(result "pointer" u32)
))
(func (export "many-param") (type $t)
(canon lift
@@ -1000,16 +1009,16 @@ fn some_traps() -> Result<()> {
)
(type $t (func
(param string)
(param string)
(param string)
(param string)
(param string)
(param string)
(param string)
(param string)
(param string)
(param string)
(param "s1" string)
(param "s2" string)
(param "s3" string)
(param "s4" string)
(param "s5" string)
(param "s6" string)
(param "s7" string)
(param "s8" string)
(param "s9" string)
(param "s10" string)
))
(func (export "take-many-unreachable") (type $t)
(canon lift (core func $i "take-many") (memory $i "memory") (realloc (func $i "realloc")))
@@ -1246,7 +1255,7 @@ fn char_bool_memory() -> Result<()> {
)
(core instance $i (instantiate $m))
(func (export "ret-tuple") (param u32) (param u32) (result (tuple bool char))
(func (export "ret-tuple") (param "a" u32) (param "b" u32) (result "c" bool) (result "d" char)
(canon lift (core func $i "ret-tuple")
(memory $i "memory")
(realloc (func $i "realloc")))
@@ -1328,10 +1337,10 @@ fn string_list_oob() -> Result<()> {
let mut store = Store::new(&engine, ());
let ret_list_u8 = Linker::new(&engine)
.instantiate(&mut store, &component)?
.get_typed_func::<(), WasmList<u8>, _>(&mut store, "ret-list-u8")?;
.get_typed_func::<(), (WasmList<u8>,), _>(&mut store, "ret-list-u8")?;
let ret_string = Linker::new(&engine)
.instantiate(&mut store, &component)?
.get_typed_func::<(), WasmStr, _>(&mut store, "ret-string")?;
.get_typed_func::<(), (WasmStr,), _>(&mut store, "ret-string")?;
let err = ret_list_u8.call(&mut store, ()).err().unwrap();
assert!(err.to_string().contains("out of bounds"), "{}", err);
@@ -1373,8 +1382,8 @@ fn tuples() -> Result<()> {
(core instance $i (instantiate $m))
(func (export "foo")
(param (tuple s32 float64))
(param (tuple s8))
(param "a" (tuple s32 float64))
(param "b" (tuple s8))
(result (tuple u16))
(canon lift (core func $i "foo"))
)
@@ -1385,8 +1394,8 @@ fn tuples() -> Result<()> {
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let foo = instance.get_typed_func::<((i32, f64), (i8,)), (u16,), _>(&mut store, "foo")?;
assert_eq!(foo.call(&mut store, ((0, 1.0), (2,)))?, (3,));
let foo = instance.get_typed_func::<((i32, f64), (i8,)), ((u16,),), _>(&mut store, "foo")?;
assert_eq!(foo.call(&mut store, ((0, 1.0), (2,)))?, ((3,),));
Ok(())
}
@@ -1444,35 +1453,35 @@ fn option() -> Result<()> {
)
(core instance $i (instantiate $m))
(func (export "option-unit-to-u32") (param (option unit)) (result u32)
(func (export "option-unit-to-u32") (param (option (tuple))) (result u32)
(canon lift (core func $i "pass0"))
)
(func (export "option-u8-to-tuple") (param (option u8)) (result (tuple u32 u32))
(func (export "option-u8-to-tuple") (param (option u8)) (result "a" u32) (result "b" u32)
(canon lift (core func $i "pass1") (memory $i "memory"))
)
(func (export "option-u32-to-tuple") (param (option u32)) (result (tuple u32 u32))
(func (export "option-u32-to-tuple") (param (option u32)) (result "a" u32) (result "b" u32)
(canon lift (core func $i "pass1") (memory $i "memory"))
)
(func (export "option-string-to-tuple") (param (option string)) (result (tuple u32 string))
(func (export "option-string-to-tuple") (param (option string)) (result "a" u32) (result "b" string)
(canon lift
(core func $i "pass2")
(memory $i "memory")
(realloc (func $i "realloc"))
)
)
(func (export "to-option-unit") (param u32) (result (option unit))
(func (export "to-option-unit") (param u32) (result (option (tuple)))
(canon lift (core func $i "pass0"))
)
(func (export "to-option-u8") (param u32) (param u32) (result (option u8))
(func (export "to-option-u8") (param "a" u32) (param "b" u32) (result (option u8))
(canon lift (core func $i "pass1") (memory $i "memory"))
)
(func (export "to-option-u32") (param u32) (param u32) (result (option u32))
(func (export "to-option-u32") (param "a" u32) (param "b" u32) (result (option u32))
(canon lift
(core func $i "pass1")
(memory $i "memory")
)
)
(func (export "to-option-string") (param u32) (param string) (result (option string))
(func (export "to-option-string") (param "a" u32) (param "b" string) (result (option string))
(canon lift
(core func $i "pass2")
(memory $i "memory")
@@ -1488,10 +1497,10 @@ fn option() -> Result<()> {
let linker = Linker::new(&engine);
let instance = linker.instantiate(&mut store, &component)?;
let option_unit_to_u32 =
instance.get_typed_func::<(Option<()>,), u32, _>(&mut store, "option-unit-to-u32")?;
assert_eq!(option_unit_to_u32.call(&mut store, (None,))?, 0);
instance.get_typed_func::<(Option<()>,), (u32,), _>(&mut store, "option-unit-to-u32")?;
assert_eq!(option_unit_to_u32.call(&mut store, (None,))?, (0,));
option_unit_to_u32.post_return(&mut store)?;
assert_eq!(option_unit_to_u32.call(&mut store, (Some(()),))?, 1);
assert_eq!(option_unit_to_u32.call(&mut store, (Some(()),))?, (1,));
option_unit_to_u32.post_return(&mut store)?;
let option_u8_to_tuple = instance
@@ -1534,49 +1543,49 @@ fn option() -> Result<()> {
let instance = linker.instantiate(&mut store, &component)?;
let to_option_unit =
instance.get_typed_func::<(u32,), Option<()>, _>(&mut store, "to-option-unit")?;
assert_eq!(to_option_unit.call(&mut store, (0,))?, None);
instance.get_typed_func::<(u32,), (Option<()>,), _>(&mut store, "to-option-unit")?;
assert_eq!(to_option_unit.call(&mut store, (0,))?, (None,));
to_option_unit.post_return(&mut store)?;
assert_eq!(to_option_unit.call(&mut store, (1,))?, Some(()));
assert_eq!(to_option_unit.call(&mut store, (1,))?, (Some(()),));
to_option_unit.post_return(&mut store)?;
let err = to_option_unit.call(&mut store, (2,)).unwrap_err();
assert!(err.to_string().contains("invalid option"), "{}", err);
let instance = linker.instantiate(&mut store, &component)?;
let to_option_u8 =
instance.get_typed_func::<(u32, u32), Option<u8>, _>(&mut store, "to-option-u8")?;
assert_eq!(to_option_u8.call(&mut store, (0x00_00, 0))?, None);
instance.get_typed_func::<(u32, u32), (Option<u8>,), _>(&mut store, "to-option-u8")?;
assert_eq!(to_option_u8.call(&mut store, (0x00_00, 0))?, (None,));
to_option_u8.post_return(&mut store)?;
assert_eq!(to_option_u8.call(&mut store, (0x00_01, 0))?, Some(0));
assert_eq!(to_option_u8.call(&mut store, (0x00_01, 0))?, (Some(0),));
to_option_u8.post_return(&mut store)?;
assert_eq!(to_option_u8.call(&mut store, (0xfd_01, 0))?, Some(0xfd));
assert_eq!(to_option_u8.call(&mut store, (0xfd_01, 0))?, (Some(0xfd),));
to_option_u8.post_return(&mut store)?;
assert!(to_option_u8.call(&mut store, (0x00_02, 0)).is_err());
let instance = linker.instantiate(&mut store, &component)?;
let to_option_u32 =
instance.get_typed_func::<(u32, u32), Option<u32>, _>(&mut store, "to-option-u32")?;
assert_eq!(to_option_u32.call(&mut store, (0, 0))?, None);
instance.get_typed_func::<(u32, u32), (Option<u32>,), _>(&mut store, "to-option-u32")?;
assert_eq!(to_option_u32.call(&mut store, (0, 0))?, (None,));
to_option_u32.post_return(&mut store)?;
assert_eq!(to_option_u32.call(&mut store, (1, 0))?, Some(0));
assert_eq!(to_option_u32.call(&mut store, (1, 0))?, (Some(0),));
to_option_u32.post_return(&mut store)?;
assert_eq!(
to_option_u32.call(&mut store, (1, 0x1234fead))?,
Some(0x1234fead)
(Some(0x1234fead),)
);
to_option_u32.post_return(&mut store)?;
assert!(to_option_u32.call(&mut store, (2, 0)).is_err());
let instance = linker.instantiate(&mut store, &component)?;
let to_option_string = instance
.get_typed_func::<(u32, &str), Option<WasmStr>, _>(&mut store, "to-option-string")?;
let ret = to_option_string.call(&mut store, (0, ""))?;
.get_typed_func::<(u32, &str), (Option<WasmStr>,), _>(&mut store, "to-option-string")?;
let ret = to_option_string.call(&mut store, (0, ""))?.0;
assert!(ret.is_none());
to_option_string.post_return(&mut store)?;
let ret = to_option_string.call(&mut store, (1, ""))?;
let ret = to_option_string.call(&mut store, (1, ""))?.0;
assert_eq!(ret.unwrap().to_str(&store)?, "");
to_option_string.post_return(&mut store)?;
let ret = to_option_string.call(&mut store, (1, "cheesecake"))?;
let ret = to_option_string.call(&mut store, (1, "cheesecake"))?.0;
assert_eq!(ret.unwrap().to_str(&store)?, "cheesecake");
to_option_string.post_return(&mut store)?;
assert!(to_option_string.call(&mut store, (2, "")).is_err());
@@ -1637,24 +1646,24 @@ fn expected() -> Result<()> {
)
(core instance $i (instantiate $m))
(func (export "take-expected-unit") (param (expected unit unit)) (result u32)
(func (export "take-expected-unit") (param (result)) (result u32)
(canon lift (core func $i "pass0"))
)
(func (export "take-expected-u8-f32") (param (expected u8 float32)) (result (tuple u32 u32))
(func (export "take-expected-u8-f32") (param (result u8 (error float32))) (result "a" u32) (result "b" u32)
(canon lift (core func $i "pass1") (memory $i "memory"))
)
(type $list (list u8))
(func (export "take-expected-string") (param (expected string $list)) (result (tuple u32 string))
(func (export "take-expected-string") (param (result string (error $list))) (result "a" u32) (result "b" string)
(canon lift
(core func $i "pass2")
(memory $i "memory")
(realloc (func $i "realloc"))
)
)
(func (export "to-expected-unit") (param u32) (result (expected unit unit))
(func (export "to-expected-unit") (param u32) (result (result))
(canon lift (core func $i "pass0"))
)
(func (export "to-expected-s16-f32") (param u32) (param u32) (result (expected s16 float32))
(func (export "to-expected-s16-f32") (param "a" u32) (param "b" u32) (result (result s16 (error float32)))
(canon lift
(core func $i "pass1")
(memory $i "memory")
@@ -1669,11 +1678,11 @@ fn expected() -> Result<()> {
let mut store = Store::new(&engine, ());
let linker = Linker::new(&engine);
let instance = linker.instantiate(&mut store, &component)?;
let take_expected_unit =
instance.get_typed_func::<(Result<(), ()>,), u32, _>(&mut store, "take-expected-unit")?;
assert_eq!(take_expected_unit.call(&mut store, (Ok(()),))?, 0);
let take_expected_unit = instance
.get_typed_func::<(Result<(), ()>,), (u32,), _>(&mut store, "take-expected-unit")?;
assert_eq!(take_expected_unit.call(&mut store, (Ok(()),))?, (0,));
take_expected_unit.post_return(&mut store)?;
assert_eq!(take_expected_unit.call(&mut store, (Err(()),))?, 1);
assert_eq!(take_expected_unit.call(&mut store, (Err(()),))?, (1,));
take_expected_unit.post_return(&mut store)?;
let take_expected_u8_f32 = instance
@@ -1702,27 +1711,29 @@ fn expected() -> Result<()> {
let instance = linker.instantiate(&mut store, &component)?;
let to_expected_unit =
instance.get_typed_func::<(u32,), Result<(), ()>, _>(&mut store, "to-expected-unit")?;
assert_eq!(to_expected_unit.call(&mut store, (0,))?, Ok(()));
instance.get_typed_func::<(u32,), (Result<(), ()>,), _>(&mut store, "to-expected-unit")?;
assert_eq!(to_expected_unit.call(&mut store, (0,))?, (Ok(()),));
to_expected_unit.post_return(&mut store)?;
assert_eq!(to_expected_unit.call(&mut store, (1,))?, Err(()));
assert_eq!(to_expected_unit.call(&mut store, (1,))?, (Err(()),));
to_expected_unit.post_return(&mut store)?;
let err = to_expected_unit.call(&mut store, (2,)).unwrap_err();
assert!(err.to_string().contains("invalid expected"), "{}", err);
let instance = linker.instantiate(&mut store, &component)?;
let to_expected_s16_f32 = instance
.get_typed_func::<(u32, u32), Result<i16, f32>, _>(&mut store, "to-expected-s16-f32")?;
assert_eq!(to_expected_s16_f32.call(&mut store, (0, 0))?, Ok(0));
.get_typed_func::<(u32, u32), (Result<i16, f32>,), _>(&mut store, "to-expected-s16-f32")?;
assert_eq!(to_expected_s16_f32.call(&mut store, (0, 0))?, (Ok(0),));
to_expected_s16_f32.post_return(&mut store)?;
assert_eq!(to_expected_s16_f32.call(&mut store, (0, 100))?, Ok(100));
assert_eq!(to_expected_s16_f32.call(&mut store, (0, 100))?, (Ok(100),));
to_expected_s16_f32.post_return(&mut store)?;
assert_eq!(
to_expected_s16_f32.call(&mut store, (1, 1.0f32.to_bits()))?,
Err(1.0)
(Err(1.0),)
);
to_expected_s16_f32.post_return(&mut store)?;
let ret = to_expected_s16_f32.call(&mut store, (1, CANON_32BIT_NAN | 1))?;
let ret = to_expected_s16_f32
.call(&mut store, (1, CANON_32BIT_NAN | 1))?
.0;
assert_eq!(ret.unwrap_err().to_bits(), CANON_32BIT_NAN);
to_expected_s16_f32.post_return(&mut store)?;
assert!(to_expected_s16_f32.call(&mut store, (2, 0)).is_err());
@@ -1768,10 +1779,13 @@ fn fancy_list() -> Result<()> {
(core instance $i (instantiate $m))
(type $a (option u8))
(type $b (expected unit string))
(type $b (result (error string)))
(type $input (list (tuple $a $b)))
(type $output (tuple u32 u32 (list u8)))
(func (export "take") (param $input) (result $output)
(func (export "take")
(param $input)
(result "ptr" u32)
(result "len" u32)
(result "list" (list u8))
(canon lift
(core func $i "take")
(memory $i "memory")
@@ -1873,9 +1887,9 @@ fn invalid_alignment() -> Result<()> {
(core instance $i (instantiate $m))
(func (export "many-params")
(param string) (param string) (param string) (param string)
(param string) (param string) (param string) (param string)
(param string) (param string) (param string) (param string)
(param "s1" string) (param "s2" string) (param "s3" string) (param "s4" string)
(param "s5" string) (param "s6" string) (param "s7" string) (param "s8" string)
(param "s9" string) (param "s10" string) (param "s11" string) (param "s12" string)
(canon lift
(core func $i "take-i32")
(memory $i "memory")
@@ -1929,7 +1943,7 @@ fn invalid_alignment() -> Result<()> {
);
let err = instance(&mut store)?
.get_typed_func::<(), WasmStr, _>(&mut store, "string-ret")?
.get_typed_func::<(), (WasmStr,), _>(&mut store, "string-ret")?
.call(&mut store, ())
.err()
.unwrap();
@@ -1940,7 +1954,7 @@ fn invalid_alignment() -> Result<()> {
);
let err = instance(&mut store)?
.get_typed_func::<(), WasmList<u32>, _>(&mut store, "list-u32-ret")?
.get_typed_func::<(), (WasmList<u32>,), _>(&mut store, "list-u32-ret")?
.call(&mut store, ())
.err()
.unwrap();
@@ -2073,8 +2087,9 @@ fn raw_slice_of_various_types() -> Result<()> {
};
let list = instance
.get_typed_func::<(), WasmList<u8>, _>(&mut store, "list-u8")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<u8>,), _>(&mut store, "list-u8")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2083,8 +2098,9 @@ fn raw_slice_of_various_types() -> Result<()> {
]
);
let list = instance
.get_typed_func::<(), WasmList<i8>, _>(&mut store, "list-i8")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<i8>,), _>(&mut store, "list-i8")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2094,8 +2110,9 @@ fn raw_slice_of_various_types() -> Result<()> {
);
let list = instance
.get_typed_func::<(), WasmList<u16>, _>(&mut store, "list-u16")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<u16>,), _>(&mut store, "list-u16")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2110,8 +2127,9 @@ fn raw_slice_of_various_types() -> Result<()> {
]
);
let list = instance
.get_typed_func::<(), WasmList<i16>, _>(&mut store, "list-i16")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<i16>,), _>(&mut store, "list-i16")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2126,8 +2144,9 @@ fn raw_slice_of_various_types() -> Result<()> {
]
);
let list = instance
.get_typed_func::<(), WasmList<u32>, _>(&mut store, "list-u32")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<u32>,), _>(&mut store, "list-u32")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2138,8 +2157,9 @@ fn raw_slice_of_various_types() -> Result<()> {
]
);
let list = instance
.get_typed_func::<(), WasmList<i32>, _>(&mut store, "list-i32")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<i32>,), _>(&mut store, "list-i32")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2150,8 +2170,9 @@ fn raw_slice_of_various_types() -> Result<()> {
]
);
let list = instance
.get_typed_func::<(), WasmList<u64>, _>(&mut store, "list-u64")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<u64>,), _>(&mut store, "list-u64")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2160,8 +2181,9 @@ fn raw_slice_of_various_types() -> Result<()> {
]
);
let list = instance
.get_typed_func::<(), WasmList<i64>, _>(&mut store, "list-i64")?
.call_and_post_return(&mut store, ())?;
.get_typed_func::<(), (WasmList<i64>,), _>(&mut store, "list-i64")?
.call_and_post_return(&mut store, ())?
.0;
assert_eq!(
list.as_le_slice(&store),
[
@@ -2194,11 +2216,11 @@ fn lower_then_lift() -> Result<()> {
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, ());
let mut linker = Linker::new(&engine);
linker.root().func_wrap("f", || Ok(2u32))?;
linker.root().func_wrap("f", || Ok((2u32,)))?;
let instance = linker.instantiate(&mut store, &component)?;
let f = instance.get_typed_func::<(), i32, _>(&mut store, "f")?;
assert_eq!(f.call(&mut store, ())?, 2);
let f = instance.get_typed_func::<(), (i32,), _>(&mut store, "f")?;
assert_eq!(f.call(&mut store, ())?, (2,));
// First test strings when the import/export ABI happen to line up
let component = format!(
@@ -2272,11 +2294,11 @@ fn lower_then_lift() -> Result<()> {
.root()
.func_wrap("s2", |store: StoreContextMut<'_, ()>, x: WasmStr| {
assert_eq!(x.to_str(&store)?, "hello");
Ok(u32::MAX)
Ok((u32::MAX,))
})?;
let instance = linker.instantiate(&mut store, &component)?;
let f = instance.get_typed_func::<(&str,), WasmStr, _>(&mut store, "f")?;
let f = instance.get_typed_func::<(&str,), (WasmStr,), _>(&mut store, "f")?;
let err = f.call(&mut store, ("hello",)).err().unwrap();
assert!(
err.to_string().contains("return pointer not aligned"),
@@ -2339,7 +2361,7 @@ fn errors_that_poison_instance() -> Result<()> {
assert_poisoned(f3.call(&mut store, ("x",)));
let instance = linker.instantiate(&mut store, &component)?;
let f4 = instance.get_typed_func::<(), WasmStr, _>(&mut store, "f4")?;
let f4 = instance.get_typed_func::<(), (WasmStr,), _>(&mut store, "f4")?;
assert!(f4.call(&mut store, ()).is_err());
assert_poisoned(f4.call(&mut store, ()));
@@ -2414,7 +2436,7 @@ fn run_export_with_internal_adapter() -> Result<()> {
let mut store = Store::new(&engine, ());
let linker = Linker::new(&engine);
let instance = linker.instantiate(&mut store, &component)?;
let run = instance.get_typed_func::<(), u32, _>(&mut store, "run")?;
assert_eq!(run.call(&mut store, ())?, 5);
let run = instance.get_typed_func::<(), (u32,), _>(&mut store, "run")?;
assert_eq!(run.call(&mut store, ())?, (5,));
Ok(())
}

View File

@@ -147,11 +147,11 @@ fn simple() -> Result<()> {
linker.root().func_new(
&component,
"",
|mut store: StoreContextMut<'_, Option<String>>, args| {
|mut store: StoreContextMut<'_, Option<String>>, args, _results| {
if let Val::String(s) = &args[0] {
assert!(store.data().is_none());
*store.data_mut() = Some(s.to_string());
Ok(Val::Unit)
Ok(())
} else {
panic!()
}
@@ -161,7 +161,7 @@ fn simple() -> Result<()> {
instance
.get_func(&mut store, "call")
.unwrap()
.call(&mut store, &[])?;
.call(&mut store, &[], &mut [])?;
assert_eq!(store.data().as_ref().unwrap(), "hello world");
Ok(())
@@ -244,9 +244,7 @@ fn attempt_to_leave_during_malloc() -> Result<()> {
.func_wrap("thunk", || -> Result<()> { panic!("should not get here") })?;
linker
.root()
.func_wrap("ret-string", || -> Result<String> {
Ok("hello".to_string())
})?;
.func_wrap("ret-string", || -> Result<_> { Ok(("hello".to_string(),)) })?;
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, ());
@@ -368,22 +366,22 @@ fn attempt_to_reenter_during_host() -> Result<()> {
linker.root().func_new(
&component,
"thunk",
|mut store: StoreContextMut<'_, DynamicState>, _| {
|mut store: StoreContextMut<'_, DynamicState>, _, _| {
let func = store.data_mut().func.take().unwrap();
let trap = func.call(&mut store, &[]).unwrap_err();
let trap = func.call(&mut store, &[], &mut []).unwrap_err();
assert!(
trap.to_string()
.contains("cannot reenter component instance"),
"bad trap: {}",
trap,
);
Ok(Val::Unit)
Ok(())
},
)?;
let instance = linker.instantiate(&mut store, &component)?;
let func = instance.get_func(&mut store, "run").unwrap();
store.data_mut().func = Some(func);
func.call(&mut store, &[])?;
func.call(&mut store, &[], &mut [])?;
Ok(())
}
@@ -532,9 +530,9 @@ fn stack_and_heap_args_and_rets() -> Result<()> {
// First, test the static API
let mut linker = Linker::new(&engine);
linker.root().func_wrap("f1", |x: u32| -> Result<u32> {
linker.root().func_wrap("f1", |x: u32| -> Result<(u32,)> {
assert_eq!(x, 1);
Ok(2)
Ok((2,))
})?;
linker.root().func_wrap(
"f2",
@@ -550,16 +548,16 @@ fn stack_and_heap_args_and_rets() -> Result<()> {
WasmStr,
WasmStr,
)|
-> Result<u32> {
-> Result<(u32,)> {
assert_eq!(arg.0.to_str(&cx).unwrap(), "abc");
Ok(3)
Ok((3,))
},
)?;
linker
.root()
.func_wrap("f3", |arg: u32| -> Result<String> {
.func_wrap("f3", |arg: u32| -> Result<(String,)> {
assert_eq!(arg, 8);
Ok("xyz".to_string())
Ok(("xyz".to_string(),))
})?;
linker.root().func_wrap(
"f4",
@@ -575,9 +573,9 @@ fn stack_and_heap_args_and_rets() -> Result<()> {
WasmStr,
WasmStr,
)|
-> Result<String> {
-> Result<(String,)> {
assert_eq!(arg.0.to_str(&cx).unwrap(), "abc");
Ok("xyz".to_string())
Ok(("xyz".to_string(),))
},
)?;
let instance = linker.instantiate(&mut store, &component)?;
@@ -588,51 +586,63 @@ fn stack_and_heap_args_and_rets() -> Result<()> {
// Next, test the dynamic API
let mut linker = Linker::new(&engine);
linker.root().func_new(&component, "f1", |_, args| {
if let Val::U32(x) = &args[0] {
assert_eq!(*x, 1);
Ok(Val::U32(2))
} else {
panic!()
}
})?;
linker.root().func_new(&component, "f2", |_, args| {
if let Val::Tuple(tuple) = &args[0] {
if let Val::String(s) = &tuple.values()[0] {
assert_eq!(s.deref(), "abc");
Ok(Val::U32(3))
linker
.root()
.func_new(&component, "f1", |_, args, results| {
if let Val::U32(x) = &args[0] {
assert_eq!(*x, 1);
results[0] = Val::U32(2);
Ok(())
} else {
panic!()
}
} else {
panic!()
}
})?;
linker.root().func_new(&component, "f3", |_, args| {
if let Val::U32(x) = &args[0] {
assert_eq!(*x, 8);
Ok(Val::String("xyz".into()))
} else {
panic!();
}
})?;
linker.root().func_new(&component, "f4", |_, args| {
if let Val::Tuple(tuple) = &args[0] {
if let Val::String(s) = &tuple.values()[0] {
assert_eq!(s.deref(), "abc");
Ok(Val::String("xyz".into()))
})?;
linker
.root()
.func_new(&component, "f2", |_, args, results| {
if let Val::Tuple(tuple) = &args[0] {
if let Val::String(s) = &tuple.values()[0] {
assert_eq!(s.deref(), "abc");
results[0] = Val::U32(3);
Ok(())
} else {
panic!()
}
} else {
panic!()
}
} else {
panic!()
}
})?;
})?;
linker
.root()
.func_new(&component, "f3", |_, args, results| {
if let Val::U32(x) = &args[0] {
assert_eq!(*x, 8);
results[0] = Val::String("xyz".into());
Ok(())
} else {
panic!();
}
})?;
linker
.root()
.func_new(&component, "f4", |_, args, results| {
if let Val::Tuple(tuple) = &args[0] {
if let Val::String(s) = &tuple.values()[0] {
assert_eq!(s.deref(), "abc");
results[0] = Val::String("xyz".into());
Ok(())
} else {
panic!()
}
} else {
panic!()
}
})?;
let instance = linker.instantiate(&mut store, &component)?;
instance
.get_func(&mut store, "run")
.unwrap()
.call(&mut store, &[])?;
.call(&mut store, &[], &mut [])?;
Ok(())
}
@@ -693,8 +703,8 @@ fn bad_import_alignment() -> Result<()> {
let mut linker = Linker::new(&engine);
linker
.root()
.func_wrap("unaligned-retptr", || -> Result<String> {
Ok(String::new())
.func_wrap("unaligned-retptr", || -> Result<(String,)> {
Ok((String::new(),))
})?;
linker.root().func_wrap(
"unaligned-argptr",
@@ -783,18 +793,20 @@ fn no_actual_wasm_code() -> Result<()> {
*store.data_mut() = 0;
let mut linker = Linker::new(&engine);
linker
.root()
.func_new(&component, "f", |mut store: StoreContextMut<'_, u32>, _| {
linker.root().func_new(
&component,
"f",
|mut store: StoreContextMut<'_, u32>, _, _| {
*store.data_mut() += 1;
Ok(Val::Unit)
})?;
Ok(())
},
)?;
let instance = linker.instantiate(&mut store, &component)?;
let thunk = instance.get_func(&mut store, "thunk").unwrap();
assert_eq!(*store.data(), 0);
thunk.call(&mut store, &[])?;
thunk.call(&mut store, &[], &mut [])?;
assert_eq!(*store.data(), 1);
Ok(())

View File

@@ -27,10 +27,10 @@ fn record_derive() -> Result<()> {
let input = Foo { a: -42, b: 73 };
let output = instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")?
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?
.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
// Sad path: field count mismatch (too few)
@@ -41,7 +41,7 @@ fn record_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: field count mismatch (too many)
@@ -56,7 +56,7 @@ fn record_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: field name mismatch
@@ -68,7 +68,7 @@ fn record_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: field type mismatch
@@ -80,7 +80,7 @@ fn record_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Happy path redux, with generics this time
@@ -105,10 +105,10 @@ fn record_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let output = instance
.get_typed_func::<(Generic<i32, u32>,), Generic<i32, u32>, _>(&mut store, "echo")?
.get_typed_func::<(Generic<i32, u32>,), (Generic<i32, u32>,), _>(&mut store, "echo")?
.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
Ok(())
}
@@ -130,12 +130,12 @@ fn union_derive() -> Result<()> {
let component = Component::new(&engine, make_echo_component("(union s32 u32 s32)", 8))?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
for &input in &[Foo::A(-42), Foo::B(73), Foo::C(314159265)] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Sad path: case count mismatch (too few)
@@ -144,7 +144,7 @@ fn union_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: case count mismatch (too many)
@@ -156,11 +156,11 @@ fn union_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: case type mismatch
@@ -169,7 +169,7 @@ fn union_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Happy path redux, with generics this time
@@ -184,7 +184,7 @@ fn union_derive() -> Result<()> {
let component = Component::new(&engine, make_echo_component("(union s32 u32 s32)", 8))?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Generic<i32, u32, i32>,), Generic<i32, u32, i32>, _>(
let func = instance.get_typed_func::<(Generic<i32, u32, i32>,), (Generic<i32, u32, i32>,), _>(
&mut store, "echo",
)?;
@@ -195,7 +195,7 @@ fn union_derive() -> Result<()> {
] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
Ok(())
@@ -220,17 +220,17 @@ fn variant_derive() -> Result<()> {
let component = Component::new(
&engine,
make_echo_component(
r#"(variant (case "foo-bar-baz" s32) (case "B" u32) (case "C" unit))"#,
r#"(variant (case "foo-bar-baz" s32) (case "B" u32) (case "C"))"#,
8,
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
for &input in &[Foo::A(-42), Foo::B(73), Foo::C] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Sad path: case count mismatch (too few)
@@ -242,7 +242,7 @@ fn variant_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: case count mismatch (too many)
@@ -250,29 +250,26 @@ fn variant_derive() -> Result<()> {
let component = Component::new(
&engine,
make_echo_component(
r#"(variant (case "foo-bar-baz" s32) (case "B" u32) (case "C" unit) (case "D" u32))"#,
r#"(variant (case "foo-bar-baz" s32) (case "B" u32) (case "C") (case "D" u32))"#,
8,
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: case name mismatch
let component = Component::new(
&engine,
make_echo_component(
r#"(variant (case "A" s32) (case "B" u32) (case "C" unit))"#,
8,
),
make_echo_component(r#"(variant (case "A" s32) (case "B" u32) (case "C"))"#, 8),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: case type mismatch
@@ -280,14 +277,14 @@ fn variant_derive() -> Result<()> {
let component = Component::new(
&engine,
make_echo_component(
r#"(variant (case "foo-bar-baz" s32) (case "B" s32) (case "C" unit))"#,
r#"(variant (case "foo-bar-baz" s32) (case "B" s32) (case "C"))"#,
8,
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Happy path redux, with generics this time
@@ -304,18 +301,18 @@ fn variant_derive() -> Result<()> {
let component = Component::new(
&engine,
make_echo_component(
r#"(variant (case "foo-bar-baz" s32) (case "B" u32) (case "C" unit))"#,
r#"(variant (case "foo-bar-baz" s32) (case "B" u32) (case "C"))"#,
8,
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance
.get_typed_func::<(Generic<i32, u32>,), Generic<i32, u32>, _>(&mut store, "echo")?;
.get_typed_func::<(Generic<i32, u32>,), (Generic<i32, u32>,), _>(&mut store, "echo")?;
for &input in &[Generic::<i32, u32>::A(-42), Generic::B(73), Generic::C] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
Ok(())
@@ -342,12 +339,12 @@ fn enum_derive() -> Result<()> {
make_echo_component(r#"(enum "foo-bar-baz" "B" "C")"#, 4),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
for &input in &[Foo::A, Foo::B, Foo::C] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Sad path: case count mismatch (too few)
@@ -359,7 +356,7 @@ fn enum_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: case count mismatch (too many)
@@ -371,7 +368,7 @@ fn enum_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: case name mismatch
@@ -380,7 +377,7 @@ fn enum_derive() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Happy path redux, with large enums (i.e. more than 2^8 cases)
@@ -404,12 +401,12 @@ fn enum_derive() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Many,), Many, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Many,), (Many,), _>(&mut store, "echo")?;
for &input in &[Many::V0, Many::V1, Many::V254, Many::V255, Many::V256] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// TODO: The following case takes forever (i.e. I gave up after 30 minutes) to compile; we'll need to profile
@@ -437,9 +434,9 @@ fn flags() -> Result<()> {
let component = Component::new(&engine, make_echo_component(r#"(flags)"#, 0))?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Flags0,), Flags0, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Flags0,), (Flags0,), _>(&mut store, "echo")?;
let output = func.call_and_post_return(&mut store, (Flags0::default(),))?;
assert_eq!(output, Flags0::default());
assert_eq!(output, (Flags0::default(),));
// Simple 8-bit flags
wasmtime::component::flags! {
@@ -465,7 +462,7 @@ fn flags() -> Result<()> {
make_echo_component(r#"(flags "foo-bar-baz" "B" "C")"#, 4),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")?;
for n in 0..8 {
let mut input = Foo::default();
@@ -481,7 +478,7 @@ fn flags() -> Result<()> {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Sad path: flag count mismatch (too few)
@@ -493,7 +490,7 @@ fn flags() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: flag count mismatch (too many)
@@ -505,7 +502,7 @@ fn flags() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Sad path: flag name mismatch
@@ -514,7 +511,7 @@ fn flags() -> Result<()> {
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
assert!(instance
.get_typed_func::<(Foo,), Foo, _>(&mut store, "echo")
.get_typed_func::<(Foo,), (Foo,), _>(&mut store, "echo")
.is_err());
// Happy path redux, with large flag count (exactly 8)
@@ -560,7 +557,7 @@ fn flags() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo8Exact,), Foo8Exact, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo8Exact,), (Foo8Exact,), _>(&mut store, "echo")?;
for &input in &[
Foo8Exact::F0,
@@ -571,7 +568,7 @@ fn flags() -> Result<()> {
] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Happy path redux, with large flag count (more than 8)
@@ -609,12 +606,12 @@ fn flags() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo16,), Foo16, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo16,), (Foo16,), _>(&mut store, "echo")?;
for &input in &[Foo16::F0, Foo16::F1, Foo16::F6, Foo16::F7, Foo16::F8] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Happy path redux, with large flag count (exactly 16)
@@ -657,7 +654,7 @@ fn flags() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo16Exact,), Foo16Exact, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo16Exact,), (Foo16Exact,), _>(&mut store, "echo")?;
for &input in &[
Foo16Exact::F0,
@@ -668,7 +665,7 @@ fn flags() -> Result<()> {
] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Happy path redux, with large flag count (more than 16)
@@ -696,12 +693,12 @@ fn flags() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo32,), Foo32, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo32,), (Foo32,), _>(&mut store, "echo")?;
for &input in &[Foo32::F0, Foo32::F1, Foo32::F14, Foo32::F15, Foo32::F16] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Happy path redux, with large flag count (exactly 32)
@@ -744,7 +741,7 @@ fn flags() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo32Exact,), Foo32Exact, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo32Exact,), (Foo32Exact,), _>(&mut store, "echo")?;
for &input in &[
Foo32Exact::F0,
@@ -755,7 +752,7 @@ fn flags() -> Result<()> {
] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Happy path redux, with large flag count (more than 32)
@@ -783,12 +780,12 @@ fn flags() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo64,), Foo64, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo64,), (Foo64,), _>(&mut store, "echo")?;
for &input in &[Foo64::F0, Foo64::F1, Foo64::F30, Foo64::F31, Foo64::F32] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
// Happy path redux, with large flag count (more than 64)
@@ -816,12 +813,12 @@ fn flags() -> Result<()> {
),
)?;
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(Foo96,), Foo96, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(Foo96,), (Foo96,), _>(&mut store, "echo")?;
for &input in &[Foo96::F0, Foo96::F1, Foo96::F62, Foo96::F63, Foo96::F64] {
let output = func.call_and_post_return(&mut store, (input,))?;
assert_eq!(input, output);
assert_eq!((input,), output);
}
Ok(())

View File

@@ -162,11 +162,12 @@ fn thread_options_through_inner() -> Result<()> {
let mut linker = Linker::new(&engine);
linker
.root()
.func_wrap("hostfn", |param: u32| Ok(param.to_string()))?;
.func_wrap("hostfn", |param: u32| Ok((param.to_string(),)))?;
let instance = linker.instantiate(&mut store, &component)?;
let result = instance
.get_typed_func::<(u32,), WasmStr, _>(&mut store, "run")?
.call(&mut store, (43,))?;
.get_typed_func::<(u32,), (WasmStr,), _>(&mut store, "run")?
.call(&mut store, (43,))?
.0;
assert_eq!(result.to_str(&store)?, "42");
Ok(())
}

View File

@@ -195,21 +195,21 @@ fn post_return_all_types() -> Result<()> {
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, false);
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let i32 = instance.get_typed_func::<(), u32, _>(&mut store, "i32")?;
let i64 = instance.get_typed_func::<(), u64, _>(&mut store, "i64")?;
let f32 = instance.get_typed_func::<(), f32, _>(&mut store, "f32")?;
let f64 = instance.get_typed_func::<(), f64, _>(&mut store, "f64")?;
let i32 = instance.get_typed_func::<(), (u32,), _>(&mut store, "i32")?;
let i64 = instance.get_typed_func::<(), (u64,), _>(&mut store, "i64")?;
let f32 = instance.get_typed_func::<(), (f32,), _>(&mut store, "f32")?;
let f64 = instance.get_typed_func::<(), (f64,), _>(&mut store, "f64")?;
assert_eq!(i32.call(&mut store, ())?, 1);
assert_eq!(i32.call(&mut store, ())?, (1,));
i32.post_return(&mut store)?;
assert_eq!(i64.call(&mut store, ())?, 2);
assert_eq!(i64.call(&mut store, ())?, (2,));
i64.post_return(&mut store)?;
assert_eq!(f32.call(&mut store, ())?, 3.);
assert_eq!(f32.call(&mut store, ())?, (3.,));
f32.post_return(&mut store)?;
assert_eq!(f64.call(&mut store, ())?, 4.);
assert_eq!(f64.call(&mut store, ())?, (4.,));
f64.post_return(&mut store)?;
Ok(())
@@ -250,8 +250,8 @@ fn post_return_string() -> Result<()> {
let component = Component::new(&engine, component)?;
let mut store = Store::new(&engine, false);
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let get = instance.get_typed_func::<(), WasmStr, _>(&mut store, "get")?;
let s = get.call(&mut store, ())?;
let get = instance.get_typed_func::<(), (WasmStr,), _>(&mut store, "get")?;
let s = get.call(&mut store, ())?.0;
assert_eq!(s.to_str(&store)?, "hello world");
get.post_return(&mut store)?;

View File

@@ -175,15 +175,15 @@ fn test_roundtrip(engine: &Engine, src: &str, dst: &str) -> Result<()> {
.root()
.func_wrap("host", |store: StoreContextMut<String>, arg: String| {
assert_eq!(*store.data(), arg);
Ok(arg)
Ok((arg,))
})?;
let instance = linker.instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(String,), String, _>(&mut store, "echo")?;
let func = instance.get_typed_func::<(String,), (String,), _>(&mut store, "echo")?;
for string in STRINGS {
println!("testing string {string:?}");
*store.data_mut() = string.to_string();
let ret = func.call(&mut store, (string.to_string(),))?;
let (ret,) = func.call(&mut store, (string.to_string(),))?;
assert_eq!(ret, *string);
func.post_return(&mut store)?;
}
@@ -554,7 +554,7 @@ fn test_raw_when_encoded(
(func (export "f") (param i32 i32 i32) (call $f (local.get 0) (local.get 2)))
)
(core instance $m (instantiate $m (with "" (instance (export "" (func $f))))))
(func (export "f") (param (list u8)) (param u32) (canon lift (core func $m "f")
(func (export "f") (param "a" (list u8)) (param "b" u32) (canon lift (core func $m "f")
(memory $libc "memory")
(realloc (func $libc "realloc"))))
)

View File

@@ -121,7 +121,7 @@
(memory (export "memory") 0)
)
(core instance $m (instantiate $m))
(func $f (param (list unit))
(func $f (param (list (record)))
(canon lift
(core func $m "x")
(realloc (func $m "realloc"))

View File

@@ -94,10 +94,10 @@
(component
(type $roundtrip (func
;; 20 u32 params
(param u32) (param u32) (param u32) (param u32) (param u32)
(param u32) (param u32) (param u32) (param u32) (param u32)
(param u32) (param u32) (param u32) (param u32) (param u32)
(param u32) (param u32) (param u32) (param u32) (param u32)
(param "a1" u32) (param "a2" u32) (param "a3" u32) (param "a4" u32) (param "a5" u32)
(param "a6" u32) (param "a7" u32) (param "a8" u32) (param "a9" u32) (param "a10" u32)
(param "a11" u32) (param "a12" u32) (param "a13" u32) (param "a14" u32) (param "a15" u32)
(param "a16" u32) (param "a17" u32) (param "a18" u32) (param "a19" u32) (param "a20" u32)
;; 10 u32 results
(result (tuple u32 u32 u32 u32 u32 u32 u32 u32 u32 u32))
@@ -717,8 +717,8 @@
;; simple variant translation
(component
(type $a (variant (case "x" unit)))
(type $b (variant (case "y" unit)))
(type $a (variant (case "x")))
(type $b (variant (case "y")))
(component $c1
(core module $m
@@ -756,7 +756,7 @@
;; invalid variant discriminant in a parameter
(assert_trap
(component
(type $a (variant (case "x" unit)))
(type $a (variant (case "x")))
(component $c1
(core module $m
@@ -789,7 +789,7 @@
;; invalid variant discriminant in a result
(assert_trap
(component
(type $a (variant (case "x" unit)))
(type $a (variant (case "x")))
(component $c1
(core module $m
@@ -889,6 +889,12 @@
(type $d (variant (case "a" float32) (case "b" float64)))
(type $e (variant (case "a" float32) (case "b" s64)))
(type $func_a (func (param "x" bool) (param "a" $a)))
(type $func_b (func (param "x" bool) (param "b" $b)))
(type $func_c (func (param "x" bool) (param "c" $c)))
(type $func_d (func (param "x" bool) (param "d" $d)))
(type $func_e (func (param "x" bool) (param "e" $d)))
(component $c1
(core module $m
(func (export "a") (param i32 i32 i32)
@@ -943,19 +949,19 @@
)
)
(core instance $m (instantiate $m))
(func (export "a") (param bool) (param $a) (canon lift (core func $m "a")))
(func (export "b") (param bool) (param $b) (canon lift (core func $m "b")))
(func (export "c") (param bool) (param $c) (canon lift (core func $m "c")))
(func (export "d") (param bool) (param $d) (canon lift (core func $m "d")))
(func (export "e") (param bool) (param $e) (canon lift (core func $m "e")))
(func (export "a") (type $func_a) (canon lift (core func $m "a")))
(func (export "b") (type $func_b) (canon lift (core func $m "b")))
(func (export "c") (type $func_c) (canon lift (core func $m "c")))
(func (export "d") (type $func_d) (canon lift (core func $m "d")))
(func (export "e") (type $func_e) (canon lift (core func $m "e")))
)
(component $c2
(import "" (instance $i
(export "a" (func (param bool) (param $a)))
(export "b" (func (param bool) (param $b)))
(export "c" (func (param bool) (param $c)))
(export "d" (func (param bool) (param $d)))
(export "e" (func (param bool) (param $e)))
(export "a" (func (type $func_a)))
(export "b" (func (type $func_b)))
(export "c" (func (type $func_c)))
(export "d" (func (type $func_d)))
(export "e" (func (type $func_e)))
))
(core func $a (canon lower (func $i "a")))
@@ -1008,10 +1014,10 @@
;; different size variants
(component
(type $a (variant
(case "a" unit)
(case "a")
(case "b" float32)
(case "c" (tuple float32 u32))
(case "d" (tuple float32 unit u64 u8))
(case "d" (tuple float32 (record) u64 u8))
))
(component $c1
@@ -1054,11 +1060,11 @@
)
)
(core instance $m (instantiate $m))
(func (export "a") (param u8) (param $a) (canon lift (core func $m "a")))
(func (export "a") (param "x" u8) (param "a" $a) (canon lift (core func $m "a")))
)
(component $c2
(import "" (instance $i
(export "a" (func (param u8) (param $a)))
(export "a" (func (param "x" u8) (param "a" $a)))
))
(core func $a (canon lower (func $i "a")))
@@ -1157,9 +1163,9 @@
(export "roundtrip" (func $c2 "roundtrip"))
)
(assert_return (invoke "roundtrip" (char.const "x")) (unit.const))
(assert_return (invoke "roundtrip" (char.const "⛳")) (unit.const))
(assert_return (invoke "roundtrip" (char.const "🍰")) (unit.const))
(assert_return (invoke "roundtrip" (char.const "x")))
(assert_return (invoke "roundtrip" (char.const "⛳")))
(assert_return (invoke "roundtrip" (char.const "🍰")))
;; invalid chars
(assert_trap

View File

@@ -39,4 +39,4 @@
(func (export "") (canon lift (core func $m "")))
)
(assert_return (invoke "") (unit.const))
(assert_return (invoke ""))

View File

@@ -1,9 +1,12 @@
(component
(type string)
(type (func (param string)))
(type $r (record (field "x" unit) (field "y" string)))
(type $r (record (field "x" (record)) (field "y" string)))
(type $u (union $r string))
(type $e (expected $u u32))
(type $e (result $u (error u32)))
(type (result $u))
(type (result (error $u)))
(type (result))
(type (func (param $e) (result (option $r))))
@@ -21,17 +24,17 @@
;; primitives in functions
(type (func
(param bool)
(param u8)
(param s8)
(param u16)
(param s16)
(param u32)
(param s32)
(param u64)
(param s64)
(param char)
(param string)
(param "a" bool)
(param "b" u8)
(param "c" s8)
(param "d" u16)
(param "e" s16)
(param "f" u32)
(param "g" s32)
(param "h" u64)
(param "i" s64)
(param "j" char)
(param "k" string)
))
;; primitives in types

View File

@@ -110,17 +110,17 @@
(assert_return (invoke "64.store64 o1" (i32.const 7)))
;; misaligned stores
(assert_return (invoke "32.store8" (i32.const 1)) (i32.const 0))
(assert_return (invoke "32.store8" (i32.const 1)))
(assert_trap (invoke "32.store16" (i32.const 1)) "misaligned memory access")
(assert_trap (invoke "32.store32" (i32.const 1)) "misaligned memory access")
(assert_return (invoke "64.store8" (i32.const 1)) (i64.const 0))
(assert_return (invoke "64.store8" (i32.const 1)))
(assert_trap (invoke "64.store16" (i32.const 1)) "misaligned memory access")
(assert_trap (invoke "64.store32" (i32.const 1)) "misaligned memory access")
(assert_trap (invoke "64.store64" (i32.const 1)) "misaligned memory access")
(assert_return (invoke "32.store8 o1" (i32.const 0)) (i32.const 0))
(assert_return (invoke "32.store8 o1" (i32.const 0)))
(assert_trap (invoke "32.store16 o1" (i32.const 0)) "misaligned memory access")
(assert_trap (invoke "32.store32 o1" (i32.const 0)) "misaligned memory access")
(assert_return (invoke "64.store8 o1" (i32.const 0)) (i64.const 0))
(assert_return (invoke "64.store8 o1" (i32.const 0)))
(assert_trap (invoke "64.store16 o1" (i32.const 0)) "misaligned memory access")
(assert_trap (invoke "64.store32 o1" (i32.const 0)) "misaligned memory access")
(assert_trap (invoke "64.store64 o1" (i32.const 0)) "misaligned memory access")