diff --git a/CHANGELOG.md b/CHANGELOG.md index e9f3c4be5e7..3446287b1fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ Looking for changes that affect our C API? See the [C API Changelog](lib/c-api/C ## **Unreleased** +## Fixed + + - [#3796](https://github.com/wasmerio/wasmer/pull/3796) Fix returning negative i64 values on web target + + + ## 3.2.1 - 21/04/2023 Some quick fixes for this maintenance release, mainly oriented towards Docs. diff --git a/lib/api/src/js/as_js.rs b/lib/api/src/js/as_js.rs index 370be4520b5..8aca92aa918 100644 --- a/lib/api/src/js/as_js.rs +++ b/lib/api/src/js/as_js.rs @@ -36,18 +36,11 @@ pub trait AsJs: Sized { pub fn param_from_js(ty: &Type, js_val: &JsValue) -> Value { match ty { Type::I32 => Value::I32(js_val.as_f64().unwrap() as _), - Type::I64 => { - let number = js_val.as_f64().map(|f| f as i64).unwrap_or_else(|| { - if js_val.is_bigint() { - // To support BigInt - let big_num: u128 = js_sys::BigInt::from(js_val.clone()).try_into().unwrap(); - big_num as i64 - } else { - (js_sys::Number::from(js_val.clone()).as_f64().unwrap()) as i64 - } - }); - Value::I64(number) - } + Type::I64 => Value::I64(if js_val.is_bigint() { + js_val.clone().try_into().unwrap() + } else { + js_val.as_f64().unwrap() as _ + }), Type::F32 => Value::F32(js_val.as_f64().unwrap() as _), Type::F64 => Value::F64(js_val.as_f64().unwrap()), Type::V128 => { diff --git a/lib/api/tests/import_function.rs b/lib/api/tests/import_function.rs index 809096d4ca7..7e1737fec57 100644 --- a/lib/api/tests/import_function.rs +++ b/lib/api/tests/import_function.rs @@ -5,6 +5,48 @@ use wasm_bindgen_test::*; use anyhow::Result; use wasmer::*; +#[universal_test] +fn pass_i64_between_host_and_plugin() -> Result<(), String> { + let mut store = Store::default(); + + let wat = r#"(module + (func $add_one_i64 (import "host" "add_one_i64") (param i64) (result i64)) + (func (export "add_three_i64") (param i64) (result i64) + (i64.add (call $add_one_i64 (i64.add (local.get 0) (i64.const 1))) (i64.const 1)) + ) + )"#; + let module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; + + let imports = { + imports! { + "host" => { + "add_one_i64" => Function::new_typed(&mut store, |value: i64| value.wrapping_add(1)), + }, + } + }; + + let instance = Instance::new(&mut store, &module, &imports).map_err(|e| format!("{e:?}"))?; + let add_three_i64 = instance + .exports + .get_typed_function::(&store, "add_three_i64") + .map_err(|e| format!("{e:?}"))?; + + let mut numbers = Vec::::new(); + numbers.extend(-4..=4); + numbers.extend((i64::MAX - 4)..=i64::MAX); + numbers.extend((i64::MIN)..=(i64::MIN + 4)); + + for number in numbers { + let wasm_result = add_three_i64 + .call(&mut store, number) + .map_err(|e| format!("{e:?}"))?; + let compare_result = number.wrapping_add(3); + + assert_eq!(wasm_result, compare_result) + } + Ok(()) +} + #[universal_test] fn calling_function_exports() -> Result<()> { let mut store = Store::default();