更新libclamav库1.0.0版本

This commit is contained in:
2023-01-14 18:28:39 +08:00
parent b879ee0b2e
commit 45fe15f472
8531 changed files with 1222046 additions and 177272 deletions

View File

@@ -0,0 +1,75 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.assert_null = x => {
assert.strictEqual(x, null);
};
exports.js_works = () => {
assert.strictEqual(wasm.api_foo(), 'foo');
assert.strictEqual(wasm.api_bar('a'), 'a');
assert.strictEqual(wasm.api_baz(), 1);
wasm.api_baz2(2, 'a');
assert.strictEqual(wasm.api_js_null(), null);
assert.strictEqual(wasm.api_js_undefined(), undefined);
wasm.api_test_is_null_undefined(null, undefined, 1.0);
assert.strictEqual(wasm.api_get_true(), true);
assert.strictEqual(wasm.api_get_false(), false);
wasm.api_test_bool(true, false, 1.0);
assert.strictEqual(typeof (wasm.api_mk_symbol()), 'symbol');
assert.strictEqual(typeof (wasm.api_mk_symbol2('a')), 'symbol');
assert.strictEqual(Symbol.keyFor(wasm.api_mk_symbol()), undefined);
assert.strictEqual(Symbol.keyFor(wasm.api_mk_symbol2('b')), undefined);
wasm.api_assert_symbols(Symbol(), 'a');
wasm.api_acquire_string('foo', null);
assert.strictEqual(wasm.api_acquire_string2(''), '');
assert.strictEqual(wasm.api_acquire_string2('a'), 'a');
let arr = [1, 2, 3, 4, {}, ['a', 'b', 'c']]
wasm.api_completely_variadic(...arr).forEach((element, index) => {
assert.strictEqual(element, arr[index]);
});
assert.strictEqual(
wasm.api_completely_variadic().length,
0
);
wasm.api_variadic_with_prefixed_params([], {}, ...arr).forEach((element, index) => {
assert.strictEqual(element, arr[index]);
});
};
exports.js_eq_works = () => {
assert.strictEqual(wasm.eq_test('a', 'a'), true);
assert.strictEqual(wasm.eq_test('a', 'b'), false);
assert.strictEqual(wasm.eq_test(NaN, NaN), false);
assert.strictEqual(wasm.eq_test({ a: 'a' }, { a: 'a' }), false);
assert.strictEqual(wasm.eq_test1(NaN), false);
let x = { a: 'a' };
assert.strictEqual(wasm.eq_test(x, x), true);
assert.strictEqual(wasm.eq_test1(x), true);
};
exports.debug_values = () => ([
null,
undefined,
0,
1.0,
true,
[1, 2, 3],
"string",
{ test: "object" },
[1.0, [2.0, 3.0]],
() => (null),
new Set(),
]);
exports.assert_function_table = (x, i) => {
const rawWasm = require('wasm-bindgen-test.js').__wasm;
assert.ok(x instanceof WebAssembly.Table);
assert.strictEqual(x.get(i), rawWasm.function_table_lookup);
};

View File

@@ -0,0 +1,199 @@
use js_sys::{Uint8Array, WebAssembly};
use wasm_bindgen::prelude::*;
use wasm_bindgen::{self, JsCast};
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/api.js")]
extern "C" {
fn js_works();
fn js_eq_works();
fn assert_null(v: JsValue);
fn debug_values() -> JsValue;
fn assert_function_table(a: JsValue, b: usize);
}
#[wasm_bindgen_test]
fn works() {
js_works();
}
#[wasm_bindgen]
pub fn api_foo() -> JsValue {
JsValue::from("foo")
}
#[wasm_bindgen]
pub fn api_bar(s: &str) -> JsValue {
JsValue::from(s)
}
#[wasm_bindgen]
pub fn api_baz() -> JsValue {
JsValue::from(1.0)
}
#[wasm_bindgen]
pub fn api_baz2(a: &JsValue, b: &JsValue) {
assert_eq!(a.as_f64(), Some(2.0));
assert_eq!(b.as_f64(), None);
}
#[wasm_bindgen]
pub fn api_js_null() -> JsValue {
JsValue::null()
}
#[wasm_bindgen]
pub fn api_js_undefined() -> JsValue {
JsValue::undefined()
}
#[wasm_bindgen]
pub fn api_test_is_null_undefined(a: &JsValue, b: &JsValue, c: &JsValue) {
assert!(a.is_null());
assert!(!a.is_undefined());
assert!(!b.is_null());
assert!(b.is_undefined());
assert!(!c.is_null());
assert!(!c.is_undefined());
}
#[wasm_bindgen]
pub fn api_get_true() -> JsValue {
JsValue::from(true)
}
#[wasm_bindgen]
pub fn api_get_false() -> JsValue {
JsValue::from(false)
}
#[wasm_bindgen]
pub fn api_test_bool(a: &JsValue, b: &JsValue, c: &JsValue) {
assert_eq!(a.as_bool(), Some(true));
assert_eq!(format!("{:?}", a), "JsValue(true)");
assert_eq!(b.as_bool(), Some(false));
assert_eq!(c.as_bool(), None);
}
#[wasm_bindgen]
pub fn api_mk_symbol() -> JsValue {
let a = JsValue::symbol(None);
assert!(a.is_symbol());
assert_eq!(format!("{:?}", a), "JsValue(Symbol)");
return a;
}
#[wasm_bindgen]
pub fn api_mk_symbol2(s: &str) -> JsValue {
let a = JsValue::symbol(Some(s));
assert!(a.is_symbol());
return a;
}
#[wasm_bindgen]
pub fn api_assert_symbols(a: &JsValue, b: &JsValue) {
assert!(a.is_symbol());
assert!(!b.is_symbol());
}
#[wasm_bindgen]
pub fn api_acquire_string(a: &JsValue, b: &JsValue) {
assert_eq!(a.as_string().unwrap(), "foo");
assert_eq!(format!("{:?}", a), "JsValue(\"foo\")");
assert_eq!(b.as_string(), None);
}
#[wasm_bindgen]
pub fn api_acquire_string2(a: &JsValue) -> String {
a.as_string().unwrap_or("wrong".to_string())
}
#[wasm_bindgen_test]
fn eq_works() {
js_eq_works();
}
#[wasm_bindgen]
pub fn eq_test(a: &JsValue, b: &JsValue) -> bool {
a == b
}
#[wasm_bindgen]
pub fn eq_test1(a: &JsValue) -> bool {
a == a
}
#[wasm_bindgen(variadic)]
pub fn api_completely_variadic(args: &JsValue) -> JsValue {
args.into()
}
#[wasm_bindgen(variadic)]
pub fn api_variadic_with_prefixed_params(
first: &JsValue,
second: &JsValue,
args: &JsValue,
) -> JsValue {
args.into()
}
#[wasm_bindgen_test]
fn null_keeps_working() {
assert_null(JsValue::null());
assert_null(JsValue::null());
}
#[wasm_bindgen_test]
fn memory_accessor_appears_to_work() {
let data = 3u32;
let ptr = &data as *const u32 as u32;
let my_mem = wasm_bindgen::memory();
let mem = my_mem.dyn_into::<WebAssembly::Memory>().unwrap();
let buf = mem.buffer();
let slice = Uint8Array::new(&buf);
let mut v = Vec::new();
slice
.subarray(ptr, ptr + 4)
.for_each(&mut |val, _, _| v.push(val));
assert_eq!(v, [3, 0, 0, 0]);
}
#[wasm_bindgen_test]
fn debug_output() {
let test_iter = debug_values()
.dyn_into::<js_sys::Array>()
.unwrap()
.values()
.into_iter();
let expecteds = vec![
"JsValue(null)",
"JsValue(undefined)",
"JsValue(0)",
"JsValue(1)",
"JsValue(true)",
"JsValue([1, 2, 3])",
"JsValue(\"string\")",
"JsValue(Object({\"test\":\"object\"}))",
"JsValue([1, [2, 3]])",
"JsValue(Function)",
"JsValue(Set)",
];
for (test, expected) in test_iter.zip(expecteds) {
assert_eq!(format!("{:?}", test.unwrap()), expected);
}
}
#[wasm_bindgen_test]
fn function_table_is() {
assert_function_table(
wasm_bindgen::function_table(),
function_table_lookup as usize,
);
}
#[no_mangle]
pub extern "C" fn function_table_lookup() {}

View File

@@ -0,0 +1,16 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
const ARGUMENT_NAMES = /([^\s,]+)/g;
const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
// https://stackoverflow.com/q/1007981/210304
function getArgNames(func) {
let fnStr = func.toString().replace(STRIP_COMMENTS, '');
let result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
return result === null ? [] : result;
}
exports.js_arg_names = () => {
assert.deepEqual(getArgNames(wasm.fn_with_many_args), ['_a', '_b', '_c', '_d']);
};

View File

@@ -0,0 +1,15 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/arg_names.js")]
extern "C" {
fn js_arg_names();
}
#[wasm_bindgen]
pub fn fn_with_many_args(_a: i32, _b: i32, _c: i32, _d: i32) {}
#[wasm_bindgen_test]
fn rust_arg_names() {
js_arg_names();
}

View File

@@ -0,0 +1,53 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.i64_js_identity = a => a;
exports.u64_js_identity = a => a;
exports.js_works = () => {
assert.strictEqual(wasm.zero(), BigInt('0'));
assert.strictEqual(wasm.one(), BigInt('1'));
assert.strictEqual(wasm.neg_one(), BigInt('-1'));
assert.strictEqual(wasm.i32_min(), BigInt('-2147483648'));
assert.strictEqual(wasm.u32_max(), BigInt('4294967295'));
assert.strictEqual(wasm.i64_min(), BigInt('-9223372036854775808'));
assert.strictEqual(wasm.u64_max(), BigInt('18446744073709551615'));
const i64_min = BigInt('-9223372036854775808');
const u64_max = BigInt('18446744073709551615');
const identityTestI64Values = [
BigInt('0'),
BigInt('1'),
BigInt('-1'),
i64_min,
];
for (const value of identityTestI64Values) {
assert.strictEqual(wasm.i64_rust_identity(value), value);
assert.strictEqual(wasm.i64_jsvalue_identity(value), value);
}
const identityTestU64Values = [
BigInt('0'),
BigInt('1'),
u64_max,
];
for (const value of identityTestU64Values) {
assert.strictEqual(wasm.u64_rust_identity(value), value);
assert.strictEqual(wasm.u64_jsvalue_identity(value), value);
}
assert.strictEqual(wasm.u64_rust_identity(BigInt('1') << BigInt('64')), BigInt('0'));
assert.strictEqual(wasm.i128_min_jsvalue(), BigInt('-170141183460469231731687303715884105728'));
assert.strictEqual(wasm.u128_max_jsvalue(), BigInt('340282366920938463463374607431768211455'));
assert.deepStrictEqual(wasm.u64_slice([]), new BigUint64Array());
assert.deepStrictEqual(wasm.i64_slice([]), new BigInt64Array());
const arr1 = new BigUint64Array([BigInt('1'), BigInt('2')]);
assert.deepStrictEqual(wasm.u64_slice([BigInt('1'), BigInt('2')]), arr1);
const arr2 = new BigInt64Array([BigInt('1'), BigInt('2')]);
assert.deepStrictEqual(wasm.i64_slice([BigInt('1'), BigInt('2')]), arr2);
assert.deepStrictEqual(wasm.i64_slice([i64_min]), new BigInt64Array([i64_min]));
assert.deepStrictEqual(wasm.u64_slice([u64_max]), new BigUint64Array([u64_max]));
};

View File

@@ -0,0 +1,118 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/bigint.js")]
extern "C" {
fn i64_js_identity(a: i64) -> i64;
fn u64_js_identity(a: u64) -> u64;
fn js_works();
}
#[wasm_bindgen]
pub fn zero() -> u64 {
0
}
#[wasm_bindgen]
pub fn one() -> u64 {
1
}
#[wasm_bindgen]
pub fn neg_one() -> i64 {
-1
}
#[wasm_bindgen]
pub fn i32_min() -> i64 {
i32::min_value() as i64
}
#[wasm_bindgen]
pub fn u32_max() -> u64 {
u32::max_value() as u64
}
#[wasm_bindgen]
pub fn i64_min() -> i64 {
i64::min_value()
}
#[wasm_bindgen]
pub fn u64_max() -> u64 {
u64::max_value()
}
#[wasm_bindgen]
pub fn i64_rust_identity(a: i64) -> i64 {
i64_js_identity(a)
}
#[wasm_bindgen]
pub fn u64_rust_identity(a: u64) -> u64 {
u64_js_identity(a)
}
#[wasm_bindgen]
pub fn i64_jsvalue_identity(a: i64) -> JsValue {
JsValue::from(a)
}
#[wasm_bindgen]
pub fn u64_jsvalue_identity(a: u64) -> JsValue {
JsValue::from(a)
}
#[wasm_bindgen]
pub fn i128_min_jsvalue() -> JsValue {
JsValue::from(i128::min_value())
}
#[wasm_bindgen]
pub fn u128_max_jsvalue() -> JsValue {
JsValue::from(u128::max_value())
}
#[wasm_bindgen]
pub fn i64_slice(a: &[i64]) -> Vec<i64> {
a.to_vec()
}
#[wasm_bindgen]
pub fn u64_slice(a: &[u64]) -> Vec<u64> {
a.to_vec()
}
#[wasm_bindgen_test]
fn works() {
js_works();
}
mod try_from_works {
use super::*;
use crate::JsValue;
use core::convert::TryFrom;
macro_rules! test_type_boundaries {
($($ty:ident)*) => {
$(
#[wasm_bindgen_test]
fn $ty() {
// Not a bigint.
assert!($ty::try_from(JsValue::NULL).is_err());
assert!($ty::try_from(JsValue::from_f64(0.0)).is_err());
// Within range.
assert_eq!($ty::try_from(JsValue::from($ty::MIN)), Ok($ty::MIN));
// Too small.
assert!($ty::try_from(JsValue::from($ty::MIN) - JsValue::from(1_i64)).is_err());
// Within range.
assert_eq!($ty::try_from(JsValue::from($ty::MAX)), Ok($ty::MAX));
// Too large.
assert!($ty::try_from(JsValue::from($ty::MAX) + JsValue::from(1_i64)).is_err());
}
)*
};
}
test_type_boundaries!(i64 u64 i128 u128);
}

View File

@@ -0,0 +1,17 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.js_identity = a => a;
exports.js_works = () => {
assert.strictEqual(wasm.letter(), 'a');
assert.strictEqual(wasm.face(), '😀');
assert.strictEqual(wasm.rust_identity('Ղ'), 'Ղ');
assert.strictEqual(wasm.rust_identity('ҝ'), 'ҝ');
assert.strictEqual(wasm.rust_identity('Δ'), 'Δ');
assert.strictEqual(wasm.rust_identity('䉨'), '䉨');
assert.strictEqual(wasm.rust_js_identity('a'), 'a');
assert.strictEqual(wasm.rust_js_identity('㊻'), '㊻');
wasm.rust_letter('a');
wasm.rust_face('😀');
};

View File

@@ -0,0 +1,43 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/char.js")]
extern "C" {
fn js_identity(c: char) -> char;
fn js_works();
}
#[wasm_bindgen]
pub fn rust_identity(c: char) -> char {
c
}
#[wasm_bindgen]
pub fn rust_js_identity(c: char) -> char {
js_identity(c)
}
#[wasm_bindgen]
pub fn letter() -> char {
'a'
}
#[wasm_bindgen]
pub fn face() -> char {
'😀'
}
#[wasm_bindgen]
pub fn rust_letter(a: char) {
assert_eq!(a, 'a');
}
#[wasm_bindgen]
pub fn rust_face(p: char) {
assert_eq!(p, '😀');
}
#[wasm_bindgen_test]
fn works() {
js_works();
}

View File

@@ -0,0 +1,239 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.js_simple = () => {
const r = new wasm.ClassesSimple();
assert.strictEqual(r.add(0), 0);
assert.strictEqual(r.add(1), 1);
assert.strictEqual(r.add(1), 2);
r.add(2);
assert.strictEqual(r.consume(), 4);
assert.throws(() => r.free(), /null pointer passed to rust/);
const r2 = wasm.ClassesSimple.with_contents(10);
assert.strictEqual(r2.add(1), 11);
assert.strictEqual(r2.add(2), 13);
assert.strictEqual(r2.add(3), 16);
r2.free();
const r3 = new wasm.ClassesSimple();
assert.strictEqual(r3.add(42), 42);
r3.free();
};
exports.js_strings = () => {
const r = wasm.ClassesStrings1.new();
r.set(3);
let bar = r.bar('baz');
r.free();
assert.strictEqual(bar.name(), 'foo-baz-3');
bar.free();
};
exports.js_exceptions = () => {
// this test only works when `--debug` is passed to `wasm-bindgen` (or the
// equivalent thereof)
if (require('process').env.WASM_BINDGEN_NO_DEBUG)
return;
assert.throws(() => new wasm.ClassesExceptions1(), /cannot invoke `new` directly/);
let a = wasm.ClassesExceptions1.new();
a.free();
assert.throws(() => a.free(), /null pointer passed to rust/);
let b = wasm.ClassesExceptions1.new();
b.foo(b);
assert.throws(() => b.bar(b), /recursive use of an object/);
let c = wasm.ClassesExceptions1.new();
let d = wasm.ClassesExceptions2.new();
assert.throws(() => c.foo(d), /expected instance of ClassesExceptions1/);
d.free();
c.free();
};
exports.js_pass_one_to_another = () => {
let a = wasm.ClassesPassA.new();
let b = wasm.ClassesPassB.new();
a.foo(b);
a.bar(b);
a.free();
};
exports.take_class = foo => {
assert.strictEqual(foo.inner(), 13);
foo.free();
assert.throws(() => foo.free(), /null pointer passed to rust/);
};
exports.js_constructors = () => {
const foo = new wasm.ConstructorsFoo(1);
assert.strictEqual(foo.get_number(), 1);
foo.free();
assert.strictEqual(wasm.ConstructorsBar.new, undefined);
const foo2 = new wasm.ConstructorsFoo(2);
assert.strictEqual(foo2.get_number(), 2);
foo2.free();
const bar = new wasm.ConstructorsBar(3, 4);
assert.strictEqual(bar.get_sum(), 7);
bar.free();
assert.strictEqual(wasm.ConstructorsBar.other_name, undefined);
const bar2 = new wasm.ConstructorsBar(5, 6);
assert.strictEqual(bar2.get_sum(), 11);
bar2.free();
assert.strictEqual(wasm.cross_item_construction().get_sum(), 15);
};
exports.js_empty_structs = () => {
wasm.OtherEmpty.return_a_value();
};
exports.js_public_fields = () => {
const a = wasm.PublicFields.new();
assert.strictEqual(a.a, 0);
a.a = 3;
assert.strictEqual(a.a, 3);
assert.strictEqual(a.b, 0);
a.b = 7;
assert.strictEqual(a.b, 7);
assert.strictEqual(a.c, 0);
a.c = 8;
assert.strictEqual(a.c, 8);
assert.strictEqual(a.d, 0);
a.d = 3.3;
assert.strictEqual(a.d, 3);
assert.strictEqual(a.skipped, undefined);
};
exports.js_getter_with_clone = () => {
const a = wasm.GetterWithCloneStruct.new();
assert.strictEqual(a.a, '');
a.a = 'foo';
assert.strictEqual(a.a, 'foo');
const b = wasm.GetterWithCloneStructField.new();
assert.strictEqual(b.a, '');
b.a = 'foo';
assert.strictEqual(b.a, 'foo');
};
exports.js_using_self = () => {
wasm.UseSelf.new().free();
};
exports.js_readonly_fields = () => {
const a = wasm.Readonly.new();
assert.strictEqual(a.a, 0);
a.a = 3;
assert.strictEqual(a.a, 0);
a.free();
};
exports.js_double_consume = () => {
const r = new wasm.DoubleConsume();
assert.throws(() => r.consume(r));
};
exports.js_js_rename = () => {
(new wasm.JsRename()).bar();
wasm.classes_foo();
};
exports.js_access_fields = () => {
assert.ok((new wasm.AccessFieldFoo()).bar instanceof wasm.AccessFieldBar);
assert.ok((new wasm.AccessField0())[0] instanceof wasm.AccessFieldBar);
};
exports.js_renamed_export = () => {
const x = new wasm.JsRenamedExport();
assert.ok(x.x === 3);
x.foo();
x.bar(x);
};
exports.js_renamed_field = () => {
const x = new wasm.RenamedField();
assert.ok(x.bar === 3);
x.foo();
}
exports.js_conditional_bindings = () => {
const x = new wasm.ConditionalBindings();
x.free();
};
exports.js_assert_none = x => {
assert.strictEqual(x, undefined);
};
exports.js_assert_some = x => {
assert.ok(x instanceof wasm.OptionClass);
};
exports.js_return_none1 = () => null;
exports.js_return_none2 = () => undefined;
exports.js_return_some = x => x;
exports.js_test_option_classes = () => {
assert.strictEqual(wasm.option_class_none(), undefined);
wasm.option_class_assert_none(undefined);
wasm.option_class_assert_none(null);
const c = wasm.option_class_some();
assert.ok(c instanceof wasm.OptionClass);
wasm.option_class_assert_some(c);
};
/**
* Invokes `console.log`, but logs to a string rather than stdout
* @param {any} data Data to pass to `console.log`
* @returns {string} Output from `console.log`, without color or trailing newlines
*/
const console_log_to_string = data => {
// Store the original stdout.write and create a console that logs without color
const original_write = process.stdout.write;
const colorless_console = new console.Console({
stdout: process.stdout,
colorMode: false
});
let output = '';
// Change stdout.write to append to our string, then restore the original function
process.stdout.write = chunk => output += chunk.trim();
colorless_console.log(data);
process.stdout.write = original_write;
return output;
};
exports.js_test_inspectable_classes = () => {
const inspectable = wasm.Inspectable.new();
const not_inspectable = wasm.NotInspectable.new();
// Inspectable classes have a toJSON and toString implementation generated
assert.deepStrictEqual(inspectable.toJSON(), { a: inspectable.a });
assert.strictEqual(inspectable.toString(), `{"a":${inspectable.a}}`);
// Inspectable classes in Node.js have improved console.log formatting as well
assert(console_log_to_string(inspectable).endsWith(`{ a: ${inspectable.a} }`));
// Non-inspectable classes do not have a toJSON or toString generated
assert.strictEqual(not_inspectable.toJSON, undefined);
assert.strictEqual(not_inspectable.toString(), '[object Object]');
// Non-inspectable classes in Node.js have no special console.log formatting
assert.strictEqual(console_log_to_string(not_inspectable), `NotInspectable { ptr: ${not_inspectable.ptr} }`);
inspectable.free();
not_inspectable.free();
};
exports.js_test_inspectable_classes_can_override_generated_methods = () => {
const overridden_inspectable = wasm.OverriddenInspectable.new();
// Inspectable classes can have the generated toJSON and toString overwritten
assert.strictEqual(overridden_inspectable.a, 0);
assert.deepStrictEqual(overridden_inspectable.toJSON(), 'JSON was overwritten');
assert.strictEqual(overridden_inspectable.toString(), 'string was overwritten');
overridden_inspectable.free();
};

View File

@@ -0,0 +1,610 @@
#[allow(unused_imports)] // test for #919
use std::borrow::BorrowMut;
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/classes.js")]
extern "C" {
fn js_simple();
fn js_strings();
fn js_exceptions();
fn js_pass_one_to_another();
fn take_class(foo: ClassesIntoJs);
#[wasm_bindgen(js_name = take_class)]
fn take_class_as_jsvalue(foo: JsValue);
fn js_constructors();
fn js_empty_structs();
fn js_public_fields();
fn js_getter_with_clone();
fn js_using_self();
fn js_readonly_fields();
fn js_double_consume();
fn js_js_rename();
fn js_access_fields();
fn js_renamed_export();
fn js_renamed_field();
fn js_conditional_bindings();
fn js_assert_none(a: Option<OptionClass>);
fn js_assert_some(a: Option<OptionClass>);
fn js_return_none1() -> Option<OptionClass>;
fn js_return_none2() -> Option<OptionClass>;
fn js_return_some(a: OptionClass) -> Option<OptionClass>;
fn js_test_option_classes();
fn js_test_inspectable_classes();
fn js_test_inspectable_classes_can_override_generated_methods();
}
#[wasm_bindgen_test]
fn simple() {
js_simple();
}
#[wasm_bindgen]
pub struct ClassesSimple {
contents: u32,
}
#[wasm_bindgen]
impl ClassesSimple {
#[wasm_bindgen(constructor)]
pub fn new() -> ClassesSimple {
ClassesSimple::with_contents(0)
}
pub fn with_contents(a: u32) -> ClassesSimple {
ClassesSimple { contents: a }
}
pub fn add(&mut self, amt: u32) -> u32 {
self.contents += amt;
self.contents
}
pub fn consume(self) -> u32 {
self.contents
}
}
#[wasm_bindgen_test]
fn strings() {
js_strings()
}
#[wasm_bindgen]
pub struct ClassesStrings1 {
name: u32,
}
#[wasm_bindgen]
pub struct ClassesStrings2 {
contents: String,
}
#[wasm_bindgen]
impl ClassesStrings1 {
pub fn new() -> ClassesStrings1 {
ClassesStrings1 { name: 0 }
}
pub fn set(&mut self, amt: u32) {
self.name = amt;
}
pub fn bar(&self, mix: &str) -> ClassesStrings2 {
ClassesStrings2 {
contents: format!("foo-{}-{}", mix, self.name),
}
}
}
#[wasm_bindgen]
impl ClassesStrings2 {
pub fn name(&self) -> String {
self.contents.clone()
}
}
#[wasm_bindgen_test]
fn exceptions() {
js_exceptions();
}
#[wasm_bindgen]
pub struct ClassesExceptions1 {}
#[wasm_bindgen]
impl ClassesExceptions1 {
pub fn new() -> ClassesExceptions1 {
ClassesExceptions1 {}
}
pub fn foo(&self, _: &ClassesExceptions1) {}
pub fn bar(&mut self, _: &mut ClassesExceptions1) {}
}
#[wasm_bindgen]
pub struct ClassesExceptions2 {}
#[wasm_bindgen]
impl ClassesExceptions2 {
pub fn new() -> ClassesExceptions2 {
ClassesExceptions2 {}
}
}
#[wasm_bindgen_test]
fn pass_one_to_another() {
js_pass_one_to_another();
}
#[wasm_bindgen]
pub struct ClassesPassA {}
#[wasm_bindgen]
impl ClassesPassA {
pub fn new() -> ClassesPassA {
ClassesPassA {}
}
pub fn foo(&self, _other: &ClassesPassB) {}
pub fn bar(&self, _other: ClassesPassB) {}
}
#[wasm_bindgen]
pub struct ClassesPassB {}
#[wasm_bindgen]
impl ClassesPassB {
pub fn new() -> ClassesPassB {
ClassesPassB {}
}
}
#[wasm_bindgen_test]
fn pass_into_js() {
take_class(ClassesIntoJs(13));
}
#[wasm_bindgen]
pub struct ClassesIntoJs(i32);
#[wasm_bindgen]
impl ClassesIntoJs {
pub fn inner(&self) -> i32 {
self.0
}
}
#[wasm_bindgen]
pub struct Issue27Context {}
#[wasm_bindgen]
impl Issue27Context {
pub fn parse(&self, _expr: &str) -> Issue27Expr {
panic!()
}
pub fn eval(&self, _expr: &Issue27Expr) -> f64 {
panic!()
}
pub fn set(&mut self, _var: &str, _val: f64) {
panic!()
}
}
#[wasm_bindgen]
pub struct Issue27Expr {}
#[wasm_bindgen_test]
fn pass_into_js_as_js_class() {
take_class_as_jsvalue(ClassesIntoJs(13).into());
}
#[wasm_bindgen_test]
fn constructors() {
js_constructors();
}
#[wasm_bindgen]
pub fn cross_item_construction() -> ConstructorsBar {
ConstructorsBar::other_name(7, 8)
}
#[wasm_bindgen]
pub struct ConstructorsFoo {
number: u32,
}
#[wasm_bindgen]
impl ConstructorsFoo {
#[wasm_bindgen(constructor)]
pub fn new(number: u32) -> ConstructorsFoo {
ConstructorsFoo { number }
}
pub fn get_number(&self) -> u32 {
self.number
}
}
#[wasm_bindgen]
pub struct ConstructorsBar {
number: u32,
number2: u32,
}
#[wasm_bindgen]
impl ConstructorsBar {
#[wasm_bindgen(constructor)]
pub fn other_name(number: u32, number2: u32) -> ConstructorsBar {
ConstructorsBar { number, number2 }
}
pub fn get_sum(&self) -> u32 {
self.number + self.number2
}
}
#[wasm_bindgen_test]
fn empty_structs() {
js_empty_structs();
}
#[wasm_bindgen]
pub struct MissingClass {}
#[wasm_bindgen]
pub struct OtherEmpty {}
#[wasm_bindgen]
impl OtherEmpty {
pub fn return_a_value() -> MissingClass {
MissingClass {}
}
}
#[wasm_bindgen_test]
fn public_fields() {
js_public_fields();
}
#[wasm_bindgen]
#[derive(Default)]
pub struct PublicFields {
pub a: u32,
pub b: f32,
pub c: f64,
pub d: i32,
#[wasm_bindgen(skip)]
pub skipped: u32,
}
#[wasm_bindgen]
impl PublicFields {
pub fn new() -> PublicFields {
PublicFields::default()
}
}
#[wasm_bindgen_test]
fn getter_with_clone() {
js_getter_with_clone();
}
#[wasm_bindgen(getter_with_clone)]
#[derive(Default)]
pub struct GetterWithCloneStruct {
pub a: String,
}
#[wasm_bindgen]
impl GetterWithCloneStruct {
pub fn new() -> GetterWithCloneStruct {
GetterWithCloneStruct::default()
}
}
#[wasm_bindgen]
#[derive(Default)]
pub struct GetterWithCloneStructField {
#[wasm_bindgen(getter_with_clone)]
pub a: String,
}
#[wasm_bindgen]
impl GetterWithCloneStructField {
pub fn new() -> GetterWithCloneStructField {
GetterWithCloneStructField::default()
}
}
#[wasm_bindgen_test]
fn using_self() {
js_using_self();
}
#[wasm_bindgen]
pub struct UseSelf {}
#[wasm_bindgen]
impl UseSelf {
pub fn new() -> Self {
UseSelf {}
}
}
#[wasm_bindgen_test]
fn readonly_fields() {
js_readonly_fields();
}
#[wasm_bindgen]
#[derive(Default)]
pub struct Readonly {
#[wasm_bindgen(readonly)]
pub a: u32,
}
#[wasm_bindgen]
impl Readonly {
pub fn new() -> Readonly {
Readonly::default()
}
}
#[wasm_bindgen_test]
fn double_consume() {
js_double_consume();
}
#[wasm_bindgen]
pub struct DoubleConsume {}
#[wasm_bindgen]
impl DoubleConsume {
#[wasm_bindgen(constructor)]
pub fn new() -> DoubleConsume {
DoubleConsume {}
}
pub fn consume(self, other: DoubleConsume) {
drop(other);
}
}
#[wasm_bindgen_test]
fn rename_function_for_js() {
js_js_rename();
foo();
}
#[wasm_bindgen]
pub struct JsRename {}
#[wasm_bindgen]
impl JsRename {
#[wasm_bindgen(constructor)]
pub fn new() -> JsRename {
let f = JsRename {};
f.foo();
f
}
#[wasm_bindgen(js_name = bar)]
pub fn foo(&self) {}
}
#[wasm_bindgen(js_name = classes_foo)]
pub fn foo() {}
#[wasm_bindgen]
pub struct AccessFieldFoo {
pub bar: AccessFieldBar,
}
#[wasm_bindgen]
pub struct AccessField0(pub AccessFieldBar);
#[wasm_bindgen]
#[derive(Copy, Clone)]
pub struct AccessFieldBar {
_value: u32,
}
#[wasm_bindgen]
impl AccessFieldFoo {
#[wasm_bindgen(constructor)]
pub fn new() -> AccessFieldFoo {
AccessFieldFoo {
bar: AccessFieldBar { _value: 2 },
}
}
}
#[wasm_bindgen]
impl AccessField0 {
#[wasm_bindgen(constructor)]
pub fn new() -> AccessField0 {
AccessField0(AccessFieldBar { _value: 2 })
}
}
#[wasm_bindgen_test]
fn access_fields() {
js_access_fields();
}
#[wasm_bindgen(js_name = JsRenamedExport)]
pub struct RenamedExport {
pub x: u32,
}
#[wasm_bindgen(js_class = JsRenamedExport)]
impl RenamedExport {
#[wasm_bindgen(constructor)]
pub fn new() -> RenamedExport {
RenamedExport { x: 3 }
}
pub fn foo(&self) {}
pub fn bar(&self, other: &RenamedExport) {
drop(other);
}
}
#[wasm_bindgen_test]
fn renamed_export() {
js_renamed_export();
}
#[wasm_bindgen]
pub struct RenamedField {
#[wasm_bindgen(js_name = bar)]
pub foo: u32,
}
#[wasm_bindgen(js_class = RenamedField)]
impl RenamedField {
#[wasm_bindgen(constructor)]
pub fn new() -> RenamedField {
RenamedField { foo: 3 }
}
pub fn foo(&self) {}
}
#[wasm_bindgen_test]
fn renamed_field() {
js_renamed_field();
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
pub struct ConditionalBindings {}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
impl ConditionalBindings {
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(constructor))]
pub fn new() -> ConditionalBindings {
ConditionalBindings {}
}
}
#[wasm_bindgen_test]
fn conditional_bindings() {
js_conditional_bindings();
}
#[wasm_bindgen]
pub struct OptionClass(u32);
#[wasm_bindgen_test]
fn option_class() {
js_assert_none(None);
js_assert_some(Some(OptionClass(1)));
assert!(js_return_none1().is_none());
assert!(js_return_none2().is_none());
assert_eq!(js_return_some(OptionClass(2)).unwrap().0, 2);
js_test_option_classes();
}
#[wasm_bindgen]
pub fn option_class_none() -> Option<OptionClass> {
None
}
#[wasm_bindgen]
pub fn option_class_some() -> Option<OptionClass> {
Some(OptionClass(3))
}
#[wasm_bindgen]
pub fn option_class_assert_none(x: Option<OptionClass>) {
assert!(x.is_none());
}
#[wasm_bindgen]
pub fn option_class_assert_some(x: Option<OptionClass>) {
assert_eq!(x.unwrap().0, 3);
}
mod works_in_module {
use wasm_bindgen::prelude::wasm_bindgen;
#[wasm_bindgen]
pub struct WorksInModule(u32);
#[wasm_bindgen]
impl WorksInModule {
#[wasm_bindgen(constructor)]
pub fn new() -> WorksInModule {
WorksInModule(1)
}
pub fn foo(&self) {}
}
}
#[wasm_bindgen_test]
fn inspectable_classes() {
js_test_inspectable_classes();
}
#[wasm_bindgen(inspectable)]
#[derive(Default)]
pub struct Inspectable {
pub a: u32,
// This private field will not be exposed unless a getter is provided for it
#[allow(dead_code)]
private: u32,
}
#[wasm_bindgen]
impl Inspectable {
pub fn new() -> Self {
Self::default()
}
}
#[wasm_bindgen]
#[derive(Default)]
pub struct NotInspectable {
pub a: u32,
}
#[wasm_bindgen]
impl NotInspectable {
pub fn new() -> Self {
Self::default()
}
}
#[wasm_bindgen_test]
fn inspectable_classes_can_override_generated_methods() {
js_test_inspectable_classes_can_override_generated_methods();
}
#[wasm_bindgen(inspectable)]
#[derive(Default)]
pub struct OverriddenInspectable {
pub a: u32,
}
#[wasm_bindgen]
impl OverriddenInspectable {
pub fn new() -> Self {
Self::default()
}
#[wasm_bindgen(js_name = toJSON)]
pub fn to_json(&self) -> String {
String::from("JSON was overwritten")
}
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String {
String::from("string was overwritten")
}
}

View File

@@ -0,0 +1,164 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
exports.works_call = a => {
a();
};
exports.works_thread = a => a(2);
let CANNOT_REUSE_CACHE = null;
exports.cannot_reuse_call = a => {
CANNOT_REUSE_CACHE = a;
};
exports.cannot_reuse_call_again = () => {
CANNOT_REUSE_CACHE();
};
exports.long_lived_call1 = a => {
a();
};
exports.long_lived_call2 = a => a(2);
exports.many_arity_call1 = a => {
a();
};
exports.many_arity_call2 = a => {
a(1);
};
exports.many_arity_call3 = a => {
a(1, 2);
};
exports.many_arity_call4 = a => {
a(1, 2, 3);
};
exports.many_arity_call5 = a => {
a(1, 2, 3, 4);
};
exports.many_arity_call6 = a => {
a(1, 2, 3, 4, 5);
};
exports.many_arity_call7 = a => {
a(1, 2, 3, 4, 5, 6);
};
exports.many_arity_call8 = a => {
a(1, 2, 3, 4, 5, 6, 7);
};
exports.many_arity_call9 = a => {
a(1, 2, 3, 4, 5, 6, 7, 8);
};
exports.option_call1 = a => {
if (a) {
a();
}
};
exports.option_call2 = a => {
if (a) {
return a(2);
}
};
exports.option_call3 = a => a == undefined;
let LONG_LIVED_DROPPING_CACHE = null;
exports.long_lived_dropping_cache = a => {
LONG_LIVED_DROPPING_CACHE = a;
};
exports.long_lived_dropping_call = () => {
LONG_LIVED_DROPPING_CACHE();
};
let LONG_LIVED_OPTION_DROPPING_CACHE = null;
exports.long_lived_option_dropping_cache = a => {
if (a) {
LONG_LIVED_OPTION_DROPPING_CACHE = a;
return true;
} else {
return false;
}
}
exports.long_lived_option_dropping_call = () => {
LONG_LIVED_OPTION_DROPPING_CACHE();
}
let LONG_FNMUT_RECURSIVE_CACHE = null;
exports.long_fnmut_recursive_cache = a => {
LONG_FNMUT_RECURSIVE_CACHE = a;
};
exports.long_fnmut_recursive_call = () => {
LONG_FNMUT_RECURSIVE_CACHE();
};
exports.fnmut_call = a => {
a();
};
exports.fnmut_thread = a => a(2);
let FNMUT_BAD_F = null;
exports.fnmut_bad_call = a => {
FNMUT_BAD_F = a;
a();
};
exports.fnmut_bad_again = x => {
if (x) {
FNMUT_BAD_F();
}
};
exports.string_arguments_call = a => {
a('foo');
};
exports.string_ret_call = a => {
assert.strictEqual(a('foo'), 'foobar');
};
let DROP_DURING_CALL = null;
exports.drop_during_call_save = f => {
DROP_DURING_CALL = f;
};
exports.drop_during_call_call = () => DROP_DURING_CALL();
exports.js_test_closure_returner = () => {
wasm.closure_returner().someKey();
};
exports.calling_it_throws = a => {
try {
a();
return false;
} catch(_) {
return true;
}
};
exports.call_val = f => f();
exports.pass_reference_first_arg_twice = (a, b, c) => {
b(a);
c(a);
a.free();
};
exports.call_destroyed = f => {
assert.throws(f, /invoked recursively or destroyed/);
};
let FORGOTTEN_CLOSURE = null;
exports.js_store_forgotten_closure = f => {
FORGOTTEN_CLOSURE = f;
};
exports.js_call_forgotten_closure = () => {
FORGOTTEN_CLOSURE();
};

View File

@@ -0,0 +1,645 @@
use js_sys::Number;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/closures.js")]
extern "C" {
fn works_call(a: &dyn Fn());
fn works_thread(a: &dyn Fn(u32) -> u32) -> u32;
fn cannot_reuse_call(a: &dyn Fn());
#[wasm_bindgen(catch)]
fn cannot_reuse_call_again() -> Result<(), JsValue>;
fn long_lived_call1(a: &Closure<dyn Fn()>);
fn long_lived_call2(a: &Closure<dyn FnMut(u32) -> u32>) -> u32;
fn many_arity_call1(a: &Closure<dyn Fn()>);
fn many_arity_call2(a: &Closure<dyn Fn(u32)>);
fn many_arity_call3(a: &Closure<dyn Fn(u32, u32)>);
fn many_arity_call4(a: &Closure<dyn Fn(u32, u32, u32)>);
fn many_arity_call5(a: &Closure<dyn Fn(u32, u32, u32, u32)>);
fn many_arity_call6(a: &Closure<dyn Fn(u32, u32, u32, u32, u32)>);
fn many_arity_call7(a: &Closure<dyn Fn(u32, u32, u32, u32, u32, u32)>);
fn many_arity_call8(a: &Closure<dyn Fn(u32, u32, u32, u32, u32, u32, u32)>);
fn many_arity_call9(a: &Closure<dyn Fn(u32, u32, u32, u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call1)]
fn many_arity_call_mut1(a: &Closure<dyn FnMut()>);
#[wasm_bindgen(js_name = many_arity_call2)]
fn many_arity_call_mut2(a: &Closure<dyn FnMut(u32)>);
#[wasm_bindgen(js_name = many_arity_call3)]
fn many_arity_call_mut3(a: &Closure<dyn FnMut(u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call4)]
fn many_arity_call_mut4(a: &Closure<dyn FnMut(u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call5)]
fn many_arity_call_mut5(a: &Closure<dyn FnMut(u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call6)]
fn many_arity_call_mut6(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call7)]
fn many_arity_call_mut7(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call8)]
fn many_arity_call_mut8(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32, u32, u32)>);
#[wasm_bindgen(js_name = many_arity_call9)]
fn many_arity_call_mut9(a: &Closure<dyn FnMut(u32, u32, u32, u32, u32, u32, u32, u32)>);
fn option_call1(a: Option<&Closure<dyn Fn()>>);
fn option_call2(a: Option<&Closure<dyn FnMut(u32) -> u32>>) -> u32;
fn option_call3(a: Option<&Closure<dyn Fn()>>) -> bool;
#[wasm_bindgen(js_name = many_arity_call1)]
fn many_arity_stack1(a: &dyn Fn());
#[wasm_bindgen(js_name = many_arity_call2)]
fn many_arity_stack2(a: &dyn Fn(u32));
#[wasm_bindgen(js_name = many_arity_call3)]
fn many_arity_stack3(a: &dyn Fn(u32, u32));
#[wasm_bindgen(js_name = many_arity_call4)]
fn many_arity_stack4(a: &dyn Fn(u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call5)]
fn many_arity_stack5(a: &dyn Fn(u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call6)]
fn many_arity_stack6(a: &dyn Fn(u32, u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call7)]
fn many_arity_stack7(a: &dyn Fn(u32, u32, u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call8)]
fn many_arity_stack8(a: &dyn Fn(u32, u32, u32, u32, u32, u32, u32));
#[wasm_bindgen(js_name = many_arity_call9)]
fn many_arity_stack9(a: &dyn Fn(u32, u32, u32, u32, u32, u32, u32, u32));
fn long_lived_dropping_cache(a: &Closure<dyn Fn()>);
#[wasm_bindgen(catch)]
fn long_lived_dropping_call() -> Result<(), JsValue>;
fn long_lived_option_dropping_cache(a: Option<&Closure<dyn Fn()>>) -> bool;
#[wasm_bindgen(catch)]
fn long_lived_option_dropping_call() -> Result<(), JsValue>;
fn long_fnmut_recursive_cache(a: &Closure<dyn FnMut()>);
#[wasm_bindgen(catch)]
fn long_fnmut_recursive_call() -> Result<(), JsValue>;
fn fnmut_call(a: &mut dyn FnMut());
fn fnmut_thread(a: &mut dyn FnMut(u32) -> u32) -> u32;
fn fnmut_bad_call(a: &mut dyn FnMut());
#[wasm_bindgen(catch)]
fn fnmut_bad_again(a: bool) -> Result<(), JsValue>;
fn string_arguments_call(a: &mut dyn FnMut(String));
fn string_ret_call(a: &mut dyn FnMut(String) -> String);
fn drop_during_call_save(a: &Closure<dyn Fn()>);
fn drop_during_call_call();
fn js_test_closure_returner();
fn calling_it_throws(a: &Closure<dyn FnMut()>) -> bool;
fn call_val(f: &JsValue);
#[wasm_bindgen(js_name = calling_it_throws)]
fn call_val_throws(f: &JsValue) -> bool;
fn pass_reference_first_arg_twice(
a: RefFirstArgument,
b: &Closure<dyn FnMut(&RefFirstArgument)>,
c: &Closure<dyn FnMut(&RefFirstArgument)>,
);
#[wasm_bindgen(js_name = pass_reference_first_arg_twice)]
fn pass_reference_first_arg_twice2(
a: RefFirstArgument,
b: &mut dyn FnMut(&RefFirstArgument),
c: &mut dyn FnMut(&RefFirstArgument),
);
fn call_destroyed(a: &JsValue);
fn js_store_forgotten_closure(closure: &Closure<dyn Fn()>);
fn js_call_forgotten_closure();
#[wasm_bindgen(js_name = many_arity_call2)]
fn externref_call(a: &Closure<dyn Fn(JsValue)>);
#[wasm_bindgen(js_name = many_arity_call2)]
fn named_externref_call(a: &Closure<dyn Fn(Number)>);
}
#[wasm_bindgen_test]
fn works() {
let a = Cell::new(false);
works_call(&|| a.set(true));
assert!(a.get());
assert_eq!(works_thread(&|a| a + 1), 3);
}
#[wasm_bindgen_test]
fn cannot_reuse() {
cannot_reuse_call(&|| {});
assert!(cannot_reuse_call_again().is_err());
}
#[wasm_bindgen_test]
fn debug() {
let closure = Closure::wrap(Box::new(|| {}) as Box<dyn FnMut()>);
assert_eq!(&format!("{:?}", closure), "Closure { ... }");
}
#[wasm_bindgen_test]
fn long_lived() {
let hit = Rc::new(Cell::new(false));
let hit2 = hit.clone();
let a = Closure::new(move || hit2.set(true));
assert!(!hit.get());
long_lived_call1(&a);
assert!(hit.get());
let hit = Rc::new(Cell::new(false));
{
let hit = hit.clone();
let a = Closure::new(move |x| {
hit.set(true);
x + 3
});
assert_eq!(long_lived_call2(&a), 5);
}
assert!(hit.get());
}
#[wasm_bindgen_test]
fn many_arity() {
many_arity_call1(&Closure::new(|| {}));
many_arity_call2(&Closure::new(|a| assert_eq!(a, 1)));
many_arity_call3(&Closure::new(|a, b| assert_eq!((a, b), (1, 2))));
many_arity_call4(&Closure::new(|a, b, c| assert_eq!((a, b, c), (1, 2, 3))));
many_arity_call5(&Closure::new(|a, b, c, d| {
assert_eq!((a, b, c, d), (1, 2, 3, 4))
}));
many_arity_call6(&Closure::new(|a, b, c, d, e| {
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5))
}));
many_arity_call7(&Closure::new(|a, b, c, d, e, f| {
assert_eq!((a, b, c, d, e, f), (1, 2, 3, 4, 5, 6))
}));
many_arity_call8(&Closure::new(|a, b, c, d, e, f, g| {
assert_eq!((a, b, c, d, e, f, g), (1, 2, 3, 4, 5, 6, 7))
}));
many_arity_call9(&Closure::new(|a, b, c, d, e, f, g, h| {
assert_eq!((a, b, c, d, e, f, g, h), (1, 2, 3, 4, 5, 6, 7, 8))
}));
let s = String::new();
many_arity_call_mut1(&Closure::once(move || drop(s)));
let s = String::new();
many_arity_call_mut2(&Closure::once(move |a| {
drop(s);
assert_eq!(a, 1);
}));
let s = String::new();
many_arity_call_mut3(&Closure::once(move |a, b| {
drop(s);
assert_eq!((a, b), (1, 2));
}));
let s = String::new();
many_arity_call_mut4(&Closure::once(move |a, b, c| {
drop(s);
assert_eq!((a, b, c), (1, 2, 3));
}));
let s = String::new();
many_arity_call_mut5(&Closure::once(move |a, b, c, d| {
drop(s);
assert_eq!((a, b, c, d), (1, 2, 3, 4));
}));
let s = String::new();
many_arity_call_mut6(&Closure::once(move |a, b, c, d, e| {
drop(s);
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
}));
let s = String::new();
many_arity_call_mut7(&Closure::once(move |a, b, c, d, e, f| {
drop(s);
assert_eq!((a, b, c, d, e, f), (1, 2, 3, 4, 5, 6));
}));
let s = String::new();
many_arity_call_mut8(&Closure::once(move |a, b, c, d, e, f, g| {
drop(s);
assert_eq!((a, b, c, d, e, f, g), (1, 2, 3, 4, 5, 6, 7));
}));
let s = String::new();
many_arity_call_mut9(&Closure::once(move |a, b, c, d, e, f, g, h| {
drop(s);
assert_eq!((a, b, c, d, e, f, g, h), (1, 2, 3, 4, 5, 6, 7, 8));
}));
many_arity_stack1(&(|| {}));
many_arity_stack2(&(|a| assert_eq!(a, 1)));
many_arity_stack3(&(|a, b| assert_eq!((a, b), (1, 2))));
many_arity_stack4(&(|a, b, c| assert_eq!((a, b, c), (1, 2, 3))));
many_arity_stack5(&(|a, b, c, d| assert_eq!((a, b, c, d), (1, 2, 3, 4))));
many_arity_stack6(&(|a, b, c, d, e| assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5))));
many_arity_stack7(&(|a, b, c, d, e, f| assert_eq!((a, b, c, d, e, f), (1, 2, 3, 4, 5, 6))));
many_arity_stack8(
&(|a, b, c, d, e, f, g| assert_eq!((a, b, c, d, e, f, g), (1, 2, 3, 4, 5, 6, 7))),
);
many_arity_stack9(
&(|a, b, c, d, e, f, g, h| assert_eq!((a, b, c, d, e, f, g, h), (1, 2, 3, 4, 5, 6, 7, 8))),
);
}
#[wasm_bindgen_test]
fn option() {
let hit = Rc::new(Cell::new(false));
let hit2 = hit.clone();
let a = Closure::new(move || hit2.set(true));
assert!(!hit.get());
option_call1(Some(&a));
assert!(hit.get());
let hit = Rc::new(Cell::new(false));
{
let hit = hit.clone();
let a = Closure::new(move |x| {
hit.set(true);
x + 3
});
assert_eq!(option_call2(Some(&a)), 5);
}
assert!(hit.get());
assert!(option_call3(None));
}
struct Dropper(Rc<Cell<bool>>);
impl Drop for Dropper {
fn drop(&mut self) {
assert!(!self.0.get());
self.0.set(true);
}
}
#[wasm_bindgen_test]
fn call_fn_once_twice() {
let dropped = Rc::new(Cell::new(false));
let dropper = Dropper(dropped.clone());
let called = Rc::new(Cell::new(false));
let c = Closure::once({
let called = called.clone();
move || {
assert!(!called.get());
called.set(true);
drop(dropper);
}
});
many_arity_call_mut1(&c);
assert!(called.get());
assert!(dropped.get());
assert!(calling_it_throws(&c));
}
#[wasm_bindgen_test]
fn once_into_js() {
let dropped = Rc::new(Cell::new(false));
let dropper = Dropper(dropped.clone());
let called = Rc::new(Cell::new(false));
let f = Closure::once_into_js({
let called = called.clone();
move || {
assert!(!called.get());
called.set(true);
drop(dropper);
}
});
call_val(&f);
assert!(called.get());
assert!(dropped.get());
assert!(call_val_throws(&f));
}
#[wasm_bindgen_test]
fn long_lived_dropping() {
let hit = Rc::new(Cell::new(false));
let hit2 = hit.clone();
let a = Closure::new(move || hit2.set(true));
long_lived_dropping_cache(&a);
assert!(!hit.get());
assert!(long_lived_dropping_call().is_ok());
assert!(hit.get());
drop(a);
assert!(long_lived_dropping_call().is_err());
}
#[wasm_bindgen_test]
fn long_lived_option_dropping() {
let hit = Rc::new(Cell::new(false));
let hit2 = hit.clone();
let a = Closure::new(move || hit2.set(true));
assert!(!long_lived_option_dropping_cache(None));
assert!(long_lived_option_dropping_cache(Some(&a)));
assert!(!hit.get());
assert!(long_lived_option_dropping_call().is_ok());
assert!(hit.get());
drop(a);
assert!(long_lived_option_dropping_call().is_err());
}
#[wasm_bindgen_test]
fn long_fnmut_recursive() {
let a = Closure::new(|| {
assert!(long_fnmut_recursive_call().is_err());
});
long_fnmut_recursive_cache(&a);
assert!(long_fnmut_recursive_call().is_ok());
}
#[wasm_bindgen_test]
fn fnmut() {
let mut a = false;
fnmut_call(&mut || a = true);
assert!(a);
let mut x = false;
assert_eq!(
fnmut_thread(&mut |a| {
x = true;
a + 1
}),
3
);
assert!(x);
}
#[wasm_bindgen_test]
fn fnmut_bad() {
let mut x = true;
let mut hits = 0;
fnmut_bad_call(&mut || {
hits += 1;
if fnmut_bad_again(hits == 1).is_err() {
return;
}
x = false;
});
assert_eq!(hits, 1);
assert!(x);
assert!(fnmut_bad_again(true).is_err());
}
#[wasm_bindgen_test]
fn string_arguments() {
let mut x = false;
string_arguments_call(&mut |s| {
assert_eq!(s, "foo");
x = true;
});
assert!(x);
}
#[wasm_bindgen_test]
fn string_ret() {
let mut x = false;
string_ret_call(&mut |mut s| {
assert_eq!(s, "foo");
s.push_str("bar");
x = true;
s
});
assert!(x);
}
#[wasm_bindgen_test]
fn drop_drops() {
static mut HIT: bool = false;
struct A;
impl Drop for A {
fn drop(&mut self) {
unsafe {
HIT = true;
}
}
}
let a = A;
let x: Closure<dyn Fn()> = Closure::new(move || drop(&a));
drop(x);
unsafe {
assert!(HIT);
}
}
#[wasm_bindgen_test]
fn drop_during_call_ok() {
static mut HIT: bool = false;
struct A;
impl Drop for A {
fn drop(&mut self) {
unsafe {
HIT = true;
}
}
}
let rc = Rc::new(RefCell::new(None));
let rc2 = rc.clone();
let x = 3;
let a = A;
let x: Closure<dyn Fn()> = Closure::new(move || {
// "drop ourselves"
drop(rc2.borrow_mut().take().unwrap());
// `A` should not have been destroyed as a result
unsafe {
assert!(!HIT);
}
// allocate some heap memory to try to paper over our `3`
drop(String::from("1234567890"));
// make sure our closure memory is still valid
assert_eq!(x, 3);
// make sure `A` is bound to our closure environment.
drop(&a);
unsafe {
assert!(!HIT);
}
});
drop_during_call_save(&x);
*rc.borrow_mut() = Some(x);
drop(rc);
unsafe {
assert!(!HIT);
}
drop_during_call_call();
unsafe {
assert!(HIT);
}
}
#[wasm_bindgen_test]
fn test_closure_returner() {
type ClosureType = dyn FnMut() -> BadStruct;
use js_sys::{Object, Reflect};
use wasm_bindgen::JsCast;
js_test_closure_returner();
#[wasm_bindgen]
pub struct ClosureHandle(Closure<ClosureType>);
#[wasm_bindgen]
pub struct BadStruct {}
#[wasm_bindgen]
pub fn closure_returner() -> Result<Object, JsValue> {
let o = Object::new();
let some_fn = Closure::wrap(Box::new(move || BadStruct {}) as Box<ClosureType>);
Reflect::set(
&o,
&JsValue::from("someKey"),
&some_fn.as_ref().unchecked_ref(),
)
.unwrap();
Reflect::set(
&o,
&JsValue::from("handle"),
&JsValue::from(ClosureHandle(some_fn)),
)
.unwrap();
Ok(o)
}
}
#[wasm_bindgen]
pub struct RefFirstArgument {
contents: u32,
}
#[wasm_bindgen_test]
fn reference_as_first_argument_builds_at_all() {
#[wasm_bindgen]
extern "C" {
fn ref_first_arg1(a: &dyn Fn(&JsValue));
fn ref_first_arg2(a: &mut dyn FnMut(&JsValue));
fn ref_first_arg3(a: &Closure<dyn Fn(&JsValue)>);
fn ref_first_arg4(a: &Closure<dyn FnMut(&JsValue)>);
fn ref_first_custom1(a: &dyn Fn(&RefFirstArgument));
fn ref_first_custom2(a: &mut dyn FnMut(&RefFirstArgument));
fn ref_first_custom3(a: &Closure<dyn Fn(&RefFirstArgument)>);
fn ref_first_custom4(a: &Closure<dyn FnMut(&RefFirstArgument)>);
}
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<dyn Fn(&JsValue)>);
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<dyn FnMut(&JsValue)>);
Closure::once(|_: &JsValue| ());
Closure::once_into_js(|_: &JsValue| ());
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<dyn Fn(&RefFirstArgument)>);
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<dyn FnMut(&RefFirstArgument)>);
Closure::once(|_: &RefFirstArgument| ());
Closure::once_into_js(|_: &RefFirstArgument| ());
}
#[wasm_bindgen_test]
fn reference_as_first_argument_works() {
let a = Rc::new(Cell::new(0));
let b = {
let a = a.clone();
Closure::once(move |x: &RefFirstArgument| {
assert_eq!(a.get(), 0);
assert_eq!(x.contents, 3);
a.set(a.get() + 1);
})
};
let c = {
let a = a.clone();
Closure::once(move |x: &RefFirstArgument| {
assert_eq!(a.get(), 1);
assert_eq!(x.contents, 3);
a.set(a.get() + 1);
})
};
pass_reference_first_arg_twice(RefFirstArgument { contents: 3 }, &b, &c);
assert_eq!(a.get(), 2);
}
#[wasm_bindgen_test]
fn reference_as_first_argument_works2() {
let a = Cell::new(0);
pass_reference_first_arg_twice2(
RefFirstArgument { contents: 3 },
&mut |x: &RefFirstArgument| {
assert_eq!(a.get(), 0);
assert_eq!(x.contents, 3);
a.set(a.get() + 1);
},
&mut |x: &RefFirstArgument| {
assert_eq!(a.get(), 1);
assert_eq!(x.contents, 3);
a.set(a.get() + 1);
},
);
assert_eq!(a.get(), 2);
}
#[wasm_bindgen_test]
fn call_destroyed_doesnt_segfault() {
struct A(i32, i32);
impl Drop for A {
fn drop(&mut self) {
assert_eq!(self.0, self.1);
}
}
let a = A(1, 1);
let a = Closure::wrap(Box::new(move || drop(&a)) as Box<dyn Fn()>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
let a = A(2, 2);
let a = Closure::wrap(Box::new(move || drop(&a)) as Box<dyn FnMut()>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
let a = A(1, 1);
let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box<dyn Fn(&JsValue)>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
let a = A(2, 2);
let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box<dyn FnMut(&JsValue)>);
let b = a.as_ref().clone();
drop(a);
call_destroyed(&b);
}
#[wasm_bindgen_test]
fn forget_works() {
let a = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
js_store_forgotten_closure(&a);
a.forget();
js_call_forgotten_closure();
}
#[wasm_bindgen_test]
fn named_externref_no_duplicate_adapter() {
externref_call(&Closure::new(|a| assert_eq!(a, 1)));
named_externref_call(&Closure::new(|a| assert_eq!(a, 1)));
}

View File

@@ -0,0 +1,19 @@
const fs = require('fs');
const assert = require('assert');
exports.assert_comments_exist = function() {
const bindings_file = require.resolve('wasm-bindgen-test');
const contents = fs.readFileSync(bindings_file);
assert.ok(contents.includes("* annotated function ✔️ \" \\ ' {"));
assert.ok(contents.includes("* annotated struct type"));
assert.ok(contents.includes("* annotated struct field b"));
assert.ok(contents.includes("* annotated struct field c"));
assert.ok(contents.includes("* annotated struct constructor"));
assert.ok(contents.includes("* annotated struct method"));
assert.ok(contents.includes("* annotated struct getter"));
assert.ok(contents.includes("* annotated struct setter"));
assert.ok(contents.includes("* annotated struct static method"));
assert.ok(contents.includes("* annotated enum type"));
assert.ok(contents.includes("* annotated enum variant 1"));
assert.ok(contents.includes("* annotated enum variant 2"));
};

View File

@@ -0,0 +1,73 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/comments.js")]
extern "C" {
fn assert_comments_exist();
}
/// annotated function ✔️ " \ ' {
#[wasm_bindgen]
pub fn annotated() -> String {
String::new()
}
/// annotated struct type
#[wasm_bindgen]
pub struct Annotated {
a: String,
/// annotated struct field b
pub b: u32,
/// annotated struct field c
#[wasm_bindgen(readonly)]
pub c: u32,
d: u32,
}
#[wasm_bindgen]
impl Annotated {
/// annotated struct constructor
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self {
a: String::new(),
b: 0,
c: 0,
d: 0,
}
}
/// annotated struct method
pub fn get_a(&self) -> String {
self.a.clone()
}
/// annotated struct getter
#[wasm_bindgen(getter)]
pub fn d(&self) -> u32 {
self.d
}
/// annotated struct setter
#[wasm_bindgen(setter)]
pub fn set_d(&mut self, value: u32) {
self.d = value
}
/// annotated struct static method
pub fn static_method() {}
}
/// annotated enum type
#[wasm_bindgen]
pub enum AnnotatedEnum {
/// annotated enum variant 1
Variant1,
/// annotated enum variant 2
Variant2,
}
#[wasm_bindgen_test]
fn works() {
assert_comments_exist();
}

View File

@@ -0,0 +1,17 @@
const assert = require('assert');
let next = null;
exports.assert_next_undefined = function() {
next = undefined;
};
exports.assert_next_ten = function() {
next = 10;
};
exports.foo = function(a) {
console.log(a, next);
assert.strictEqual(a, next);
next = null;
};

View File

@@ -0,0 +1,18 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
use wasm_bindgen_test_crate_a as a;
use wasm_bindgen_test_crate_b as b;
#[wasm_bindgen(module = "tests/wasm/duplicate_deps.js")]
extern "C" {
fn assert_next_undefined();
fn assert_next_ten();
}
#[wasm_bindgen_test]
fn works() {
assert_next_undefined();
a::test();
assert_next_ten();
b::test();
}

View File

@@ -0,0 +1,57 @@
use wasm_bindgen_test::*;
pub mod same_function_different_locations_a {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_a.js")]
extern "C" {
pub fn foo();
pub static bar: JsValue;
}
}
pub mod same_function_different_locations_b {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_a.js")]
extern "C" {
pub fn foo();
pub static bar: JsValue;
}
}
#[wasm_bindgen_test]
fn same_function_different_locations() {
same_function_different_locations_a::foo();
same_function_different_locations_b::foo();
assert_eq!(*same_function_different_locations_a::bar, 3);
assert_eq!(*same_function_different_locations_a::bar, 3);
}
pub mod same_function_different_modules_a {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_b.js")]
extern "C" {
pub fn foo() -> bool;
pub static bar: JsValue;
}
}
pub mod same_function_different_modules_b {
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/duplicates_c.js")]
extern "C" {
pub fn foo() -> bool;
pub static bar: JsValue;
}
}
#[wasm_bindgen_test]
fn same_function_different_modules() {
assert!(same_function_different_modules_a::foo());
assert!(!same_function_different_modules_b::foo());
assert_eq!(*same_function_different_modules_a::bar, 4);
assert_eq!(*same_function_different_modules_b::bar, 5);
}

View File

@@ -0,0 +1,2 @@
exports.foo = () => {};
exports.bar = 3;

View File

@@ -0,0 +1,2 @@
exports.foo = () => true;
exports.bar = 4;

View File

@@ -0,0 +1,2 @@
exports.foo = () => false;
exports.bar = 5;

View File

@@ -0,0 +1,40 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.js_c_style_enum = () => {
assert.strictEqual(wasm.Color.Green, 0);
assert.strictEqual(wasm.Color.Yellow, 1);
assert.strictEqual(wasm.Color.Red, 2);
assert.strictEqual(wasm.Color[0], 'Green');
assert.strictEqual(wasm.Color[1], 'Yellow');
assert.strictEqual(wasm.Color[2], 'Red');
assert.strictEqual(Object.keys(wasm.Color).length, 6);
assert.strictEqual(wasm.enum_cycle(wasm.Color.Green), wasm.Color.Yellow);
};
exports.js_c_style_enum_with_custom_values = () => {
assert.strictEqual(wasm.ColorWithCustomValues.Green, 21);
assert.strictEqual(wasm.ColorWithCustomValues.Yellow, 34);
assert.strictEqual(wasm.ColorWithCustomValues.Red, 2);
assert.strictEqual(wasm.ColorWithCustomValues[21], 'Green');
assert.strictEqual(wasm.ColorWithCustomValues[34], 'Yellow');
assert.strictEqual(wasm.ColorWithCustomValues[2], 'Red');
assert.strictEqual(Object.keys(wasm.ColorWithCustomValues).length, 6);
assert.strictEqual(wasm.enum_with_custom_values_cycle(wasm.ColorWithCustomValues.Green), wasm.ColorWithCustomValues.Yellow);
};
exports.js_handle_optional_enums = x => wasm.handle_optional_enums(x);
exports.js_expect_enum = (a, b) => {
assert.strictEqual(a, b);
};
exports.js_expect_enum_none = a => {
assert.strictEqual(a, undefined);
};
exports.js_renamed_enum = b => {
assert.strictEqual(wasm.JsRenamedEnum.B, b);
};

View File

@@ -0,0 +1,97 @@
use self::inner::ColorWithCustomValues;
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/enums.js")]
extern "C" {
fn js_c_style_enum();
fn js_c_style_enum_with_custom_values();
fn js_handle_optional_enums(x: Option<Color>) -> Option<Color>;
fn js_expect_enum(x: Color, y: Option<Color>);
fn js_expect_enum_none(x: Option<Color>);
fn js_renamed_enum(b: RenamedEnum);
}
#[wasm_bindgen]
#[derive(PartialEq, Debug)]
pub enum Color {
Green,
Yellow,
Red,
}
pub mod inner {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub enum ColorWithCustomValues {
Green = 21,
Yellow = 34,
Red = 2,
}
}
#[wasm_bindgen(js_name = JsRenamedEnum)]
#[derive(Copy, Clone)]
pub enum RenamedEnum {
A = 10,
B = 20,
}
#[wasm_bindgen]
pub fn enum_cycle(color: Color) -> Color {
match color {
Color::Green => Color::Yellow,
Color::Yellow => Color::Red,
Color::Red => Color::Green,
}
}
#[wasm_bindgen]
pub fn enum_with_custom_values_cycle(color: ColorWithCustomValues) -> ColorWithCustomValues {
match color {
ColorWithCustomValues::Green => ColorWithCustomValues::Yellow,
ColorWithCustomValues::Yellow => ColorWithCustomValues::Red,
ColorWithCustomValues::Red => ColorWithCustomValues::Green,
}
}
#[wasm_bindgen_test]
fn c_style_enum() {
js_c_style_enum();
}
#[wasm_bindgen_test]
fn c_style_enum_with_custom_values() {
js_c_style_enum_with_custom_values();
}
#[wasm_bindgen]
pub fn handle_optional_enums(x: Option<Color>) -> Option<Color> {
x
}
#[wasm_bindgen_test]
fn test_optional_enums() {
use self::Color::*;
assert_eq!(js_handle_optional_enums(None), None);
assert_eq!(js_handle_optional_enums(Some(Green)), Some(Green));
assert_eq!(js_handle_optional_enums(Some(Yellow)), Some(Yellow));
assert_eq!(js_handle_optional_enums(Some(Red)), Some(Red));
}
#[wasm_bindgen_test]
fn test_optional_enum_values() {
use self::Color::*;
js_expect_enum(Green, Some(Green));
js_expect_enum(Yellow, Some(Yellow));
js_expect_enum(Red, Some(Red));
js_expect_enum_none(None);
}
#[wasm_bindgen_test]
fn test_renamed_enum() {
js_renamed_enum(RenamedEnum::B);
}

View File

@@ -0,0 +1,25 @@
const assert = require('assert');
exports.MyType = class {
static foo(y) {
assert.equal(y, 'x');
return y + 'y';
}
constructor(x) {
assert.equal(x, 2);
this._a = 1;
}
bar(x) {
assert.equal(x, true);
return 3.2;
}
get a() {
return this._a;
}
set a(v) {
this._a = v;
}
};

View File

@@ -0,0 +1,40 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen]
extern "C" {
type Math;
#[wasm_bindgen(static_method_of = Math, final)]
fn log(f: f32) -> f32;
}
#[wasm_bindgen(module = "tests/wasm/final.js")]
extern "C" {
type MyType;
#[wasm_bindgen(constructor, final)]
fn new(x: u32) -> MyType;
#[wasm_bindgen(static_method_of = MyType, final)]
fn foo(a: &str) -> String;
#[wasm_bindgen(method, final)]
fn bar(this: &MyType, arg: bool) -> f32;
#[wasm_bindgen(method, getter, final)]
fn a(this: &MyType) -> u32;
#[wasm_bindgen(method, setter, final)]
fn set_a(this: &MyType, a: u32);
}
#[wasm_bindgen_test]
fn simple() {
assert_eq!(Math::log(1.0), 0.0);
}
#[wasm_bindgen_test]
fn classes() {
assert_eq!(MyType::foo("x"), "xy");
let x = MyType::new(2);
assert_eq!(x.bar(true), 3.2);
assert_eq!(x.a(), 1);
x.set_a(3);
assert_eq!(x.a(), 3);
}

View File

@@ -0,0 +1,44 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
exports.call_exports = async function() {
await wasm.async_do_nothing();
assert.strictEqual(1, await wasm.async_return_1());
assert.strictEqual(2, await wasm.async_return_2());
await wasm.async_nothing_again();
assert.strictEqual(3, await wasm.async_return_3());
assert.strictEqual(4, await wasm.async_return_4());
assert.strictEqual(5, (await wasm.async_return_5()).val);
assert.strictEqual(6, (await wasm.async_return_6()).val);
await assert.rejects(wasm.async_throw_7(), /7/);
await assert.rejects(wasm.async_throw_custom(), /\[object Object\]/);
await assert.rejects(wasm.async_throw_message(), /async message/);
await assert.rejects(wasm.async_throw_jserror(), /async message/);
await assert.rejects(wasm.async_throw_custom_error(), /custom error/);
assert.strictEqual("Hi, Jim!", await wasm.async_take_reference("Jim"));
const foo = await new wasm.AsyncStruct();
assert.strictEqual(42, await foo.method());
};
exports.call_promise = async function() {
return "ok";
}
exports.call_promise_ok = async function() {
return "ok";
}
exports.call_promise_err = async function() {
throw "error";
}
exports.call_promise_unit = async function() {
console.log("asdfasdf");
}
exports.call_promise_ok_unit = async function() {
}
exports.call_promise_err_unit = async function() {
throw "error";
}

View File

@@ -0,0 +1,166 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[rustfmt::skip]
#[wasm_bindgen(module = "tests/wasm/futures.js")]
extern "C" {
#[wasm_bindgen(catch)]
async fn call_exports() -> Result<JsValue, JsValue>;
async fn call_promise() -> JsValue;
#[wasm_bindgen(catch)]
async fn call_promise_ok() -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
async fn call_promise_err() -> Result<JsValue, JsValue>;
#[wasm_bindgen]
async fn call_promise_unit();
#[wasm_bindgen(catch)]
async fn call_promise_ok_unit() -> Result<(), JsValue>;
#[wasm_bindgen(catch)]
async fn call_promise_err_unit() -> Result<(), JsValue>;
}
#[wasm_bindgen_test]
async fn smoke() {
call_exports().await.unwrap();
}
#[wasm_bindgen]
pub async fn async_do_nothing() {}
#[wasm_bindgen]
pub async fn async_return_1() -> JsValue {
1.into()
}
#[wasm_bindgen]
pub async fn async_return_2() -> u32 {
2
}
#[wasm_bindgen]
pub async fn async_nothing_again() -> Result<(), JsValue> {
Ok(())
}
#[wasm_bindgen]
pub async fn async_return_3() -> Result<u32, JsValue> {
Ok(3)
}
#[wasm_bindgen]
pub async fn async_return_4() -> Result<JsValue, JsValue> {
Ok(4.into())
}
#[wasm_bindgen]
pub struct AsyncCustomReturn {
pub val: u32,
}
#[wasm_bindgen]
pub async fn async_return_5() -> AsyncCustomReturn {
AsyncCustomReturn { val: 5 }
}
#[wasm_bindgen]
pub async fn async_return_6() -> Result<AsyncCustomReturn, JsValue> {
Ok(AsyncCustomReturn { val: 6 })
}
#[wasm_bindgen]
pub async fn async_throw_7() -> Result<AsyncCustomReturn, JsValue> {
Err(7.into())
}
#[wasm_bindgen]
pub async fn async_throw_custom() -> Result<AsyncCustomReturn, JsValue> {
Err(AsyncCustomReturn { val: 8 }.into())
}
#[wasm_bindgen]
pub async fn async_throw_message() -> Result<(), JsValue> {
Err(js_sys::Error::new("async message").into())
}
#[wasm_bindgen]
pub async fn async_throw_jserror() -> Result<AsyncCustomReturn, JsError> {
Err(JsError::new("async message"))
}
pub struct AsyncCustomError {
pub val: JsValue,
}
impl Into<JsValue> for AsyncCustomError {
fn into(self) -> JsValue {
self.val
}
}
#[wasm_bindgen]
pub async fn async_throw_custom_error() -> Result<AsyncCustomReturn, AsyncCustomError> {
Err(AsyncCustomError {
val: JsValue::from("custom error"),
})
}
#[wasm_bindgen]
pub async fn async_take_reference(x: &str) -> String {
format!("Hi, {x}!")
}
#[wasm_bindgen]
pub struct AsyncStruct;
#[wasm_bindgen]
impl AsyncStruct {
#[wasm_bindgen(constructor)]
pub async fn new() -> AsyncStruct {
AsyncStruct
}
pub async fn method(&self) -> u32 {
42
}
}
#[wasm_bindgen_test]
async fn test_promise() {
assert_eq!(call_promise().await.as_string(), Some(String::from("ok")))
}
#[wasm_bindgen_test]
async fn test_promise_ok() {
assert_eq!(
call_promise_ok().await.map(|j| j.as_string()),
Ok(Some(String::from("ok")))
)
}
#[wasm_bindgen_test]
async fn test_promise_err() {
assert_eq!(
call_promise_err().await.map_err(|j| j.as_string()),
Err(Some(String::from("error")))
)
}
#[wasm_bindgen_test]
async fn test_promise_unit() {
call_promise_unit().await
}
#[wasm_bindgen_test]
async fn test_promise_ok_unit() {
call_promise_ok_unit().await.unwrap()
}
#[wasm_bindgen_test]
async fn test_promise_err_unit() {
assert_eq!(
call_promise_err_unit().await.map_err(|j| j.as_string()),
Err::<(), _>(Some(String::from("error")))
)
}

View File

@@ -0,0 +1,107 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports._1_js = (rules) => {
assert.equal(rules.field, 1);
rules.field *= 2;
return rules;
}
exports._2_js = (rules) => {
let value = rules.no_js_name__no_getter_with_name__no_getter_without_name();
assert.equal(value, 2);
rules.set_no_js_name__no_setter_with_name__no_setter_without_name(value * 2);
return rules;
}
exports._3_js = (rules) => {
let value = rules.no_js_name__no_getter_with_name__getter_without_name;
assert.equal(value, 3);
rules.no_js_name__no_setter_with_name__setter_without_name = value * 2;
return rules;
}
exports._4_js = (rules) => {
let value = rules.new_no_js_name__getter_with_name__getter_without_name;
assert.equal(value, 4);
rules.new_no_js_name__setter_with_name__setter_without_name = value * 2;
return rules;
}
exports._5_js = (rules) => {
let value = rules.new_js_name__no_getter_with_name__no_getter_without_name();
assert.equal(value, 5);
rules.new_js_name__no_setter_with_name__no_setter_without_name(value * 2);
return rules;
}
exports._6_js = (rules) => {
let value = rules.new_js_name__no_getter_with_name__getter_without_name;
assert.equal(value, 6);
rules.new_js_name__no_setter_with_name__setter_without_name = value * 2;
return rules;
}
exports._7_js = (rules) => {
let value = rules.new_js_name__getter_with_name__no_getter_without_name_for_field;
assert.equal(value, 7);
rules.new_js_name__setter_with_name__no_setter_without_name_for_field = value * 2;
return rules;
}
exports._8_js = (rules) => {
let value = rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name;
assert.equal(value, 8);
rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name = value * 2;
return rules;
}
exports._9_js = (rules) => {
let value = rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name;
assert.equal(value, 9);
rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name = value * 2;
return rules;
}
exports._10_js = (rules) => {
let value = rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name;
assert.equal(value, 10);
rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name = value * 2;
return rules;
}
exports._11_js = (rules) => {
let value = rules.new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name;
assert.equal(value, 11);
rules.new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name = value * 2;
return rules;
}
exports._12_js = (rules) => {
let value = rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name;
assert.equal(value, 12);
rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name = value * 2;
return rules;
}
exports._13_js = (rules) => {
let value = rules.new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name;
assert.equal(value, 13);
rules.new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name = value * 2;
return rules;
}
exports.test_getter_compute = x => {
assert.equal(x.foo, 3)
};
exports.test_setter_compute = x => {
x.foo = 97;
};
exports.test_statics = x => {
assert.equal(x.field, 3);
assert.equal(wasm.Statics.field, 4);
x.field = 13;
wasm.Statics.field = 14;
}

View File

@@ -0,0 +1,348 @@
use std::cell::Cell;
use std::rc::Rc;
use std::sync::atomic::{AtomicU32, Ordering};
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/getters_and_setters.js")]
extern "C" {
fn _1_js(rules: Rules) -> Rules;
fn _2_js(rules: Rules) -> Rules;
fn _3_js(rules: Rules) -> Rules;
fn _4_js(rules: Rules) -> Rules;
fn _5_js(rules: Rules) -> Rules;
fn _6_js(rules: Rules) -> Rules;
fn _7_js(rules: Rules) -> Rules;
fn _8_js(rules: Rules) -> Rules;
fn _9_js(rules: Rules) -> Rules;
fn _10_js(rules: Rules) -> Rules;
fn _11_js(rules: Rules) -> Rules;
fn _12_js(rules: Rules) -> Rules;
fn _13_js(rules: Rules) -> Rules;
fn test_getter_compute(x: GetterCompute);
fn test_setter_compute(x: SetterCompute);
fn test_statics(x: Statics);
}
// Each getter/setter combination is derived
// from https://github.com/rustwasm/wasm-bindgen/pull/1440#issuecomment-487113564
#[wasm_bindgen]
pub struct Rules {
pub field: i32,
}
#[wasm_bindgen]
#[allow(non_snake_case)]
impl Rules {
#[wasm_bindgen]
pub fn no_js_name__no_getter_with_name__no_getter_without_name(&self) -> i32 {
self.field
}
#[wasm_bindgen]
pub fn set_no_js_name__no_setter_with_name__no_setter_without_name(&mut self, field: i32) {
self.field = field;
}
#[wasm_bindgen(getter)]
pub fn no_js_name__no_getter_with_name__getter_without_name(&self) -> i32 {
self.field
}
#[wasm_bindgen(setter)]
pub fn set_no_js_name__no_setter_with_name__setter_without_name(&mut self, field: i32) {
self.field = field;
}
#[wasm_bindgen(getter = new_no_js_name__getter_with_name__getter_without_name)]
pub fn no_js_name__getter_with_name__getter_without_name(&self) -> i32 {
self.field
}
#[wasm_bindgen(setter = new_no_js_name__setter_with_name__setter_without_name)]
pub fn set_no_js_name__setter_with_name__setter_without_name(&mut self, field: i32) {
self.field = field;
}
#[wasm_bindgen(js_name = new_js_name__no_getter_with_name__no_getter_without_name)]
pub fn js_name__no_getter_with_name__no_getter_without_name(&self) -> i32 {
self.field
}
#[wasm_bindgen(js_name = new_js_name__no_setter_with_name__no_setter_without_name)]
pub fn set_js_name__no_setter_with_name__no_setter_without_name(&mut self, field: i32) {
self.field = field;
}
#[wasm_bindgen(getter, js_name = new_js_name__no_getter_with_name__getter_without_name)]
pub fn js_name__no_getter_with_name__getter_without_name(&self) -> i32 {
self.field
}
#[wasm_bindgen(js_name = new_js_name__no_setter_with_name__setter_without_name, setter)]
pub fn set_js_name__no_setter_with_name__setter_without_name(&mut self, field: i32) {
self.field = field;
}
#[wasm_bindgen(
getter = new_js_name__getter_with_name__no_getter_without_name_for_field,
js_name = new_js_name__getter_with_name__no_getter_without_name_for_method
)]
pub fn js_name__getter_with_name__no_getter_without_name(&self) -> i32 {
self.field
}
#[wasm_bindgen(
js_name = new_js_name__setter_with_name__no_setter_without_name_for_method,
setter = new_js_name__setter_with_name__no_setter_without_name_for_field
)]
pub fn set_js_name__setter_with_name__no_setter_without_name_for_field(&mut self, field: i32) {
self.field = field;
}
#[wasm_bindgen(getter, js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name)]
pub fn js_name__no_getter_with_name__getter_without_name__same_getter_setter_name(
&self,
) -> i32 {
self.field
}
#[wasm_bindgen(js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name, setter)]
pub fn set_js_name__no_setter_with_name__setter_without_name__same_getter_setter_name(
&mut self,
field: i32,
) {
self.field = field;
}
#[wasm_bindgen(getter, js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name)]
pub fn js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name(
&self,
) -> i32 {
self.field
}
#[wasm_bindgen(js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name, setter)]
pub fn set_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name(
&mut self,
field: i32,
) {
self.field = field;
}
#[wasm_bindgen(
getter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name,
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name)]
pub fn js_name__getter_with_name__no_getter_without_name__same_getter_setter_name(
&self,
) -> i32 {
self.field
}
#[wasm_bindgen(
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name,
setter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name)]
pub fn set_js_name__setter_with_name__no_setter_without_name__same_getter_setter_name(
&mut self,
field: i32,
) {
self.field = field;
}
#[wasm_bindgen(
getter = new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name,
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__no_same_field_name)]
pub fn js_name__getter_with_name__no_getter_without_name__same_getter_setter_name__no_same_field_name(
&self,
) -> i32 {
self.field
}
#[wasm_bindgen(
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__no_same_field_name,
setter = new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name)]
pub fn set_js_name__setter_with_name__no_setter_without_name__same_getter_setter_name__no_same_field_name(
&mut self,
field: i32,
) {
self.field = field;
}
#[wasm_bindgen(
getter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name,
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name)]
pub fn js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name(
&self,
) -> i32 {
self.field
}
#[wasm_bindgen(
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name,
setter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name)]
pub fn set_js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name(
&mut self,
field: i32,
) {
self.field = field;
}
#[wasm_bindgen(
getter = new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name,
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name)]
pub fn js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name(
&self,
) -> i32 {
self.field
}
#[wasm_bindgen(
js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name,
setter = new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name)]
pub fn set_js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name(
&mut self,
field: i32,
) {
self.field = field;
}
}
#[wasm_bindgen_test]
fn _1_rust() {
let rules = _1_js(Rules { field: 1 });
assert_eq!(rules.field, 2);
}
#[wasm_bindgen_test]
fn _2_rust() {
let rules = _2_js(Rules { field: 2 });
assert_eq!(rules.field, 4);
}
#[wasm_bindgen_test]
fn _3_rust() {
let rules = _3_js(Rules { field: 3 });
assert_eq!(rules.field, 6);
}
#[wasm_bindgen_test]
fn _4_rust() {
let rules = _4_js(Rules { field: 4 });
assert_eq!(rules.field, 8);
}
#[wasm_bindgen_test]
fn _5_rust() {
let rules = _5_js(Rules { field: 5 });
assert_eq!(rules.field, 10);
}
#[wasm_bindgen_test]
fn _6_rust() {
let rules = _6_js(Rules { field: 6 });
assert_eq!(rules.field, 12);
}
#[wasm_bindgen_test]
fn _7_rust() {
let rules = _7_js(Rules { field: 7 });
assert_eq!(rules.field, 14);
}
#[wasm_bindgen_test]
fn _8_rust() {
let rules = _8_js(Rules { field: 8 });
assert_eq!(rules.field, 16);
}
#[wasm_bindgen_test]
fn _9_rust() {
let rules = _9_js(Rules { field: 9 });
assert_eq!(rules.field, 18);
}
#[wasm_bindgen_test]
fn _10_rust() {
let rules = _10_js(Rules { field: 10 });
assert_eq!(rules.field, 20);
}
#[wasm_bindgen_test]
fn _11_rust() {
let rules = _11_js(Rules { field: 11 });
assert_eq!(rules.field, 22);
}
#[wasm_bindgen_test]
fn _12_rust() {
let rules = _12_js(Rules { field: 12 });
assert_eq!(rules.field, 24);
}
#[wasm_bindgen_test]
fn _13_rust() {
let rules = _13_js(Rules { field: 13 });
assert_eq!(rules.field, 26);
}
#[wasm_bindgen]
struct GetterCompute;
#[wasm_bindgen]
impl GetterCompute {
#[wasm_bindgen(getter)]
pub fn foo(&self) -> u32 {
3
}
}
#[wasm_bindgen_test]
fn getter_compute() {
test_getter_compute(GetterCompute);
}
#[wasm_bindgen]
struct SetterCompute(Rc<Cell<u32>>);
#[wasm_bindgen]
impl SetterCompute {
#[wasm_bindgen(setter)]
pub fn set_foo(&self, x: u32) {
self.0.set(x + 3);
}
}
#[wasm_bindgen_test]
fn setter_compute() {
let r = Rc::new(Cell::new(3));
test_setter_compute(SetterCompute(r.clone()));
assert_eq!(r.get(), 100);
}
static FIELD: AtomicU32 = AtomicU32::new(3);
static STATIC_FIELD: AtomicU32 = AtomicU32::new(4);
#[wasm_bindgen]
struct Statics;
#[wasm_bindgen]
impl Statics {
#[wasm_bindgen(getter = field)]
// Make sure that this still works if we make this mutable for no reason
pub fn getter(&mut self) -> u32 {
FIELD.load(Ordering::Relaxed)
}
#[wasm_bindgen(setter = field)]
// Make sure that this still works if we make this consume the type for no reason
pub fn setter(self, x: u32) {
FIELD.store(x, Ordering::Relaxed)
}
// Define a static field with the same name to make sure that works.
#[wasm_bindgen(getter = field)]
pub fn static_getter() -> u32 {
STATIC_FIELD.load(Ordering::Relaxed)
}
#[wasm_bindgen(setter = field)]
pub fn static_setter(x: u32) {
STATIC_FIELD.store(x, Ordering::Relaxed)
}
}
#[wasm_bindgen_test]
fn statics() {
test_statics(Statics);
assert_eq!(FIELD.load(Ordering::Relaxed), 13);
assert_eq!(STATIC_FIELD.load(Ordering::Relaxed), 14);
}

View File

@@ -0,0 +1,170 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
exports.math_log = Math.log;
exports.StaticFunction = class {
static bar() { return 2; }
};
class Construct {
static create() {
const ret = new Construct();
ret.internal_string = 'this';
return ret;
}
get_internal_string() {
return this.internal_string;
}
append_to_internal_string(s) {
this.internal_string += s;
}
assert_internal_string(s) {
assert.strictEqual(this.internal_string, s);
}
}
Construct.internal_string = '';
exports.Construct = Construct;
class NewConstructor {
constructor(field) {
this.field = field;
}
get() {
return this.field + 1;
}
}
exports.NewConstructors = NewConstructor;
exports.default = NewConstructor;
let switch_called = false;
class SwitchMethods {
constructor() {
}
static a() {
switch_called = true;
}
b() {
switch_called = true;
}
}
exports.SwitchMethods = SwitchMethods;
exports.switch_methods_called = function() {
const tmp = switch_called;
switch_called = false;
return tmp;
};
exports.switch_methods_a = function() { SwitchMethods.a = function() {}; };
exports.switch_methods_b = function() { SwitchMethods.prototype.b = function() {}; };
exports.Properties = class {
constructor() {
this.num = 1;
}
get a() {
return this.num;
}
set a(val) {
this.num = val;
}
};
exports.RenameProperties = class {
constructor() {
this.num = 1;
}
get a() {
return this.num;
}
set a(val) {
this.num = val;
}
};
class Options {
}
exports.Options = Options;
exports.take_none = function(val) {
assert.strictEqual(val, undefined);
};
exports.take_some = function(val) {
assert.strictEqual(val === undefined, false);
};
exports.return_null = function() {
return null;
};
exports.return_undefined = function() {
return undefined;
};
exports.return_some = function() {
return new Options();
};
exports.run_rust_option_tests = function() {
wasm.rust_take_none();
wasm.rust_take_none(null)
wasm.rust_take_none(undefined);
wasm.rust_take_some(new Options());
assert.strictEqual(wasm.rust_return_none(), undefined);
assert.strictEqual(wasm.rust_return_none(), undefined);
assert.strictEqual(wasm.rust_return_some() === undefined, false);
};
exports.CatchConstructors = class {
constructor(x) {
if (x == 0) {
throw new Error('bad!');
}
}
};
exports.StaticStructural = class {
static static_structural(x) {
return x + 3;
}
};
class InnerClass {
static inner_static_function(x) {
return x + 5;
}
static create_inner_instance() {
const ret = new InnerClass();
ret.internal_int = 3;
return ret;
}
get_internal_int() {
return this.internal_int;
}
append_to_internal_int(i) {
this.internal_int += i;
}
assert_internal_int(i) {
assert.strictEqual(this.internal_int, i);
}
}
exports.nestedNamespace = {
InnerClass: InnerClass
}

View File

@@ -0,0 +1,263 @@
//! dox
#![deny(missing_docs)] // test that documenting public bindings is enough
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/import_class.js")]
extern "C" {
fn math_log(f: f64) -> f64;
#[wasm_bindgen(js_namespace = StaticFunction)]
fn bar() -> u32;
#[derive(Clone)]
type Construct;
#[wasm_bindgen(js_namespace = Construct)]
fn create() -> Construct;
#[wasm_bindgen(method)]
fn get_internal_string(this: &Construct) -> String;
#[wasm_bindgen(method)]
fn append_to_internal_string(this: &Construct, s: &str);
#[wasm_bindgen(method)]
fn assert_internal_string(this: &Construct, s: &str);
type NewConstructors;
#[wasm_bindgen(constructor)]
fn new(arg: i32) -> NewConstructors;
#[wasm_bindgen(method)]
fn get(this: &NewConstructors) -> i32;
#[wasm_bindgen(js_name = default)]
type RenamedTypes;
#[wasm_bindgen(constructor, js_class = default)]
fn new(arg: i32) -> RenamedTypes;
#[wasm_bindgen(method, js_class = default)]
fn get(this: &RenamedTypes) -> i32;
fn switch_methods_a();
fn switch_methods_b();
type SwitchMethods;
#[wasm_bindgen(constructor)]
#[wasm_bindgen(final)]
fn new() -> SwitchMethods;
#[wasm_bindgen(js_namespace = SwitchMethods, final)]
fn a();
fn switch_methods_called() -> bool;
#[wasm_bindgen(method, final)]
fn b(this: &SwitchMethods);
type Properties;
#[wasm_bindgen(constructor)]
fn new() -> Properties;
#[wasm_bindgen(getter, method)]
fn a(this: &Properties) -> i32;
#[wasm_bindgen(setter, method)]
fn set_a(this: &Properties, a: i32);
type RenameProperties;
#[wasm_bindgen(constructor)]
fn new() -> RenameProperties;
#[wasm_bindgen(getter = a, method)]
fn test(this: &RenameProperties) -> i32;
#[wasm_bindgen(getter, method, js_name = a)]
fn test2(this: &RenameProperties) -> i32;
#[wasm_bindgen(setter = a, method)]
fn another(this: &RenameProperties, a: i32);
#[wasm_bindgen(setter, method, js_name = a)]
fn another2(this: &RenameProperties, a: i32);
/// dox
pub type AssertImportDenyDocsWorks;
/// dox
#[wasm_bindgen(constructor)]
pub fn new() -> AssertImportDenyDocsWorks;
/// dox
#[wasm_bindgen(getter = a, method)]
pub fn test(this: &AssertImportDenyDocsWorks) -> i32;
/// dox
pub fn foo();
pub type Options;
#[wasm_bindgen(constructor)]
fn new() -> Options;
fn take_none(val: Option<Options>);
fn take_some(val: Option<Options>);
fn return_null() -> Option<Options>;
fn return_undefined() -> Option<Options>;
fn return_some() -> Option<Options>;
fn run_rust_option_tests();
type CatchConstructors;
#[wasm_bindgen(constructor, catch)]
fn new(x: u32) -> Result<CatchConstructors, JsValue>;
type StaticStructural;
#[wasm_bindgen(static_method_of = StaticStructural, structural)]
fn static_structural(a: u32) -> u32;
#[derive(Clone)]
type InnerClass;
#[wasm_bindgen(js_namespace = ["nestedNamespace", "InnerClass"])]
fn inner_static_function(a: u32) -> u32;
#[wasm_bindgen(js_namespace = ["nestedNamespace", "InnerClass"])]
fn create_inner_instance() -> InnerClass;
#[wasm_bindgen(method)]
fn get_internal_int(this: &InnerClass) -> u32;
#[wasm_bindgen(method)]
fn append_to_internal_int(this: &InnerClass, i: u32);
#[wasm_bindgen(method)]
fn assert_internal_int(this: &InnerClass, i: u32);
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = Math)]
fn random() -> f64;
#[wasm_bindgen(js_namespace = Math)]
fn log(a: f64) -> f64;
}
#[wasm_bindgen_test]
fn simple() {
random();
assert_eq!(log(1.0), math_log(1.0));
}
#[wasm_bindgen_test]
fn import_class() {
assert_eq!(bar(), 2);
}
#[wasm_bindgen_test]
fn construct() {
let f = Construct::create();
assert_eq!(f.get_internal_string(), "this");
assert_eq!(f.clone().get_internal_string(), "this");
f.append_to_internal_string(" foo");
f.assert_internal_string("this foo");
}
#[wasm_bindgen_test]
fn new_constructors() {
let f = NewConstructors::new(1);
assert_eq!(f.get(), 2);
}
#[wasm_bindgen_test]
fn rename_type() {
let f = RenamedTypes::new(1);
assert_eq!(f.get(), 2);
}
#[wasm_bindgen_test]
#[cfg(ignored)] // TODO: fix this before landing
fn switch_methods() {
assert!(!switch_methods_called());
SwitchMethods::a();
assert!(switch_methods_called());
switch_methods_a();
assert!(!switch_methods_called());
SwitchMethods::a();
assert!(switch_methods_called());
assert!(!switch_methods_called());
SwitchMethods::new().b();
assert!(switch_methods_called());
switch_methods_b();
assert!(!switch_methods_called());
SwitchMethods::new().b();
assert!(!switch_methods_called());
}
#[wasm_bindgen_test]
fn properties() {
let a = Properties::new();
assert_eq!(a.a(), 1);
a.set_a(2);
assert_eq!(a.a(), 2);
}
#[wasm_bindgen_test]
fn rename_setter_getter() {
let x: fn() -> RenameProperties = RenameProperties::new;
let a = x();
assert_eq!(a.test(), 1);
a.another(2);
assert_eq!(a.test(), 2);
a.another2(3);
assert_eq!(a.test2(), 3);
}
/// dox
#[wasm_bindgen]
pub struct AssertDenyDocsWorks {
/// dox
pub a: u32,
_b: i64,
}
/// dox
#[wasm_bindgen]
pub fn assert_deny_docs_works() {}
#[wasm_bindgen_test]
fn options() {
take_none(None);
take_some(Some(Options::new()));
assert!(return_null().is_none());
assert!(return_undefined().is_none());
assert!(return_some().is_some());
run_rust_option_tests();
}
/// doc
#[wasm_bindgen]
pub fn rust_take_none(a: Option<Options>) {
assert!(a.is_none());
}
/// doc
#[wasm_bindgen]
pub fn rust_take_some(a: Option<Options>) {
assert!(a.is_some());
}
/// doc
#[wasm_bindgen]
pub fn rust_return_none() -> Option<Options> {
None
}
/// doc
#[wasm_bindgen]
pub fn rust_return_some() -> Option<Options> {
Some(Options::new())
}
#[wasm_bindgen_test]
fn catch_constructors() {
assert!(CatchConstructors::new(0).is_err());
assert!(CatchConstructors::new(1).is_ok());
}
#[wasm_bindgen_test]
fn static_structural() {
assert_eq!(StaticStructural::static_structural(30), 33);
}
#[wasm_bindgen_test]
fn nested_namespace() {
assert_eq!(InnerClass::inner_static_function(15), 20);
let f = InnerClass::create_inner_instance();
assert_eq!(f.get_internal_int(), 3);
assert_eq!(f.clone().get_internal_int(), 3);
f.append_to_internal_int(5);
f.assert_internal_int(8);
}

View File

@@ -0,0 +1,143 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
const fs = require('fs');
let ARG = null;
let ANOTHER_ARG = null;
let SYM = Symbol('a');
exports.simple_foo = function(s) {
assert.strictEqual(ARG, null);
assert.strictEqual(s, "foo");
ARG = s;
};
exports.simple_another = function(s) {
assert.strictEqual(ANOTHER_ARG, null);
assert.strictEqual(s, 21);
ANOTHER_ARG = s;
return 35;
};
exports.simple_take_and_return_bool = function(s) {
return s;
};
exports.simple_return_object = function() {
return SYM;
};
exports.test_simple = function() {
assert.strictEqual(ARG, null);
wasm.simple_take_str("foo");
assert.strictEqual(ARG, "foo");
assert.strictEqual(ANOTHER_ARG, null);
assert.strictEqual(wasm.simple_another_thunk(21), 35);
assert.strictEqual(ANOTHER_ARG, 21);
assert.strictEqual(wasm.simple_bool_thunk(true), true);
assert.strictEqual(wasm.simple_bool_thunk(false), false);
assert.strictEqual(wasm.simple_get_the_object(), SYM);
};
exports.return_string = function() {
return 'bar';
};
exports.take_and_ret_string = function(a) {
return a + 'b';
};
exports.exceptions_throw = function() {
throw new Error('error!');
};
exports.exceptions_throw2 = function() {
throw new Error('error2');
};
exports.test_exception_propagates = function() {
assert.throws(wasm.exceptions_propagate, /error!/);
};
exports.assert_valid_error = function(obj) {
assert.strictEqual(obj instanceof Error, true);
assert.strictEqual(obj.message, 'error2');
};
exports.IMPORT = 1.0;
exports.return_three = function() { return 3; };
exports.underscore = function(x) {};
exports.pub = function() { return 2; };
exports.bar = { foo: 3 };
let CUSTOM_TYPE = null;
exports.take_custom_type = function(f) {
CUSTOM_TYPE = f;
return f;
};
exports.custom_type_return_2 = function() {
return 2;
};
exports.touch_custom_type = function() {
assert.throws(() => CUSTOM_TYPE.touch(),
/Attempt to use a moved value|null pointer passed to rust/);
};
exports.interpret_2_as_custom_type = function() {
assert.throws(wasm.interpret_2_as_custom_type, /expected instance of CustomType/);
};
exports.baz$ = function() {};
exports.$foo = 1.0;
exports.assert_dead_import_not_generated = function() {
const filename = require.resolve("wasm-bindgen-test");
const bindings = fs.readFileSync(filename);
assert.ok(!bindings.includes("unused_import"));
};
exports.import_inside_function_works = function() {};
exports.import_inside_private_module = function() {};
exports.should_call_undefined_functions = () => false;
exports.STATIC_STRING = 'x';
class StaticMethodCheck {
static static_method_of_right_this() {
assert.ok(this === StaticMethodCheck);
}
}
exports.StaticMethodCheck = StaticMethodCheck;
exports.receive_undefined = val => {
assert.strictEqual(val, undefined);
};
const VAL = {};
exports.receive_some = val => {
assert.strictEqual(val, VAL);
};
exports.get_some_val = () => VAL;
exports.Math = {
func_from_module_math: (a) => a * 2
}
exports.Number = {
func_from_module_number: () => 3.0
}
exports.same_name_from_import = (a) => a * 3;
exports.same_js_namespace_from_module = {
func_from_module_1_same_js_namespace: (a) => a * 5
}

View File

@@ -0,0 +1,323 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/imports.js")]
extern "C" {
fn test_simple();
fn simple_foo(s: &str);
fn simple_another(a: u32) -> i32;
fn simple_take_and_return_bool(a: bool) -> bool;
fn simple_return_object() -> JsValue;
#[allow(dead_code)]
fn missing_symbol(s: &str);
fn return_string() -> String;
fn take_and_ret_string(s: String) -> String;
#[wasm_bindgen(js_name = take_and_ret_string)]
fn take_and_ret_string2(s: &str) -> String;
fn exceptions_throw();
#[wasm_bindgen(catch)]
fn exceptions_throw2() -> Result<(), JsValue>;
fn test_exception_propagates();
fn assert_valid_error(val: JsValue);
static IMPORT: JsValue;
#[wasm_bindgen(js_name = return_three)]
fn rust_name_for_return_three() -> u32;
fn underscore(_: u8);
#[wasm_bindgen(js_name = pub)]
fn js_function_named_rust_keyword() -> u32;
type bar;
#[wasm_bindgen(js_namespace = bar, js_name = foo)]
static FOO: JsValue;
fn take_custom_type(f: CustomType) -> CustomType;
fn touch_custom_type();
fn custom_type_return_2() -> CustomType;
#[wasm_bindgen(js_name = interpret_2_as_custom_type)]
fn js_interpret_2_as_custom_type();
#[wasm_bindgen(js_name = "baz$")]
fn renamed_with_dollar_sign();
#[wasm_bindgen(js_name = "$foo")]
static RENAMED: JsValue;
fn unused_import();
fn assert_dead_import_not_generated();
fn should_call_undefined_functions() -> bool;
type StaticMethodCheck;
#[wasm_bindgen(static_method_of = StaticMethodCheck)]
fn static_method_of_right_this();
static STATIC_STRING: String;
#[derive(Clone)]
type PassOutOptionUndefined;
fn get_some_val() -> PassOutOptionUndefined;
#[wasm_bindgen(js_name = "receive_undefined")]
fn receive_undefined_ref(arg: Option<&PassOutOptionUndefined>);
#[wasm_bindgen(js_name = "receive_undefined")]
fn receive_undefined_owned(arg: Option<PassOutOptionUndefined>);
#[wasm_bindgen(js_name = "receive_some")]
fn receive_some_ref(arg: Option<&PassOutOptionUndefined>);
#[wasm_bindgen(js_name = "receive_some")]
fn receive_some_owned(arg: Option<PassOutOptionUndefined>);
#[wasm_bindgen(js_namespace = Math)]
fn func_from_module_math(a: i32) -> i32;
#[wasm_bindgen(js_namespace = Number)]
fn func_from_module_number() -> f64;
#[wasm_bindgen(js_name = "same_name_from_import")]
fn same_name_from_import_1(s: i32) -> i32;
#[wasm_bindgen(js_namespace = same_js_namespace_from_module)]
fn func_from_module_1_same_js_namespace(s: i32) -> i32;
}
#[wasm_bindgen(module = "tests/wasm/imports_2.js")]
extern "C" {
#[wasm_bindgen(js_name = "same_name_from_import")]
fn same_name_from_import_2(s: i32) -> i32;
#[wasm_bindgen(js_namespace = same_js_namespace_from_module)]
fn func_from_module_2_same_js_namespace(s: i32) -> i32;
}
#[wasm_bindgen]
extern "C" {
fn parseInt(a: &str) -> u32;
#[wasm_bindgen(js_namespace = Math, js_name = "sqrt")]
fn func_from_global_math(s: f64) -> f64;
type Number;
#[wasm_bindgen(getter, static_method_of = Number, js_name = "NAN")]
fn static_getter_from_global_number() -> f64;
}
#[wasm_bindgen_test]
fn simple() {
test_simple();
}
#[wasm_bindgen]
pub fn simple_take_str(s: &str) {
simple_foo(s);
}
#[wasm_bindgen]
pub fn simple_another_thunk(a: u32) -> i32 {
simple_another(a)
}
#[wasm_bindgen]
pub fn simple_bool_thunk(a: bool) -> bool {
simple_take_and_return_bool(a)
}
#[wasm_bindgen]
pub fn simple_get_the_object() -> JsValue {
simple_return_object()
}
#[wasm_bindgen_test]
fn string_ret() {
assert_eq!(return_string(), "bar");
}
#[wasm_bindgen_test]
fn strings() {
assert_eq!(take_and_ret_string(String::from("a")), "ab");
assert_eq!(take_and_ret_string2("b"), "bb");
}
#[wasm_bindgen_test]
fn exceptions() {
test_exception_propagates();
assert!(exceptions_throw2().is_err());
}
#[wasm_bindgen]
pub fn exceptions_propagate() {
exceptions_throw();
}
#[wasm_bindgen_test]
fn exn_caught() {
assert_valid_error(exceptions_throw2().unwrap_err());
}
#[wasm_bindgen_test]
fn free_imports() {
assert_eq!(parseInt("3"), 3);
}
#[wasm_bindgen_test]
fn import_a_field() {
assert_eq!(IMPORT.as_f64(), Some(1.0));
}
#[wasm_bindgen_test]
fn rename() {
assert_eq!(rust_name_for_return_three(), 3);
}
#[wasm_bindgen_test]
fn underscore_pattern() {
underscore(2);
}
#[wasm_bindgen_test]
fn rust_keyword() {
assert_eq!(js_function_named_rust_keyword(), 2);
}
#[wasm_bindgen_test]
fn rust_keyword2() {
assert_eq!(FOO.as_f64(), Some(3.0));
}
#[wasm_bindgen_test]
fn custom_type() {
take_custom_type(CustomType(()));
touch_custom_type();
js_interpret_2_as_custom_type();
}
#[wasm_bindgen]
pub fn interpret_2_as_custom_type() {
custom_type_return_2();
}
#[wasm_bindgen]
pub struct CustomType(());
#[wasm_bindgen]
impl CustomType {
pub fn touch(&self) {
panic!()
}
}
#[wasm_bindgen_test]
fn rename_with_string() {
renamed_with_dollar_sign();
}
#[wasm_bindgen_test]
fn rename_static_with_string() {
assert_eq!(RENAMED.as_f64(), Some(1.0));
}
#[wasm_bindgen_test]
fn dead_imports_not_generated() {
assert_dead_import_not_generated();
}
#[wasm_bindgen_test]
fn import_inside_function_works() {
#[wasm_bindgen(module = "tests/wasm/imports.js")]
extern "C" {
fn import_inside_function_works();
}
import_inside_function_works();
}
#[wasm_bindgen_test]
fn private_module_imports_work() {
private::foo();
}
mod private {
use wasm_bindgen::prelude::*;
pub fn foo() {
#[wasm_bindgen(module = "tests/wasm/imports.js")]
extern "C" {
fn import_inside_private_module();
}
import_inside_private_module();
}
}
#[wasm_bindgen]
extern "C" {
fn something_not_defined_in_the_environment();
type TypeThatIsNotDefined;
#[wasm_bindgen(constructor)]
fn new() -> TypeThatIsNotDefined;
#[wasm_bindgen(method)]
fn method(this: &TypeThatIsNotDefined);
#[wasm_bindgen(method, getter)]
fn property(this: &TypeThatIsNotDefined) -> u32;
#[wasm_bindgen(method, setter)]
fn set_property(this: &TypeThatIsNotDefined, val: u32);
}
#[wasm_bindgen_test]
fn undefined_function_is_ok() {
if !should_call_undefined_functions() {
return;
}
something_not_defined_in_the_environment();
let x = TypeThatIsNotDefined::new();
x.method();
x.set_property(x.property());
}
#[wasm_bindgen_test]
fn static_string_ok() {
assert_eq!(*STATIC_STRING, "x");
}
#[wasm_bindgen_test]
fn static_method_of_has_right_this() {
StaticMethodCheck::static_method_of_right_this();
}
#[wasm_bindgen_test]
fn pass_out_options_as_undefined() {
receive_undefined_ref(None);
receive_undefined_ref(None);
receive_undefined_owned(None);
receive_undefined_owned(None);
let v = get_some_val();
receive_some_ref(Some(&v));
receive_some_ref(Some(&v));
receive_some_owned(Some(v.clone()));
receive_some_owned(Some(v));
}
#[wasm_bindgen_test]
fn func_from_global_and_module_same_js_namespace() {
assert_eq!(func_from_global_math(4.0), 2.0);
assert_eq!(func_from_module_math(2), 4);
}
#[wasm_bindgen_test]
fn getter_from_global_and_module_same_name() {
assert!(Number::static_getter_from_global_number().is_nan());
assert_eq!(func_from_module_number(), 3.0);
}
#[wasm_bindgen_test]
fn func_from_two_modules_same_js_name() {
assert_eq!(same_name_from_import_1(1), 3);
assert_eq!(same_name_from_import_2(1), 4);
}
#[wasm_bindgen_test]
fn func_from_two_modules_same_js_namespace() {
assert_eq!(func_from_module_1_same_js_namespace(2), 10);
assert_eq!(func_from_module_2_same_js_namespace(2), 12);
}

View File

@@ -0,0 +1,5 @@
exports.same_name_from_import = (a) => a * 4;
exports.same_js_namespace_from_module = {
func_from_module_2_same_js_namespace: (a) => a * 6
}

View File

@@ -0,0 +1,113 @@
//! Tests that some of our more obscure intrinsics work properly.
use std::convert::TryFrom;
use std::fmt::Debug;
use js_sys::{Object, RangeError, Reflect};
use wasm_bindgen::{JsCast, JsValue};
use wasm_bindgen_test::wasm_bindgen_test;
// Shorter `JsValue::from(i32)`.
fn int(x: i32) -> JsValue {
JsValue::from(x)
}
#[wasm_bindgen_test]
fn bitwise() {
assert_eq!(int(0b1110) & int(0b0111), 0b0110);
assert_eq!(int(0b1000) | int(0b0010), 0b1010);
assert_eq!(int(0b1110) ^ int(0b0100), 0b1010);
assert_eq!(int(0x00ffffff).bit_not(), 0xff000000u32 as i32);
assert_eq!(int(0b0001) << int(2), 0b0100);
assert_eq!(int(0b1000) >> int(2), 0b0010);
assert_eq!(int(-0b1000) >> int(2), -0b0010);
// Note that bit-wise, this is the same as the above `-0b1000`.
assert_eq!(
JsValue::from(0xfffffff8u32).unsigned_shr(&int(2)),
0x3ffffffe
);
}
#[wasm_bindgen_test]
fn arithmetic() {
assert_eq!(-int(12), -12);
assert_eq!(int(1) + int(2), 3);
assert_eq!(int(1) - int(2), -1);
assert_eq!(int(10) / int(5), 2);
assert_eq!(int(42).checked_div(&int(6)), 7);
// Note that this doesn't throw for regular numbers, since they just give
// `NaN` for invalid results.
assert!(JsValue::bigint_from_str("0")
.checked_div(&JsValue::bigint_from_str("0"))
.dyn_into::<RangeError>()
.is_ok());
assert_eq!(int(12) * int(34), 408);
assert_eq!(int(17) % int(10), 7);
assert_eq!(int(2).pow(&int(8)), 256)
}
#[wasm_bindgen_test]
fn cmp() {
assert!(int(2).lt(&int(3)));
assert!(!int(2).lt(&int(2)));
assert!(int(2).le(&int(3)));
assert!(int(2).le(&int(2)));
assert!(int(3).ge(&int(2)));
assert!(int(3).ge(&int(3)));
assert!(int(3).gt(&int(2)));
assert!(!int(3).gt(&int(3)));
assert!(int(2) == int(2));
assert!(int(2) != int(3));
assert!(int(2) != JsValue::from_str("2"));
assert!(int(2).loose_eq(&JsValue::from_str("2")));
}
#[wasm_bindgen_test]
fn types() {
assert!(
Reflect::get(&js_sys::global(), &JsValue::from_str("Number"))
.unwrap()
.is_function()
);
assert!(JsValue::UNDEFINED.is_undefined());
assert!(JsValue::NULL.is_null());
assert!(Object::new().is_object());
assert!(JsValue::symbol(None).is_symbol());
assert!(JsValue::from_str("hi").is_string());
assert!(JsValue::bigint_from_str("5").is_bigint());
assert_eq!(int(5).js_typeof(), "number");
assert_eq!(JsValue::bigint_from_str("5").js_typeof(), "bigint");
assert_eq!(JsValue::NULL.js_typeof(), "object");
}
#[wasm_bindgen_test]
fn misc() {
assert!(JsValue::from_str("Number").js_in(&js_sys::global()));
assert!(!JsValue::from_str("frob").js_in(&js_sys::global()));
assert_eq!(int(5).unchecked_into_f64(), 5.0);
assert_eq!(JsValue::from_str("5").unchecked_into_f64(), 5.0);
assert_eq!(f64::try_from(int(5)), Ok(5.0));
assert_eq!(f64::try_from(JsValue::from_str("5")), Ok(5.0));
assert!(f64::try_from(JsValue::from_str("hi")).unwrap().is_nan());
assert!(f64::try_from(JsValue::symbol(None)).is_err());
}
fn debug(x: impl Debug) -> String {
format!("{x:?}")
}
#[wasm_bindgen_test]
fn debug_string() {
assert_eq!(debug(int(5)), "JsValue(5)");
assert_eq!(debug(JsValue::TRUE), "JsValue(true)");
assert_eq!(debug(JsValue::symbol(None)), "JsValue(Symbol)");
assert_eq!(debug(JsValue::from_str("hi")), "JsValue(\"hi\")");
}

View File

@@ -0,0 +1,24 @@
const wasm = require("wasm-bindgen-test.js");
const assert = require("assert");
exports.js_keywords_compile = () => {
assert.strictEqual(wasm._throw(1), 1);
assert.strictEqual(wasm._class(1, 2), false);
assert.strictEqual(wasm.classy(3), 3);
let obj = new wasm.Class("class");
assert.strictEqual(wasm.Class.void("string"), "string");
assert.strictEqual(obj.catch, "class");
assert.strictEqual(obj.instanceof("Class"), "class is instance of Class");
};
exports.test_keyword_1_as_fn_name = (x) => {
return wasm._throw(x);
};
exports.test_keyword_2_as_fn_name = (x, y) => {
return wasm._class(x, y);
};
exports.test_keyword_as_fn_arg = (x) => {
return wasm.classy(x);
};

View File

@@ -0,0 +1,55 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/js_keywords.js")]
extern "C" {
fn js_keywords_compile();
fn test_keyword_1_as_fn_name(x: u8) -> u8;
fn test_keyword_2_as_fn_name(x: u8, y: u8) -> bool;
fn test_keyword_as_fn_arg(x: u8) -> u8;
}
#[wasm_bindgen]
pub fn throw(class: u8) -> u8 {
class
}
#[wasm_bindgen(js_name = class)]
pub fn fn_parsed_to_keyword(instanceof: u8, catch: u8) -> bool {
instanceof > catch
}
#[wasm_bindgen(js_name = classy)]
pub fn arg_is_keyword(class: u8) -> u8 {
class
}
#[wasm_bindgen]
struct Class {
name: String,
}
#[wasm_bindgen]
impl Class {
#[wasm_bindgen(constructor)]
pub fn new(void: String) -> Self {
Class { name: void }
}
pub fn instanceof(&self, class: String) -> String {
format!("{} is instance of {}", self.name.clone(), class)
}
#[wasm_bindgen(getter)]
pub fn catch(&self) -> String {
self.name.clone()
}
pub fn void(void: String) -> String {
void
}
}
#[wasm_bindgen_test]
fn compile() {
js_keywords_compile();
assert_eq!(test_keyword_1_as_fn_name(1), 1);
assert_eq!(test_keyword_2_as_fn_name(1, 2), false);
assert_eq!(test_keyword_as_fn_arg(1), 1);
}

View File

@@ -0,0 +1,112 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
let SIMPLE_ARG = null;
exports.simple_foo = s => {
assert.strictEqual(SIMPLE_ARG, null);
SIMPLE_ARG = s;
};
exports.js_simple = () => {
assert.strictEqual(SIMPLE_ARG, null);
let sym = Symbol('test');
wasm.simple_bar(sym);
assert.strictEqual(SIMPLE_ARG, sym);
};
let OWNED_ARG = null;
exports.owned_foo = s => {
assert.strictEqual(OWNED_ARG, null);
OWNED_ARG = s;
};
exports.js_owned = () => {
assert.strictEqual(OWNED_ARG, null);
let sym = Symbol('test');
wasm.owned_bar(sym);
assert.strictEqual(OWNED_ARG, sym);
};
let CLONE_ARG = Symbol('test');
exports.clone_foo1 = s => {
assert.strictEqual(s, CLONE_ARG);
};
exports.clone_foo2 = s => {
assert.strictEqual(s, CLONE_ARG);
};
exports.clone_foo3 = s => {
assert.strictEqual(s, CLONE_ARG);
};
exports.clone_foo4 = s => {
assert.strictEqual(s, CLONE_ARG);
};
exports.clone_foo5 = s => {
assert.strictEqual(s, CLONE_ARG);
};
exports.js_clone = () => {
wasm.clone_bar(CLONE_ARG);
};
let PROMOTE_ARG = Symbol('test');
exports.promote_foo1 = s => {
assert.strictEqual(s, PROMOTE_ARG);
};
exports.promote_foo2 = s => {
assert.strictEqual(s, PROMOTE_ARG);
};
exports.promote_foo3 = s => {
assert.strictEqual(s, PROMOTE_ARG);
};
exports.promote_foo4 = s => {
assert.strictEqual(s, PROMOTE_ARG);
};
exports.js_promote = () => {
wasm.promote_bar(PROMOTE_ARG);
};
exports.returning_vector_foo = () => {
return {'foo': 'bar'};
};
exports.js_returning_vector = () => {
assert.strictEqual(wasm.returning_vector_bar().length, 10);
};
exports.js_another_vector_return = () => {
assert.deepStrictEqual(wasm.another_vector_return_get_array(), [1, 2, 3, 4, 5, 6]);
};
exports.returning_vector_string_foo = () => {
return "This is the mostest awesomest string that can possibly exist.";
};
exports.js_returning_vector_string = () => {
assert.strictEqual(wasm.returning_vector_string_bar().length, 10);
};
exports.js_another_vector_string_return = () => {
assert.deepStrictEqual(wasm.another_vector_string_return_get_array(), ["1", "2", "3", "4", "5", "6"]);
};
exports.verify_serde = function(a) {
assert.deepStrictEqual(a, {
a: 0,
b: 'foo',
c: null,
d: { a: 1 }
});
return {
a: 2,
b: 'bar',
c: { a: 3 },
d: { a: 4 },
}
};

View File

@@ -0,0 +1,184 @@
use js_sys::JsString;
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/js_objects.js")]
extern "C" {
fn simple_foo(s: &JsValue);
fn js_simple();
fn owned_foo(s: JsValue);
fn js_owned();
fn clone_foo1(s: JsValue);
fn clone_foo2(s: &JsValue);
fn clone_foo3(s: JsValue);
fn clone_foo4(s: &JsValue);
fn clone_foo5(s: JsValue);
fn js_clone();
fn promote_foo1(s: &JsValue);
fn promote_foo2(s: JsValue);
fn promote_foo3(s: &JsValue);
fn promote_foo4(s: JsValue);
fn js_promote();
fn returning_vector_foo() -> JsValue;
fn js_returning_vector();
fn js_another_vector_return();
fn returning_vector_string_foo() -> JsString;
fn js_returning_vector_string();
fn js_another_vector_string_return();
fn verify_serde(val: JsValue) -> JsValue;
}
#[wasm_bindgen]
pub fn simple_bar(s: &JsValue) {
simple_foo(s);
}
#[wasm_bindgen_test]
fn simple() {
js_simple();
}
#[wasm_bindgen]
pub fn owned_bar(s: JsValue) {
owned_foo(s);
}
#[wasm_bindgen_test]
fn owned() {
js_owned();
}
#[wasm_bindgen]
pub fn clone_bar(s: JsValue) {
clone_foo1(s.clone());
clone_foo2(&s);
clone_foo3(s.clone());
clone_foo4(&s);
clone_foo5(s);
}
#[wasm_bindgen_test]
fn clone() {
js_clone();
}
#[wasm_bindgen]
pub fn promote_bar(s: &JsValue) {
promote_foo1(s);
promote_foo2(s.clone());
promote_foo3(s);
promote_foo4(s.clone());
}
#[wasm_bindgen_test]
fn promote() {
js_promote();
}
#[wasm_bindgen]
pub fn returning_vector_bar() -> Vec<JsValue> {
let mut res = Vec::new();
for _ in 0..10 {
res.push(returning_vector_foo())
}
res
}
#[wasm_bindgen_test]
fn returning_vector() {
js_returning_vector();
}
#[wasm_bindgen]
pub fn another_vector_return_get_array() -> Vec<JsValue> {
vec![
JsValue::from(1),
JsValue::from(2),
JsValue::from(3),
JsValue::from(4),
JsValue::from(5),
JsValue::from(6),
]
}
#[wasm_bindgen_test]
fn another_vector_return() {
js_another_vector_return();
}
#[wasm_bindgen]
pub fn returning_vector_string_bar() -> Vec<JsString> {
let mut res = Vec::new();
for _ in 0..10 {
res.push(returning_vector_string_foo())
}
res
}
#[wasm_bindgen_test]
fn returning_vector_string() {
js_returning_vector_string();
}
#[wasm_bindgen]
pub fn another_vector_string_return_get_array() -> Vec<JsString> {
vec![
"1".into(),
"2".into(),
"3".into(),
"4".into(),
"5".into(),
"6".into(),
]
}
#[wasm_bindgen_test]
fn another_vector_string_return() {
js_another_vector_string_return();
}
#[cfg(feature = "serde-serialize")]
#[wasm_bindgen_test]
fn serde() {
#[derive(Deserialize, Serialize)]
pub struct SerdeFoo {
a: u32,
b: String,
c: Option<SerdeBar>,
d: SerdeBar,
}
#[derive(Deserialize, Serialize)]
pub struct SerdeBar {
a: u32,
}
let js = JsValue::from_serde("foo").unwrap();
assert_eq!(js.as_string(), Some("foo".to_string()));
let ret = verify_serde(
JsValue::from_serde(&SerdeFoo {
a: 0,
b: "foo".to_string(),
c: None,
d: SerdeBar { a: 1 },
})
.unwrap(),
);
let foo = ret.into_serde::<SerdeFoo>().unwrap();
assert_eq!(foo.a, 2);
assert_eq!(foo.b, "bar");
assert!(foo.c.is_some());
assert_eq!(foo.c.as_ref().unwrap().a, 3);
assert_eq!(foo.d.a, 4);
assert_eq!(JsValue::from("bar").into_serde::<String>().unwrap(), "bar");
assert_eq!(JsValue::undefined().into_serde::<i32>().ok(), None);
}

View File

@@ -0,0 +1,28 @@
class JsCast1 {
constructor() {
this.val = 1;
}
myval() { return this.val; }
}
class JsCast2 {
}
class JsCast3 extends JsCast1 {
constructor() {
super();
this.val = 3;
}
}
class JsCast4 extends JsCast3 {
constructor() {
super();
this.val = 4;
}
}
exports.JsCast1 = JsCast1;
exports.JsCast2 = JsCast2;
exports.JsCast3 = JsCast3;
exports.JsCast4 = JsCast4;

View File

@@ -0,0 +1,88 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/jscast.js")]
extern "C" {
type JsCast1;
#[wasm_bindgen(constructor)]
fn new() -> JsCast1;
#[wasm_bindgen(method)]
fn myval(this: &JsCast1) -> u32;
type JsCast2;
#[wasm_bindgen(constructor)]
fn new() -> JsCast2;
#[wasm_bindgen(extends = JsCast1)]
type JsCast3;
#[wasm_bindgen(constructor)]
fn new() -> JsCast3;
#[wasm_bindgen(extends = crate::jscast::JsCast1, extends = JsCast3)]
type JsCast4;
#[wasm_bindgen(constructor)]
fn new() -> JsCast4;
}
#[wasm_bindgen_test]
fn instanceof_works() {
let a = JsCast1::new();
let b = JsCast2::new();
let c = JsCast3::new();
assert!(a.is_instance_of::<JsCast1>());
assert!(!a.is_instance_of::<JsCast2>());
assert!(!a.is_instance_of::<JsCast3>());
assert!(!b.is_instance_of::<JsCast1>());
assert!(b.is_instance_of::<JsCast2>());
assert!(!b.is_instance_of::<JsCast3>());
assert!(c.is_instance_of::<JsCast1>());
assert!(!c.is_instance_of::<JsCast2>());
assert!(c.is_instance_of::<JsCast3>());
}
#[wasm_bindgen_test]
fn casting() {
let a = JsCast1::new();
let b = JsCast2::new();
let c = JsCast3::new();
assert!(a.dyn_ref::<JsCast1>().is_some());
assert!(a.dyn_ref::<JsCast2>().is_none());
assert!(a.dyn_ref::<JsCast3>().is_none());
assert!(b.dyn_ref::<JsCast1>().is_none());
assert!(b.dyn_ref::<JsCast2>().is_some());
assert!(b.dyn_ref::<JsCast3>().is_none());
assert!(c.dyn_ref::<JsCast1>().is_some());
assert!(c.dyn_ref::<JsCast2>().is_none());
assert!(c.dyn_ref::<JsCast3>().is_some());
}
#[wasm_bindgen_test]
fn method_calling() {
let a = JsCast1::new();
let b = JsCast3::new();
assert_eq!(a.myval(), 1);
assert_eq!(b.dyn_ref::<JsCast1>().unwrap().myval(), 3);
assert_eq!(b.unchecked_ref::<JsCast1>().myval(), 3);
let c: &JsCast1 = b.as_ref();
assert_eq!(c.myval(), 3);
}
#[wasm_bindgen_test]
fn multiple_layers_of_inheritance() {
let a = JsCast4::new();
assert!(a.is_instance_of::<JsCast4>());
assert!(a.is_instance_of::<JsCast3>());
assert!(a.is_instance_of::<JsCast1>());
let _: &JsCast3 = a.as_ref();
let b: &JsCast1 = a.as_ref();
assert_eq!(b.myval(), 4);
}

View File

@@ -0,0 +1,56 @@
#![cfg(target_arch = "wasm32")]
extern crate js_sys;
extern crate wasm_bindgen;
extern crate wasm_bindgen_test;
extern crate wasm_bindgen_test_crate_a;
extern crate wasm_bindgen_test_crate_b;
#[cfg(feature = "serde-serialize")]
#[macro_use]
extern crate serde_derive;
use wasm_bindgen::prelude::*;
pub mod api;
pub mod arg_names;
pub mod bigint;
pub mod char;
pub mod classes;
pub mod closures;
pub mod comments;
pub mod duplicate_deps;
pub mod duplicates;
pub mod enums;
#[path = "final.rs"]
pub mod final_;
pub mod futures;
pub mod getters_and_setters;
pub mod import_class;
pub mod imports;
pub mod intrinsics;
pub mod js_keywords;
pub mod js_objects;
pub mod jscast;
pub mod math;
pub mod no_shims;
pub mod node;
pub mod option;
pub mod optional_primitives;
pub mod result;
pub mod result_jserror;
pub mod rethrow;
pub mod simple;
pub mod slice;
pub mod structural;
pub mod truthy_falsy;
pub mod usize;
pub mod validate_prt;
pub mod variadic;
pub mod vendor_prefix;
// should not be executed
#[wasm_bindgen(start)]
pub fn start() {
panic!();
}

View File

@@ -0,0 +1,37 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.js_auto_bind_math = () => {
wasm.math(1.0, 2.0);
};
exports.roundtrip = x => x;
exports.test_js_roundtrip = () => {
assert.strictEqual(wasm.rust_roundtrip_i8(0), 0);
assert.strictEqual(wasm.rust_roundtrip_i8(0x80), -128);
assert.strictEqual(wasm.rust_roundtrip_i8(0x7f), 127);
assert.strictEqual(wasm.rust_roundtrip_i16(0), 0);
assert.strictEqual(wasm.rust_roundtrip_i16(0x8000), -32768);
assert.strictEqual(wasm.rust_roundtrip_i16(0x7fff), 32767);
assert.strictEqual(wasm.rust_roundtrip_i32(0), 0);
assert.strictEqual(wasm.rust_roundtrip_i32(0x80000000), -2147483648);
assert.strictEqual(wasm.rust_roundtrip_i32(0x7fffffff), 2147483647);
assert.strictEqual(wasm.rust_roundtrip_u8(0), 0);
assert.strictEqual(wasm.rust_roundtrip_u8(0x80), 128);
assert.strictEqual(wasm.rust_roundtrip_u8(0x7f), 127);
assert.strictEqual(wasm.rust_roundtrip_u8(0xff), 255);
assert.strictEqual(wasm.rust_roundtrip_u16(0), 0);
assert.strictEqual(wasm.rust_roundtrip_u16(0x8000), 32768);
assert.strictEqual(wasm.rust_roundtrip_u16(0x7fff), 32767);
assert.strictEqual(wasm.rust_roundtrip_u16(0xffff), 65535);
assert.strictEqual(wasm.rust_roundtrip_u32(0), 0);
assert.strictEqual(wasm.rust_roundtrip_u32(0x80000000), 2147483648);
assert.strictEqual(wasm.rust_roundtrip_u32(0x7fffffff), 2147483647);
assert.strictEqual(wasm.rust_roundtrip_u32(0xffffffff), 4294967295);
};

View File

@@ -0,0 +1,142 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/math.js")]
extern "C" {
fn js_auto_bind_math();
// There's an identity function called `roundtrip` in the module and we bind
// that one function with multiple different signatures here. Note that the
// return value is always `f64` to faithfully capture what was sent to JS
// (what we're interested in) because all JS numbers fit in `f64` anyway.
// This is testing what happens when we pass numbers to JS and what it sees.
#[wasm_bindgen(assert_no_shim, js_name = roundtrip)]
fn roundtrip_i8(a: i8) -> f64;
#[wasm_bindgen(assert_no_shim, js_name = roundtrip)]
fn roundtrip_i16(a: i16) -> f64;
#[wasm_bindgen(assert_no_shim, js_name = roundtrip)]
fn roundtrip_i32(a: i32) -> f64;
#[wasm_bindgen(assert_no_shim, js_name = roundtrip)]
fn roundtrip_u8(a: u8) -> f64;
#[wasm_bindgen(assert_no_shim, js_name = roundtrip)]
fn roundtrip_u16(a: u16) -> f64;
#[wasm_bindgen(js_name = roundtrip)]
fn roundtrip_u32(a: u32) -> f64;
fn test_js_roundtrip();
}
#[wasm_bindgen]
pub fn math(a: f32, b: f64) -> f64 {
b.acos()
+ b.asin()
+ b.atan()
+ b.atan2(b)
+ b.cbrt()
+ b.cosh()
+ b.exp_m1()
+ b.ln_1p()
+ b.sinh()
+ b.tan()
+ b.tanh()
+ b.hypot(b)
+ b.cos()
+ b.exp()
+ b.exp2()
+ b.mul_add(b, b)
+ b.ln()
+ b.log(b)
+ b.log10()
+ b.log2()
+ b.powi(8)
+ b.powf(b)
+ b.round()
+ b.sin()
+ b.abs()
+ b.signum()
+ b.floor()
+ b.ceil()
+ b.trunc()
+ b.sqrt()
+ (b % (a as f64))
+ ((a.cos()
+ a.exp()
+ a.exp2()
+ a.mul_add(a, a)
+ a.ln()
+ a.log(a)
+ a.log10()
+ a.log2()
+ a.powi(8)
+ a.powf(a)
+ a.round()
+ a.sin()
+ a.abs()
+ a.signum()
+ a.floor()
+ a.ceil()
+ a.trunc()
+ a.sqrt()
+ (a % (b as f32))) as f64)
+ (b + 2.0f64.powf(a as f64))
}
#[wasm_bindgen_test]
fn auto_bind_math() {
js_auto_bind_math();
}
macro_rules! t_roundtrip {
($f:ident($e:expr)) => {
assert_eq!($f($e), $e as f64)
};
}
#[wasm_bindgen_test]
fn limits_correct() {
t_roundtrip!(roundtrip_i8(i8::min_value()));
t_roundtrip!(roundtrip_i8(0));
t_roundtrip!(roundtrip_i8(i8::max_value()));
t_roundtrip!(roundtrip_i16(i16::min_value()));
t_roundtrip!(roundtrip_i16(0));
t_roundtrip!(roundtrip_i16(i16::max_value()));
t_roundtrip!(roundtrip_i32(i32::min_value()));
t_roundtrip!(roundtrip_i32(0));
t_roundtrip!(roundtrip_i32(i32::max_value()));
t_roundtrip!(roundtrip_u8(u8::min_value()));
t_roundtrip!(roundtrip_u8(0));
t_roundtrip!(roundtrip_u8(u8::max_value()));
t_roundtrip!(roundtrip_u16(u16::min_value()));
t_roundtrip!(roundtrip_u16(0));
t_roundtrip!(roundtrip_u16(u16::max_value()));
t_roundtrip!(roundtrip_u32(u32::min_value()));
t_roundtrip!(roundtrip_u32(0));
t_roundtrip!(roundtrip_u32(u32::max_value()));
test_js_roundtrip();
#[wasm_bindgen]
pub fn rust_roundtrip_i8(a: i8) -> i8 {
a
}
#[wasm_bindgen]
pub fn rust_roundtrip_i16(a: i16) -> i16 {
a
}
#[wasm_bindgen]
pub fn rust_roundtrip_i32(a: i32) -> i32 {
a
}
#[wasm_bindgen]
pub fn rust_roundtrip_u8(a: u8) -> u8 {
a
}
#[wasm_bindgen]
pub fn rust_roundtrip_u16(a: u16) -> u16 {
a
}
#[wasm_bindgen]
pub fn rust_roundtrip_u32(a: u32) -> u32 {
a
}
}

View File

@@ -0,0 +1,152 @@
//! A collection of tests to exercise imports where we don't need to generate a
//! JS shim to convert arguments/returns even when Web IDL bindings is not
//! implemented.
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(inline_js = "
function assert_eq(a, b) {
if (a !== b) {
throw new Error(`assert_eq failed: ${a} != ${b}`);
}
}
module.exports.trivial = function () {};
module.exports.incoming_bool = function () { return true; };
module.exports.incoming_u8 = function () { return 255; };
module.exports.incoming_i8 = function () { return -127; };
module.exports.incoming_u16 = function () { return 65535; };
module.exports.incoming_i16 = function () { return 32767; };
module.exports.incoming_u32 = function () { return 4294967295; };
module.exports.incoming_i32 = function () { return 0; };
module.exports.incoming_f32 = function () { return 1.5; };
module.exports.incoming_f64 = function () { return 13.37; };
module.exports.outgoing_u8 = function (k) { assert_eq(k, 255); };
module.exports.outgoing_i8 = function (i) { assert_eq(i, -127); };
module.exports.outgoing_u16 = function (l) { assert_eq(l, 65535); };
module.exports.outgoing_i16 = function (j) { assert_eq(j, 32767); };
module.exports.outgoing_i32 = function (x) { assert_eq(x, 0); };
module.exports.outgoing_f32 = function (y) { assert_eq(y, 1.5); };
module.exports.outgoing_f64 = function (z) { assert_eq(z, 13.37); };
module.exports.many = function (x, y, z) {
assert_eq(x, 0);
assert_eq(y, 1.5);
assert_eq(z, 13.37);
return 42;
};
module.exports.works_when_externref_support_is_enabled = function (v) {
assert_eq(v, 'hello');
return v;
};
module.exports.MyNamespace = {};
module.exports.MyNamespace.incoming_namespaced = function () { return 3.14; };
module.exports.MyNamespace.outgoing_namespaced = function (pi) { assert_eq(3.14, pi); };
")]
extern "C" {
#[wasm_bindgen(assert_no_shim)]
fn trivial();
#[wasm_bindgen(assert_no_shim)]
fn incoming_bool() -> bool;
#[wasm_bindgen(assert_no_shim)]
fn incoming_u8() -> u8;
#[wasm_bindgen(assert_no_shim)]
fn incoming_i8() -> i8;
#[wasm_bindgen(assert_no_shim)]
fn incoming_u16() -> u16;
#[wasm_bindgen(assert_no_shim)]
fn incoming_i16() -> i16;
#[wasm_bindgen(assert_no_shim)]
fn incoming_u32() -> u32;
#[wasm_bindgen(assert_no_shim)]
fn incoming_i32() -> i32;
#[wasm_bindgen(assert_no_shim)]
fn incoming_f32() -> f32;
#[wasm_bindgen(assert_no_shim)]
fn incoming_f64() -> f64;
#[wasm_bindgen(assert_no_shim)]
fn outgoing_u8(k: u8);
#[wasm_bindgen(assert_no_shim)]
fn outgoing_i8(i: i8);
#[wasm_bindgen(assert_no_shim)]
fn outgoing_u16(l: u16);
#[wasm_bindgen(assert_no_shim)]
fn outgoing_i16(j: i16);
#[wasm_bindgen(assert_no_shim)]
fn outgoing_i32(x: i32);
#[wasm_bindgen(assert_no_shim)]
fn outgoing_f32(y: f32);
#[wasm_bindgen(assert_no_shim)]
fn outgoing_f64(z: f64);
#[wasm_bindgen(assert_no_shim)]
fn many(x: i32, y: f32, z: f64) -> i32;
#[wasm_bindgen(assert_no_shim, js_namespace = MyNamespace)]
fn incoming_namespaced() -> f64;
#[wasm_bindgen(assert_no_shim, js_namespace = MyNamespace)]
fn outgoing_namespaced(x: f64);
// Note that this should only skip the JS shim if we have externref support
// enabled.
//
// #[wasm_bindgen(assert_no_shim)]
fn works_when_externref_support_is_enabled(v: JsValue) -> JsValue;
}
#[wasm_bindgen_test]
fn no_shims() {
trivial();
let k = incoming_u8();
assert_eq!(k, 255);
outgoing_u8(k);
let l = incoming_u16();
assert_eq!(l, 65535);
outgoing_u16(l);
let m = incoming_u32();
assert_eq!(m, 4294967295);
let i = incoming_i8();
assert_eq!(i, -127);
outgoing_i8(i);
let j = incoming_i16();
assert_eq!(j, 32767);
outgoing_i16(j);
let x = incoming_i32();
assert_eq!(x, 0);
outgoing_i32(x);
let y = incoming_f32();
assert_eq!(y, 1.5);
outgoing_f32(y);
let z = incoming_f64();
assert_eq!(z, 13.37);
outgoing_f64(z);
let w = many(x, y, z);
assert_eq!(w, 42);
let pi = incoming_namespaced();
assert_eq!(pi, 3.14);
outgoing_namespaced(pi);
let b = incoming_bool();
assert!(b);
let v = JsValue::from("hello");
let vv = works_when_externref_support_is_enabled(v.clone());
assert_eq!(v, vv);
}

View File

@@ -0,0 +1,37 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
var called = false;
exports.hit = function() {
called = true;
};
exports.FOO = 1.0;
exports.test_works = function() {
assert.strictEqual(called, true);
var r = wasm.Foo.new();
assert.strictEqual(r.add(0), 0);
assert.strictEqual(r.add(1), 1);
assert.strictEqual(r.add(2), 3);
r.free();
var r2 = wasm.Foo.with_contents(10);
assert.strictEqual(r2.add(0), 10);
assert.strictEqual(r2.add(1), 11);
assert.strictEqual(r2.add(2), 13);
r2.free();
assert.strictEqual(wasm.Color.Green, 0);
assert.strictEqual(wasm.Color.Yellow, 1);
assert.strictEqual(wasm.Color.Red, 2);
assert.strictEqual(wasm.Color[0], 'Green');
assert.strictEqual(wasm.Color[1], 'Yellow');
assert.strictEqual(wasm.Color[2], 'Red');
assert.strictEqual(Object.keys(wasm.Color).length, 6);
assert.strictEqual(wasm.cycle(wasm.Color.Green), wasm.Color.Yellow);
wasm.node_math(1.0, 2.0);
};

View File

@@ -0,0 +1,105 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/node.js")]
extern "C" {
fn test_works();
static FOO: JsValue;
fn hit();
}
#[wasm_bindgen_test]
fn works() {
hit();
assert_eq!(FOO.as_f64(), Some(1.0));
test_works();
}
#[wasm_bindgen]
pub struct Foo {
contents: u32,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Foo {
Foo::with_contents(0)
}
pub fn with_contents(a: u32) -> Foo {
Foo { contents: a }
}
pub fn add(&mut self, amt: u32) -> u32 {
self.contents += amt;
self.contents
}
}
#[wasm_bindgen]
pub enum Color {
Green,
Yellow,
Red,
}
#[wasm_bindgen]
pub fn cycle(color: Color) -> Color {
match color {
Color::Green => Color::Yellow,
Color::Yellow => Color::Red,
Color::Red => Color::Green,
}
}
#[wasm_bindgen]
pub fn node_math(a: f32, b: f64) -> f64 {
b.acos()
+ b.asin()
+ b.atan()
+ b.atan2(b)
+ b.cbrt()
+ b.cosh()
+ b.exp_m1()
+ b.ln_1p()
+ b.sinh()
+ b.tan()
+ b.tanh()
+ b.hypot(b)
+ b.cos()
+ b.exp()
+ b.exp2()
+ b.mul_add(b, b)
+ b.ln()
+ b.log(b)
+ b.log10()
+ b.log2()
+ b.powi(8)
+ b.powf(b)
+ b.round()
+ b.sin()
+ b.abs()
+ b.signum()
+ b.floor()
+ b.ceil()
+ b.trunc()
+ b.sqrt()
+ (b % (a as f64))
+ ((a.cos()
+ a.exp()
+ a.exp2()
+ a.mul_add(a, a)
+ a.ln()
+ a.log(a)
+ a.log10()
+ a.log2()
+ a.powi(8)
+ a.powf(a)
+ a.round()
+ a.sin()
+ a.abs()
+ a.signum()
+ a.floor()
+ a.ceil()
+ a.trunc()
+ a.sqrt()
+ (a % (b as f32))) as f64)
+ (b + 2.0f64.powf(a as f64))
}

View File

@@ -0,0 +1,28 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
class MyType {
}
exports.MyType = MyType;
exports.take_none_byval = x => {
assert.strictEqual(x, undefined);
};
exports.take_some_byval = x => {
assert.ok(x !== null && x !== undefined);
assert.ok(x instanceof MyType);
};
exports.return_undef_byval = () => undefined;
exports.return_null_byval = () => null;
exports.return_some_byval = () => new MyType();
exports.test_option_values = () => {
wasm.rust_take_none_byval(null);
wasm.rust_take_none_byval(undefined);
wasm.rust_take_some_byval(new MyType());
assert.strictEqual(wasm.rust_return_none_byval(), undefined);
const x = wasm.rust_return_some_byval();
assert.ok(x !== null && x !== undefined);
assert.ok(x instanceof MyType);
};

View File

@@ -0,0 +1,61 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/option.js")]
extern "C" {
pub type MyType;
#[wasm_bindgen(constructor)]
fn new() -> MyType;
fn take_none_byval(t: Option<MyType>);
fn take_some_byval(t: Option<MyType>);
fn return_undef_byval() -> Option<MyType>;
fn return_null_byval() -> Option<MyType>;
fn return_some_byval() -> Option<MyType>;
fn test_option_values();
#[wasm_bindgen(js_name = take_none_byval)]
fn take_none_byref(t: Option<&MyType>);
#[wasm_bindgen(js_name = take_some_byval)]
fn take_some_byref(t: Option<&MyType>);
}
#[wasm_bindgen_test]
fn import_by_value() {
take_none_byval(None);
take_some_byval(Some(MyType::new()));
assert!(return_null_byval().is_none());
assert!(return_undef_byval().is_none());
assert!(return_some_byval().is_some());
}
#[wasm_bindgen_test]
fn export_by_value() {
test_option_values();
}
#[wasm_bindgen]
pub fn rust_take_none_byval(t: Option<MyType>) {
assert!(t.is_none());
}
#[wasm_bindgen]
pub fn rust_take_some_byval(t: Option<MyType>) {
assert!(t.is_some());
}
#[wasm_bindgen]
pub fn rust_return_none_byval() -> Option<MyType> {
None
}
#[wasm_bindgen]
pub fn rust_return_some_byval() -> Option<MyType> {
Some(MyType::new())
}
#[wasm_bindgen_test]
fn import_by_ref() {
take_none_byref(None);
take_some_byref(Some(&MyType::new()));
}

View File

@@ -0,0 +1,102 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.optional_i32_js_identity = a => a;
exports.optional_u32_js_identity = a => a;
exports.optional_isize_js_identity = a => a;
exports.optional_usize_js_identity = a => a;
exports.optional_f32_js_identity = a => a;
exports.optional_f64_js_identity = a => a;
exports.optional_i8_js_identity = a => a;
exports.optional_u8_js_identity = a => a;
exports.optional_i16_js_identity = a => a;
exports.optional_u16_js_identity = a => a;
exports.optional_i64_js_identity = a => a;
exports.optional_u64_js_identity = a => a;
exports.optional_bool_js_identity = a => a;
exports.optional_char_js_identity = a => a;
exports.js_works = () => {
assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_none()), undefined);
assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_zero()), 0);
assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_one()), 1);
assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_neg_one()), -1);
assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_min()), -2147483648);
assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_max()), 2147483647);
assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_none()), undefined);
assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_zero()), 0);
assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_one()), 1);
assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_min()), 0);
assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_max()), 4294967295);
assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_none()), undefined);
assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_zero()), 0);
assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_one()), 1);
assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_neg_one()), -1);
assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_min()), -2147483648);
assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_max()), 2147483647);
assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_none()), undefined);
assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_zero()), 0);
assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_one()), 1);
assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_min()), 0);
assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_max()), 4294967295);
assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_none()), undefined);
assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_zero()), 0);
assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_one()), 1);
assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_neg_one()), -1);
assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_none()), undefined);
assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_zero()), 0);
assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_one()), 1);
assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_neg_one()), -1);
assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_none()), undefined);
assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_zero()), 0);
assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_one()), 1);
assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_neg_one()), -1);
assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_min()), -128);
assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_max()), 127);
assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_none()), undefined);
assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_zero()), 0);
assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_one()), 1);
assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_min()), 0);
assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_max()), 255);
assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_none()), undefined);
assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_zero()), 0);
assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_one()), 1);
assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_neg_one()), -1);
assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_min()), -32768);
assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_max()), 32767);
assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_none()), undefined);
assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_zero()), 0);
assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_one()), 1);
assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_min()), 0);
assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_max()), 65535);
assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_none()), undefined);
assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_zero()), BigInt('0'));
assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_one()), BigInt('1'));
assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_neg_one()), BigInt('-1'));
assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_min()), BigInt('-9223372036854775808'));
assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_max()), BigInt('9223372036854775807'));
assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_none()), undefined);
assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_zero()), BigInt('0'));
assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_one()), BigInt('1'));
assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_min()), BigInt('0'));
assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_max()), BigInt('18446744073709551615'));
assert.strictEqual(wasm.optional_bool_identity(wasm.optional_bool_none()), undefined);
assert.strictEqual(wasm.optional_bool_identity(wasm.optional_bool_false()), false);
assert.strictEqual(wasm.optional_bool_identity(wasm.optional_bool_true()), true);
assert.strictEqual(wasm.optional_char_identity(wasm.optional_char_none()), undefined);
assert.strictEqual(wasm.optional_char_identity(wasm.optional_char_letter()), 'a');
assert.strictEqual(wasm.optional_char_identity(wasm.optional_char_face()), '😀');
};

View File

@@ -0,0 +1,442 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/optional_primitives.js")]
extern "C" {
fn optional_i32_js_identity(a: Option<i32>) -> Option<i32>;
fn optional_u32_js_identity(a: Option<u32>) -> Option<u32>;
fn optional_isize_js_identity(a: Option<isize>) -> Option<isize>;
fn optional_usize_js_identity(a: Option<usize>) -> Option<usize>;
fn optional_f32_js_identity(a: Option<f32>) -> Option<f32>;
fn optional_f64_js_identity(a: Option<f64>) -> Option<f64>;
fn optional_i8_js_identity(a: Option<i8>) -> Option<i8>;
fn optional_u8_js_identity(a: Option<u8>) -> Option<u8>;
fn optional_i16_js_identity(a: Option<i16>) -> Option<i16>;
fn optional_u16_js_identity(a: Option<u16>) -> Option<u16>;
fn optional_i64_js_identity(a: Option<i64>) -> Option<i64>;
fn optional_u64_js_identity(a: Option<u64>) -> Option<u64>;
fn optional_bool_js_identity(a: Option<bool>) -> Option<bool>;
fn optional_char_js_identity(a: Option<char>) -> Option<char>;
fn js_works();
}
#[wasm_bindgen]
pub fn optional_i32_none() -> Option<i32> {
None
}
#[wasm_bindgen]
pub fn optional_i32_zero() -> Option<i32> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_i32_one() -> Option<i32> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_i32_neg_one() -> Option<i32> {
Some(-1)
}
#[wasm_bindgen]
pub fn optional_i32_min() -> Option<i32> {
Some(i32::min_value())
}
#[wasm_bindgen]
pub fn optional_i32_max() -> Option<i32> {
Some(i32::max_value())
}
#[wasm_bindgen]
pub fn optional_i32_identity(a: Option<i32>) -> Option<i32> {
optional_i32_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_u32_none() -> Option<u32> {
None
}
#[wasm_bindgen]
pub fn optional_u32_zero() -> Option<u32> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_u32_one() -> Option<u32> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_u32_min() -> Option<u32> {
Some(u32::min_value())
}
#[wasm_bindgen]
pub fn optional_u32_max() -> Option<u32> {
Some(u32::max_value())
}
#[wasm_bindgen]
pub fn optional_u32_identity(a: Option<u32>) -> Option<u32> {
optional_u32_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_isize_none() -> Option<isize> {
None
}
#[wasm_bindgen]
pub fn optional_isize_zero() -> Option<isize> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_isize_one() -> Option<isize> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_isize_neg_one() -> Option<isize> {
Some(-1)
}
#[wasm_bindgen]
pub fn optional_isize_min() -> Option<isize> {
Some(isize::min_value())
}
#[wasm_bindgen]
pub fn optional_isize_max() -> Option<isize> {
Some(isize::max_value())
}
#[wasm_bindgen]
pub fn optional_isize_identity(a: Option<isize>) -> Option<isize> {
optional_isize_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_usize_none() -> Option<usize> {
None
}
#[wasm_bindgen]
pub fn optional_usize_zero() -> Option<usize> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_usize_one() -> Option<usize> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_usize_min() -> Option<usize> {
Some(usize::min_value())
}
#[wasm_bindgen]
pub fn optional_usize_max() -> Option<usize> {
Some(usize::max_value())
}
#[wasm_bindgen]
pub fn optional_usize_identity(a: Option<usize>) -> Option<usize> {
optional_usize_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_f32_none() -> Option<f32> {
None
}
#[wasm_bindgen]
pub fn optional_f32_zero() -> Option<f32> {
Some(0f32)
}
#[wasm_bindgen]
pub fn optional_f32_one() -> Option<f32> {
Some(1f32)
}
#[wasm_bindgen]
pub fn optional_f32_neg_one() -> Option<f32> {
Some(-1f32)
}
#[wasm_bindgen]
pub fn optional_f32_identity(a: Option<f32>) -> Option<f32> {
optional_f32_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_f64_none() -> Option<f64> {
None
}
#[wasm_bindgen]
pub fn optional_f64_zero() -> Option<f64> {
Some(0f64)
}
#[wasm_bindgen]
pub fn optional_f64_one() -> Option<f64> {
Some(1f64)
}
#[wasm_bindgen]
pub fn optional_f64_neg_one() -> Option<f64> {
Some(-1f64)
}
#[wasm_bindgen]
pub fn optional_f64_identity(a: Option<f64>) -> Option<f64> {
optional_f64_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_i8_none() -> Option<i8> {
None
}
#[wasm_bindgen]
pub fn optional_i8_zero() -> Option<i8> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_i8_one() -> Option<i8> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_i8_neg_one() -> Option<i8> {
Some(-1)
}
#[wasm_bindgen]
pub fn optional_i8_min() -> Option<i8> {
Some(i8::min_value())
}
#[wasm_bindgen]
pub fn optional_i8_max() -> Option<i8> {
Some(i8::max_value())
}
#[wasm_bindgen]
pub fn optional_i8_identity(a: Option<i8>) -> Option<i8> {
optional_i8_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_u8_none() -> Option<u8> {
None
}
#[wasm_bindgen]
pub fn optional_u8_zero() -> Option<u8> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_u8_one() -> Option<u8> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_u8_min() -> Option<u8> {
Some(u8::min_value())
}
#[wasm_bindgen]
pub fn optional_u8_max() -> Option<u8> {
Some(u8::max_value())
}
#[wasm_bindgen]
pub fn optional_u8_identity(a: Option<u8>) -> Option<u8> {
optional_u8_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_i16_none() -> Option<i16> {
None
}
#[wasm_bindgen]
pub fn optional_i16_zero() -> Option<i16> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_i16_one() -> Option<i16> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_i16_neg_one() -> Option<i16> {
Some(-1)
}
#[wasm_bindgen]
pub fn optional_i16_min() -> Option<i16> {
Some(i16::min_value())
}
#[wasm_bindgen]
pub fn optional_i16_max() -> Option<i16> {
Some(i16::max_value())
}
#[wasm_bindgen]
pub fn optional_i16_identity(a: Option<i16>) -> Option<i16> {
optional_i16_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_u16_none() -> Option<u16> {
None
}
#[wasm_bindgen]
pub fn optional_u16_zero() -> Option<u16> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_u16_one() -> Option<u16> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_u16_min() -> Option<u16> {
Some(u16::min_value())
}
#[wasm_bindgen]
pub fn optional_u16_max() -> Option<u16> {
Some(u16::max_value())
}
#[wasm_bindgen]
pub fn optional_u16_identity(a: Option<u16>) -> Option<u16> {
optional_u16_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_i64_none() -> Option<i64> {
None
}
#[wasm_bindgen]
pub fn optional_i64_zero() -> Option<i64> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_i64_one() -> Option<i64> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_i64_neg_one() -> Option<i64> {
Some(-1)
}
#[wasm_bindgen]
pub fn optional_i64_min() -> Option<i64> {
Some(i64::min_value())
}
#[wasm_bindgen]
pub fn optional_i64_max() -> Option<i64> {
Some(i64::max_value())
}
#[wasm_bindgen]
pub fn optional_i64_identity(a: Option<i64>) -> Option<i64> {
optional_i64_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_u64_none() -> Option<u64> {
None
}
#[wasm_bindgen]
pub fn optional_u64_zero() -> Option<u64> {
Some(0)
}
#[wasm_bindgen]
pub fn optional_u64_one() -> Option<u64> {
Some(1)
}
#[wasm_bindgen]
pub fn optional_u64_min() -> Option<u64> {
Some(u64::min_value())
}
#[wasm_bindgen]
pub fn optional_u64_max() -> Option<u64> {
Some(u64::max_value())
}
#[wasm_bindgen]
pub fn optional_u64_identity(a: Option<u64>) -> Option<u64> {
optional_u64_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_bool_none() -> Option<bool> {
None
}
#[wasm_bindgen]
pub fn optional_bool_false() -> Option<bool> {
Some(false)
}
#[wasm_bindgen]
pub fn optional_bool_true() -> Option<bool> {
Some(true)
}
#[wasm_bindgen]
pub fn optional_bool_identity(a: Option<bool>) -> Option<bool> {
optional_bool_js_identity(a)
}
#[wasm_bindgen]
pub fn optional_char_none() -> Option<char> {
None
}
#[wasm_bindgen]
pub fn optional_char_letter() -> Option<char> {
Some('a')
}
#[wasm_bindgen]
pub fn optional_char_face() -> Option<char> {
Some('😀')
}
#[wasm_bindgen]
pub fn optional_char_identity(a: Option<char>) -> Option<char> {
optional_char_js_identity(a)
}
#[wasm_bindgen_test]
fn works() {
js_works();
}

View File

@@ -0,0 +1,126 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.error_new = function(message) {
return new Error(message)
}
exports.call_ok = function() {
assert.doesNotThrow(() => {
let five = wasm.return_my_ok();
assert.strictEqual(five, 5);
})
}
exports.call_err = function() {
assert.throws(() => wasm.return_my_err(), {
message: "MyError::Variant"
});
}
function check_inflight(struct) {
assert.strictEqual(struct.is_inflight(), false);
}
exports.all_struct_methods = function() {
let struct;
assert.throws(() => wasm.Struct.new_err(), {
message: "MyError::Variant"
});
assert.doesNotThrow(() => {
struct = wasm.Struct.new();
});
check_inflight(struct);
assert.doesNotThrow(() => {
let five = struct.return_ok();
assert.strictEqual(five, 5);
});
check_inflight(struct);
assert.throws(() => struct.return_err(), {
message: "MyError::Variant"
});
check_inflight(struct);
}
exports.call_return_string = function() {
assert.doesNotThrow(() => {
let ok = wasm.return_string();
assert.strictEqual(ok, "string here");
})
}
exports.call_jsvalue_ok = function() {
assert.doesNotThrow(() => {
let five = wasm.return_jsvalue_ok();
assert.strictEqual(five, 5);
})
}
exports.call_jsvalue_err = function() {
try {
wasm.return_jsvalue_err();
assert.fail("should have thrown");
} catch (e) {
assert.strictEqual(e, -1);
}
}
exports.call_string_ok = function() {
assert.doesNotThrow(() => {
let ok = wasm.return_string_ok();
assert.strictEqual(ok, "Ok");
})
}
exports.call_string_err = function() {
// the behaviour of Result<String, _> is so finicky that it's not obvious
// how to to reproduce reliably but also pass the test suite.
assert.throws(() => e = wasm.return_string_err(), e => {
// one thing we can do (uncomment to test)
// is to throw an error in here.
// throw new Error("should not cause a SIGBUS in Node")
return e === "Er";
});
}
exports.call_enum_ok = function() {
assert.doesNotThrow(() => {
let ok = wasm.return_enum_ok();
assert.strictEqual(ok, 2);
})
}
exports.call_enum_err = function() {
assert.throws(() => {
wasm.return_enum_err();
}, {
message: "MyError::Variant"
})
}
exports.call_unit = function() {
assert.doesNotThrow(() => {
wasm.return_unit_ok();
});
assert.throws(() => {
wasm.return_unit_err();
}, {
message: "MyError::Variant"
});
}
exports.call_option = function() {
assert.doesNotThrow(() => {
let o = wasm.return_option_ok_some();
assert.strictEqual(o, 10.0);
});
assert.doesNotThrow(() => {
let o = wasm.return_option_ok_none();
assert.strictEqual(o, undefined);
});
assert.throws(() => {
wasm.return_option_err();
}, {
message: "MyError::Variant"
});
}

View File

@@ -0,0 +1,190 @@
use std::fmt;
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[derive(Clone, Debug)]
pub enum MyError {
Variant,
InflightShouldBeFalse,
}
// shouldn't technically need this, surely
impl std::error::Error for MyError {}
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "MyError::{:?}", self)
}
}
#[wasm_bindgen(module = "tests/wasm/result.js")]
extern "C" {
fn error_new(message: &str) -> JsValue;
}
impl Into<JsValue> for MyError {
fn into(self) -> JsValue {
error_new(&format!("{}", self))
}
}
macro_rules! call_test {
($test_fn:ident, $js_fn:ident) => {
#[wasm_bindgen_test]
fn $test_fn() {
#[wasm_bindgen(module = "tests/wasm/result.js")]
extern "C" {
fn $js_fn();
}
$js_fn();
}
};
}
#[wasm_bindgen]
pub fn return_my_err() -> Result<i32, MyError> {
let e = Err(MyError::Variant)?;
Ok(e)
}
call_test!(test_err, call_err);
#[wasm_bindgen]
pub fn return_my_ok() -> Result<i32, MyError> {
Ok(5)
}
call_test!(test_ok, call_ok);
#[wasm_bindgen]
pub struct Struct {
inflight: bool,
}
call_test!(test_struct, all_struct_methods);
struct ResetOnDrop<'a> {
flag: &'a mut bool,
}
impl<'a> Drop for ResetOnDrop<'a> {
fn drop(&mut self) {
*self.flag = false;
}
}
impl<'a> ResetOnDrop<'a> {
fn new(flag: &'a mut bool) -> Result<Self, MyError> {
if *flag {
return Err(MyError::InflightShouldBeFalse);
}
Ok(Self { flag })
}
}
#[wasm_bindgen]
impl Struct {
#[wasm_bindgen]
pub fn new() -> Result<Struct, MyError> {
Ok(Struct { inflight: false })
}
#[wasm_bindgen]
pub fn new_err() -> Result<Struct, MyError> {
Err(MyError::Variant.into())
}
#[wasm_bindgen]
pub fn return_ok(&mut self) -> Result<i32, MyError> {
let _guard = ResetOnDrop::new(&mut self.inflight)?;
Ok(5)
}
#[wasm_bindgen]
pub fn return_err(&mut self) -> Result<i32, MyError> {
let guard = ResetOnDrop::new(&mut self.inflight)?;
let err = Err(MyError::Variant);
let nope = err?;
// we are checking both for the flag being reset (from js, via is_inflight)
// and for the running of drop code
drop(guard);
Ok(nope)
}
#[wasm_bindgen]
pub fn is_inflight(&self) -> bool {
self.inflight
}
}
// check some more Ok types
#[wasm_bindgen]
pub fn return_string() -> Result<String, MyError> {
Ok("string here".into())
}
call_test!(test_return_string, call_return_string);
// now we check that jsvalue works, as it did before
#[wasm_bindgen]
pub fn return_jsvalue_ok() -> Result<i32, JsValue> {
Ok(5)
}
call_test!(test_jsvalue_ok, call_jsvalue_ok);
#[wasm_bindgen]
pub fn return_jsvalue_err() -> Result<i32, JsValue> {
Err(JsValue::from(-1i32))
}
call_test!(test_jsvalue_err, call_jsvalue_err);
// test strings (they have a deferred free, in a finally block: tricky)
#[wasm_bindgen]
pub fn return_string_ok() -> Result<String, String> {
Ok("Ok".into())
}
call_test!(test_string_ok, call_string_ok);
#[wasm_bindgen]
pub fn return_string_err() -> Result<String, String> {
Err("Er".into())
}
call_test!(test_string_err, call_string_err);
// test enums
#[wasm_bindgen]
pub enum MyEnum {
One = 1,
Two = 2,
}
#[wasm_bindgen]
pub fn return_enum_ok() -> Result<MyEnum, MyError> {
Ok(MyEnum::Two)
}
call_test!(test_enum_ok, call_enum_ok);
#[wasm_bindgen]
pub fn return_enum_err() -> Result<MyEnum, MyError> {
Err(MyError::Variant)
}
call_test!(test_enum_err, call_enum_err);
// T = Unit
#[wasm_bindgen]
pub fn return_unit_ok() -> Result<(), MyError> {
Ok(())
}
#[wasm_bindgen]
pub fn return_unit_err() -> Result<(), MyError> {
Err(MyError::Variant)
}
call_test!(test_unit, call_unit);
// T = Option<f64>
#[wasm_bindgen]
pub fn return_option_ok_some() -> Result<Option<f64>, MyError> {
Ok(Some(10f64))
}
#[wasm_bindgen]
pub fn return_option_ok_none() -> Result<Option<f64>, MyError> {
Ok(None)
}
#[wasm_bindgen]
pub fn return_option_err() -> Result<Option<f64>, MyError> {
Err(MyError::Variant)
}
call_test!(test_option, call_option);

View File

@@ -0,0 +1,54 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.call_ok = function() {
assert.doesNotThrow(() => {
let five = wasm.return_ok();
assert.strictEqual(five, 5);
})
}
exports.call_err = function() {
assert.throws(() => wasm.return_err(), {
message: "MyError::Variant"
});
}
exports.call_make_an_error = function() {
assert.doesNotThrow(() => {
let e = wasm.make_an_error()
assert.strictEqual(e.message, "un-thrown error");
});
}
function check_inflight(struct) {
assert.strictEqual(struct.is_inflight(), false);
}
exports.all_struct_methods = function() {
let struct;
assert.throws(() => wasm.MyStruct.new_err(), {
message: "MyError::Variant"
});
assert.doesNotThrow(() => {
struct = wasm.MyStruct.new();
});
check_inflight(struct);
assert.doesNotThrow(() => {
let five = struct.return_ok();
assert.strictEqual(five, 5);
});
check_inflight(struct);
assert.throws(() => struct.return_err(), {
message: "MyError::Variant"
});
check_inflight(struct);
}
exports.call_return_string = function() {
assert.doesNotThrow(() => {
let ok = wasm.jserror_return_string();
assert.strictEqual(ok, "string here");
})
}

View File

@@ -0,0 +1,118 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsError;
use wasm_bindgen_test::*;
use std::fmt;
#[derive(Clone, Debug)]
enum MyError {
Variant,
InflightShouldBeFalse,
}
// shouldn't technically need this, surely
impl std::error::Error for MyError {}
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "MyError::{:?}", self)
}
}
macro_rules! call_test {
($test_fn:ident, $js_fn:ident) => {
#[wasm_bindgen_test]
fn $test_fn() {
#[wasm_bindgen(module = "tests/wasm/result_jserror.js")]
extern "C" {
fn $js_fn();
}
$js_fn();
}
};
}
#[wasm_bindgen]
pub fn return_err() -> Result<i32, JsError> {
let e = Err(MyError::Variant)?;
Ok(e)
}
call_test!(test_err, call_err);
#[wasm_bindgen]
pub fn return_ok() -> Result<i32, JsError> {
Ok(5)
}
call_test!(test_ok, call_ok);
#[wasm_bindgen]
pub fn make_an_error() -> JsError {
JsError::new("un-thrown error").into()
}
call_test!(test_make_an_error, call_make_an_error);
#[wasm_bindgen]
pub struct MyStruct {
inflight: bool,
}
call_test!(test_struct, all_struct_methods);
struct ResetOnDrop<'a> {
flag: &'a mut bool,
}
impl<'a> Drop for ResetOnDrop<'a> {
fn drop(&mut self) {
*self.flag = false;
}
}
impl<'a> ResetOnDrop<'a> {
fn new(flag: &'a mut bool) -> Result<Self, MyError> {
if *flag {
return Err(MyError::InflightShouldBeFalse);
}
Ok(Self { flag })
}
}
#[wasm_bindgen]
impl MyStruct {
#[wasm_bindgen]
pub fn new() -> Result<MyStruct, JsError> {
Ok(MyStruct { inflight: false })
}
#[wasm_bindgen]
pub fn new_err() -> Result<MyStruct, JsError> {
Err(MyError::Variant.into())
}
#[wasm_bindgen]
pub fn return_ok(&mut self) -> Result<i32, JsError> {
let _guard = ResetOnDrop::new(&mut self.inflight)?;
Ok(5)
}
#[wasm_bindgen]
pub fn return_err(&mut self) -> Result<i32, JsError> {
let guard = ResetOnDrop::new(&mut self.inflight)?;
let err = Err(MyError::Variant);
let nope = err?;
// we are checking both for the flag being reset (from js, via is_inflight)
// and for the running of drop code
drop(guard);
Ok(nope)
}
#[wasm_bindgen]
pub fn is_inflight(&self) -> bool {
self.inflight
}
}
// check some more Ok types
#[wasm_bindgen]
pub fn jserror_return_string() -> Result<String, JsError> {
Ok("string here".into())
}
call_test!(test_return_string, call_return_string);

View File

@@ -0,0 +1,14 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.call_throw_one = function() {
try {
wasm.throw_one();
} catch (e) {
assert.strictEqual(e, 1);
}
};
exports.call_ok = function() {
wasm.nothrow();
};

View File

@@ -0,0 +1,28 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/rethrow.js")]
extern "C" {
fn call_throw_one();
fn call_ok();
}
#[wasm_bindgen_test]
fn err_works() {
call_throw_one();
}
#[wasm_bindgen]
pub fn throw_one() -> Result<u32, JsValue> {
Err(1.into())
}
#[wasm_bindgen_test]
fn ok_works() {
call_ok();
}
#[wasm_bindgen]
pub fn nothrow() -> Result<u32, JsValue> {
Ok(1)
}

View File

@@ -0,0 +1,107 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');
exports.test_add = function() {
assert.strictEqual(wasm.simple_add(1, 2), 3);
assert.strictEqual(wasm.simple_add(2, 3), 5);
assert.strictEqual(wasm.simple_add3(2), 5);
assert.strictEqual(wasm.simple_get2(true), 2);
assert.strictEqual(wasm.simple_return_and_take_bool(true, false), false);
};
exports.test_string_arguments = function() {
wasm.simple_assert_foo("foo");
wasm.simple_assert_foo_and_bar("foo2", "bar");
};
exports.test_return_a_string = function() {
assert.strictEqual(wasm.simple_clone("foo"), "foo");
assert.strictEqual(wasm.simple_clone("another"), "another");
assert.strictEqual(wasm.simple_concat("a", "b", 3), "a b 3");
assert.strictEqual(wasm.simple_concat("c", "d", -2), "c d -2");
};
exports.test_wrong_types = function() {
// this test only works when `--debug` is passed to `wasm-bindgen` (or the
// equivalent thereof)
if (require('process').env.WASM_BINDGEN_NO_DEBUG)
return;
assert.throws(() => wasm.simple_int('a'), /expected a number argument/);
assert.throws(() => wasm.simple_str(3), /expected a string argument/);
};
exports.test_other_exports_still_available = function() {
require('wasm-bindgen-test').__wasm.foo(3);
};
exports.test_jsvalue_typeof = function() {
assert.ok(wasm.is_object({}));
assert.ok(!wasm.is_object(42));
assert.ok(wasm.is_function(function() {}));
assert.ok(!wasm.is_function(42));
assert.ok(wasm.is_string("2b or !2b"));
assert.ok(!wasm.is_string(42));
};
exports.optional_str_none = function(x) {
assert.strictEqual(x, undefined);
};
exports.optional_str_some = function(x) {
assert.strictEqual(x, 'x');
};
exports.optional_slice_none = function(x) {
assert.strictEqual(x, undefined);
};
exports.optional_slice_some = function(x) {
assert.strictEqual(x.length, 3);
assert.strictEqual(x[0], 1);
assert.strictEqual(x[1], 2);
assert.strictEqual(x[2], 3);
}
exports.optional_string_none = function(x) {
assert.strictEqual(x, undefined);
};
exports.optional_string_some = function(x) {
assert.strictEqual(x, 'abcd');
};
exports.optional_string_some_empty = function(x) {
assert.strictEqual(x, '');
};
exports.return_string_none = function() {};
exports.return_string_some = function() {
return 'foo';
};
exports.test_rust_optional = function() {
wasm.take_optional_str_none();
wasm.take_optional_str_none(null);
wasm.take_optional_str_none(undefined);
wasm.take_optional_str_some('hello');
assert.strictEqual(wasm.return_optional_str_none(), undefined);
assert.strictEqual(wasm.return_optional_str_some(), 'world');
};
exports.RenamedInRust = class {};
exports.new_renamed = () => new exports.RenamedInRust;
exports.import_export_same_name = () => {};
exports.test_string_roundtrip = () => {
const test = s => {
assert.strictEqual(wasm.do_string_roundtrip(s), s);
};
test('');
test('a');
test('💖');
test('a longer string');
test('a longer 💖 string');
};

View File

@@ -0,0 +1,227 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen::{intern, unintern, JsCast};
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/simple.js")]
extern "C" {
fn test_add();
fn test_string_arguments();
fn test_return_a_string();
fn test_wrong_types();
fn test_other_exports_still_available();
fn test_jsvalue_typeof();
fn optional_str_none(a: Option<&str>);
fn optional_str_some(a: Option<&str>);
fn optional_slice_none(a: Option<&[u8]>);
fn optional_slice_some(a: Option<&[u8]>);
fn optional_string_none(a: Option<String>);
fn optional_string_some(a: Option<String>);
fn optional_string_some_empty(a: Option<String>);
fn return_string_none() -> Option<String>;
fn return_string_some() -> Option<String>;
fn test_rust_optional();
#[wasm_bindgen(js_name = import_export_same_name)]
fn js_import_export_same_name();
#[wasm_bindgen(js_name = RenamedInRust)]
type Renamed;
fn new_renamed() -> Renamed;
fn test_string_roundtrip();
}
#[wasm_bindgen_test]
fn add() {
test_add();
}
#[wasm_bindgen]
pub fn simple_add(a: u32, b: u32) -> u32 {
a + b
}
#[wasm_bindgen]
pub fn simple_add3(a: u32) -> u32 {
a + 3
}
#[wasm_bindgen]
pub fn simple_get2(_b: bool) -> u32 {
2
}
#[wasm_bindgen]
pub fn simple_return_and_take_bool(a: bool, b: bool) -> bool {
a && b
}
#[wasm_bindgen]
pub fn simple_raw_pointers_work(a: *mut u32, b: *const u8) -> *const u32 {
unsafe {
(*a) = (*b) as u32;
return a;
}
}
#[wasm_bindgen_test]
fn string_arguments() {
test_string_arguments();
}
#[wasm_bindgen]
pub fn simple_assert_foo_and_bar(a: &str, b: &str) {
assert_eq!(a, "foo2");
assert_eq!(b, "bar");
}
#[wasm_bindgen]
pub fn simple_assert_foo(a: &str) {
assert_eq!(a, "foo");
}
#[wasm_bindgen_test]
fn return_a_string() {
test_return_a_string();
}
#[wasm_bindgen]
pub fn simple_clone(a: &str) -> String {
a.to_string()
}
#[wasm_bindgen]
pub fn simple_concat(a: &str, b: &str, c: i8) -> String {
format!("{} {} {}", a, b, c)
}
#[wasm_bindgen_test]
fn wrong_types() {
test_wrong_types();
}
#[wasm_bindgen]
pub fn simple_int(_a: u32) {}
#[wasm_bindgen]
pub fn simple_str(_a: &str) {}
#[wasm_bindgen_test]
fn other_exports() {
test_other_exports_still_available();
}
#[no_mangle]
pub extern "C" fn foo(_a: u32) {}
#[wasm_bindgen_test]
fn jsvalue_typeof() {
test_jsvalue_typeof();
}
#[wasm_bindgen]
pub fn is_object(val: &JsValue) -> bool {
val.is_object()
}
#[wasm_bindgen]
pub fn is_function(val: &JsValue) -> bool {
val.is_function()
}
#[wasm_bindgen]
pub fn is_string(val: &JsValue) -> bool {
val.is_string()
}
#[wasm_bindgen]
extern "C" {
#[derive(Clone)]
type Array;
#[wasm_bindgen(constructor)]
fn new() -> Array;
#[wasm_bindgen(method, catch)]
fn standardized_method_this_js_runtime_doesnt_implement_yet(
this: &Array,
) -> Result<(), JsValue>;
}
#[wasm_bindgen_test]
fn binding_to_unimplemented_apis_doesnt_break_everything() {
let array = Array::new();
let res = array.standardized_method_this_js_runtime_doesnt_implement_yet();
assert!(res.is_err());
}
#[wasm_bindgen_test]
fn optional_slices() {
optional_str_none(None);
optional_str_some(Some("x"));
optional_str_some(Some(intern("x")));
unintern("x");
optional_str_some(Some("x"));
optional_slice_none(None);
optional_slice_some(Some(&[1, 2, 3]));
optional_string_none(None);
optional_string_some_empty(Some(String::new()));
optional_string_some(Some("abcd".to_string()));
assert_eq!(return_string_none(), None);
assert_eq!(return_string_some(), Some("foo".to_string()));
test_rust_optional();
}
#[wasm_bindgen]
pub fn take_optional_str_none(x: Option<String>) {
assert!(x.is_none())
}
#[wasm_bindgen]
pub fn take_optional_str_some(x: Option<String>) {
assert_eq!(x, Some(String::from("hello")));
}
#[wasm_bindgen]
pub fn return_optional_str_none() -> Option<String> {
None
}
#[wasm_bindgen]
pub fn return_optional_str_some() -> Option<String> {
Some("world".to_string())
}
#[wasm_bindgen_test]
fn renaming_imports_and_instanceof() {
let null = JsValue::NULL;
assert!(!null.is_instance_of::<Renamed>());
let arr: JsValue = Array::new().into();
assert!(!arr.is_instance_of::<Renamed>());
let renamed: JsValue = new_renamed().into();
assert!(renamed.is_instance_of::<Renamed>());
}
#[wasm_bindgen]
pub fn import_export_same_name() {
js_import_export_same_name();
}
#[wasm_bindgen_test]
fn string_roundtrip() {
test_string_roundtrip();
}
#[wasm_bindgen]
pub fn do_string_roundtrip(s: String) -> String {
s
}
#[wasm_bindgen_test]
fn externref_heap_live_count() {
let x = wasm_bindgen::externref_heap_live_count();
let y = JsValue::null().clone();
assert!(wasm_bindgen::externref_heap_live_count() > x);
drop(y);
assert_eq!(x, wasm_bindgen::externref_heap_live_count());
}

View File

@@ -0,0 +1,197 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.js_export = () => {
const i8 = new Int8Array(2);
i8[0] = 1;
i8[1] = 2;
assert.deepStrictEqual(wasm.export_i8(i8), i8);
const u8 = new Uint8Array(2);
u8[0] = 1;
u8[1] = 2;
assert.deepStrictEqual(wasm.export_u8(u8), u8);
const i16 = new Int16Array(2);
i16[0] = 1;
i16[1] = 2;
assert.deepStrictEqual(wasm.export_i16(i16), i16);
const u16 = new Uint16Array(2);
u16[0] = 1;
u16[1] = 2;
assert.deepStrictEqual(wasm.export_u16(u16), u16);
const i32 = new Int32Array(2);
i32[0] = 1;
i32[1] = 2;
assert.deepStrictEqual(wasm.export_i32(i32), i32);
assert.deepStrictEqual(wasm.export_isize(i32), i32);
const u32 = new Uint32Array(2);
u32[0] = 1;
u32[1] = 2;
assert.deepStrictEqual(wasm.export_u32(u32), u32);
assert.deepStrictEqual(wasm.export_usize(u32), u32);
const f32 = new Float32Array(2);
f32[0] = 1;
f32[1] = 2;
assert.deepStrictEqual(wasm.export_f32(f32), f32);
const f64 = new Float64Array(2);
f64[0] = 1;
f64[1] = 2;
assert.deepStrictEqual(wasm.export_f64(f64), f64);
};
const test_import = (a, b, c) => {
assert.strictEqual(a.length, 2);
assert.strictEqual(a[0], 1);
assert.strictEqual(a[1], 2);
assert.strictEqual(b.length, 2);
assert.strictEqual(b[0], 1);
assert.strictEqual(b[1], 2);
assert.strictEqual(c, undefined);
return a;
};
exports.import_js_i8 = test_import;
exports.import_js_u8 = test_import;
exports.import_js_i16 = test_import;
exports.import_js_u16 = test_import;
exports.import_js_i32 = test_import;
exports.import_js_isize = test_import;
exports.import_js_u32 = test_import;
exports.import_js_usize = test_import;
exports.import_js_f32 = test_import;
exports.import_js_f64 = test_import;
exports.js_import = () => {
const i8 = new Int8Array(2);
i8[0] = 1;
i8[1] = 2;
assert.deepStrictEqual(wasm.import_rust_i8(i8), i8);
const u8 = new Uint8Array(2);
u8[0] = 1;
u8[1] = 2;
assert.deepStrictEqual(wasm.import_rust_u8(u8), u8);
const i16 = new Int16Array(2);
i16[0] = 1;
i16[1] = 2;
assert.deepStrictEqual(wasm.import_rust_i16(i16), i16);
const u16 = new Uint16Array(2);
u16[0] = 1;
u16[1] = 2;
assert.deepStrictEqual(wasm.import_rust_u16(u16), u16);
const i32 = new Int32Array(2);
i32[0] = 1;
i32[1] = 2;
assert.deepStrictEqual(wasm.import_rust_i32(i32), i32);
assert.deepStrictEqual(wasm.import_rust_isize(i32), i32);
const u32 = new Uint32Array(2);
u32[0] = 1;
u32[1] = 2;
assert.deepStrictEqual(wasm.import_rust_u32(u32), u32);
assert.deepStrictEqual(wasm.import_rust_usize(u32), u32);
const f32 = new Float32Array(2);
f32[0] = 1;
f32[1] = 2;
assert.deepStrictEqual(wasm.import_rust_f32(f32), f32);
const f64 = new Float64Array(2);
f64[0] = 1;
f64[1] = 2;
assert.deepStrictEqual(wasm.import_rust_f64(f64), f64);
};
exports.js_pass_array = () => {
wasm.pass_array_rust_i8([1, 2]);
wasm.pass_array_rust_u8([1, 2]);
wasm.pass_array_rust_i16([1, 2]);
wasm.pass_array_rust_u16([1, 2]);
wasm.pass_array_rust_i32([1, 2]);
wasm.pass_array_rust_u32([1, 2]);
wasm.pass_array_rust_isize([1, 2]);
wasm.pass_array_rust_usize([1, 2]);
wasm.pass_array_rust_f32([1, 2]);
wasm.pass_array_rust_f64([1, 2]);
};
const import_mut_foo = (a, b, c) => {
assert.strictEqual(a.length, 3);
assert.strictEqual(a[0], 1);
assert.strictEqual(a[1], 2);
a[0] = 4;
a[1] = 5;
assert.strictEqual(b.length, 3);
assert.strictEqual(b[0], 4);
assert.strictEqual(b[1], 5);
assert.strictEqual(b[2], 6);
b[0] = 8;
b[1] = 7;
assert.strictEqual(c, undefined);
};
exports.import_mut_js_i8 = import_mut_foo;
exports.import_mut_js_u8 = import_mut_foo;
exports.import_mut_js_i16 = import_mut_foo;
exports.import_mut_js_u16 = import_mut_foo;
exports.import_mut_js_i32 = import_mut_foo;
exports.import_mut_js_u32 = import_mut_foo;
exports.import_mut_js_isize = import_mut_foo;
exports.import_mut_js_usize = import_mut_foo;
exports.import_mut_js_f32 = import_mut_foo;
exports.import_mut_js_f64 = import_mut_foo;
const export_mut_run = (a, rust) => {
assert.strictEqual(a.length, 3);
a[0] = 1;
a[1] = 2;
a[2] = 3;
console.log(a);
rust(a);
console.log(a);
assert.strictEqual(a.length, 3);
assert.strictEqual(a[0], 4);
assert.strictEqual(a[1], 5);
assert.strictEqual(a[2], 3);
};
exports.js_export_mut = () => {
export_mut_run(new Int8Array(3), wasm.export_mut_i8);
export_mut_run(new Uint8Array(3), wasm.export_mut_u8);
export_mut_run(new Int16Array(3), wasm.export_mut_i16);
export_mut_run(new Uint16Array(3), wasm.export_mut_u16);
export_mut_run(new Int32Array(3), wasm.export_mut_i32);
export_mut_run(new Uint32Array(3), wasm.export_mut_u32);
export_mut_run(new Int32Array(3), wasm.export_mut_isize);
export_mut_run(new Uint32Array(3), wasm.export_mut_usize);
export_mut_run(new Float32Array(3), wasm.export_mut_f32);
export_mut_run(new Float64Array(3), wasm.export_mut_f64);
};
exports.js_return_vec = () => {
const app = wasm.return_vec_web_main();
for (let i = 0; i < 10; i++) {
app.tick();
const bad = wasm.return_vec_broken_vec();
console.log('Received from rust:', i, bad);
assert.strictEqual(bad[0], 1);
assert.strictEqual(bad[1], 2);
assert.strictEqual(bad[2], 3);
assert.strictEqual(bad[3], 4);
assert.strictEqual(bad[4], 5);
assert.strictEqual(bad[5], 6);
assert.strictEqual(bad[6], 7);
assert.strictEqual(bad[7], 8);
assert.strictEqual(bad[8], 9);
}
};
exports.js_clamped = (a, offset) => {
assert.ok(a instanceof Uint8ClampedArray);
assert.equal(a.length, 3);
assert.equal(a[0], offset + 0);
assert.equal(a[1], offset + 1);
assert.equal(a[2], offset + 2);
};

View File

@@ -0,0 +1,240 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen::Clamped;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/slice.js")]
extern "C" {
fn js_export();
fn js_import();
fn js_pass_array();
fn js_export_mut();
fn js_return_vec();
fn js_clamped(val: Clamped<&[u8]>, offset: u8);
#[wasm_bindgen(js_name = js_clamped)]
fn js_clamped2(val: Clamped<Vec<u8>>, offset: u8);
#[wasm_bindgen(js_name = js_clamped)]
fn js_clamped3(val: Clamped<&mut [u8]>, offset: u8);
}
macro_rules! export_macro {
($(($i:ident, $n:ident))*) => ($(
#[wasm_bindgen]
pub fn $n(a: &[$i]) -> Vec<$i> {
assert_eq!(a.len(), 2);
assert_eq!(a[0], 1 as $i);
assert_eq!(a[1], 2 as $i);
a.to_vec()
}
)*)
}
export_macro! {
(i8, export_i8)
(u8, export_u8)
(i16, export_i16)
(u16, export_u16)
(i32, export_i32)
(u32, export_u32)
(isize, export_isize)
(usize, export_usize)
(f32, export_f32)
(f64, export_f64)
}
#[wasm_bindgen_test]
fn export() {
js_export();
}
macro_rules! import_macro {
($(($rust:ident, $js:ident, $i:ident))*) => ($(
#[wasm_bindgen(module = "tests/wasm/slice.js")]
extern "C" {
fn $js(a: &[$i], b: Option<&[$i]>, c: Option<&[$i]>) -> Vec<$i>;
}
#[wasm_bindgen]
pub fn $rust(a: &[$i]) -> Vec<$i> {
assert_eq!(a.len(), 2);
assert_eq!(a[0], 1 as $i);
assert_eq!(a[1], 2 as $i);
$js(a, Some(a), None)
}
)*)
}
import_macro! {
(import_rust_i8, import_js_i8, i8)
(import_rust_u8, import_js_u8, u8)
(import_rust_i16, import_js_i16, i16)
(import_rust_u16, import_js_u16, u16)
(import_rust_i32, import_js_i32, i32)
(import_rust_u32, import_js_u32, u32)
(import_rust_isize, import_js_isize, isize)
(import_rust_usize, import_js_usize, usize)
(import_rust_f32, import_js_f32, f32)
(import_rust_f64, import_js_f64, f64)
}
#[wasm_bindgen_test]
fn import() {
js_import();
}
macro_rules! pass_array_marco {
($(($rust:ident, $i:ident))*) => ($(
#[wasm_bindgen]
pub fn $rust(a: &[$i]) {
assert_eq!(a.len(), 2);
assert_eq!(a[0], 1 as $i);
assert_eq!(a[1], 2 as $i);
}
)*)
}
pass_array_marco! {
(pass_array_rust_i8, i8)
(pass_array_rust_u8, u8)
(pass_array_rust_i16, i16)
(pass_array_rust_u16, u16)
(pass_array_rust_i32, i32)
(pass_array_rust_u32, u32)
(pass_array_rust_isize, isize)
(pass_array_rust_usize, usize)
(pass_array_rust_f32, f32)
(pass_array_rust_f64, f64)
}
#[wasm_bindgen_test]
fn pass_array() {
js_pass_array();
}
macro_rules! import_mut_macro {
($(($rust:ident, $js:ident, $i:ident))*) => (
$(
#[wasm_bindgen(module = "tests/wasm/slice.js")]
extern "C" {
fn $js(a: &mut [$i], b: Option<&mut [$i]>, c: Option<&mut [$i]>);
}
fn $rust() {
let mut buf1 = [
1 as $i,
2 as $i,
3 as $i,
];
let mut buf2 = [
4 as $i,
5 as $i,
6 as $i,
];
$js(&mut buf1, Some(&mut buf2), None);
assert_eq!(buf1[0], 4 as $i);
assert_eq!(buf1[1], 5 as $i);
assert_eq!(buf1[2], 3 as $i);
assert_eq!(buf2[0], 8 as $i);
assert_eq!(buf2[1], 7 as $i);
assert_eq!(buf2[2], 6 as $i);
}
)*
#[wasm_bindgen_test]
fn import_mut() {
$($rust();)*
}
)
}
import_mut_macro! {
(import_mut_rust_i8, import_mut_js_i8, i8)
(import_mut_rust_u8, import_mut_js_u8, u8)
(import_mut_rust_i16, import_mut_js_i16, i16)
(import_mut_rust_u16, import_mut_js_u16, u16)
(import_mut_rust_i32, import_mut_js_i32, i32)
(import_mut_rust_u32, import_mut_js_u32, u32)
(import_mut_rust_f32, import_mut_js_f32, f32)
(import_mut_rust_f64, import_mut_js_f64, f64)
}
macro_rules! export_mut_macro {
($(($i:ident, $n:ident))*) => ($(
#[wasm_bindgen]
pub fn $n(a: &mut [$i]) {
assert_eq!(a.len(), 3);
assert_eq!(a[0], 1 as $i);
assert_eq!(a[1], 2 as $i);
assert_eq!(a[2], 3 as $i);
a[0] = 4 as $i;
a[1] = 5 as $i;
}
)*)
}
export_mut_macro! {
(i8, export_mut_i8)
(u8, export_mut_u8)
(i16, export_mut_i16)
(u16, export_mut_u16)
(i32, export_mut_i32)
(u32, export_mut_u32)
(isize, export_mut_isize)
(usize, export_mut_usize)
(f32, export_mut_f32)
(f64, export_mut_f64)
}
#[wasm_bindgen_test]
fn export_mut() {
js_export_mut();
}
#[wasm_bindgen]
pub fn return_vec_broken_vec() -> Vec<u32> {
vec![1, 2, 3, 4, 5, 6, 7, 8, 9]
}
#[wasm_bindgen]
pub fn return_vec_web_main() -> ReturnVecApplication {
ReturnVecApplication::new()
}
#[wasm_bindgen]
pub struct ReturnVecApplication {
thing: Vec<u32>,
}
#[wasm_bindgen]
impl ReturnVecApplication {
pub fn new() -> ReturnVecApplication {
let mut thing = vec![];
thing.push(0);
thing.push(0);
thing.push(0);
thing.push(0);
thing.push(0);
ReturnVecApplication { thing }
}
pub fn tick(&mut self) {
self.thing = self.thing.clone();
}
}
#[wasm_bindgen_test]
fn return_vec() {
js_return_vec();
}
#[wasm_bindgen_test]
fn take_clamped() {
js_clamped(Clamped(&[1, 2, 3]), 1);
js_clamped2(Clamped(vec![4, 5, 6]), 4);
js_clamped3(Clamped(&mut [7, 8, 9]), 7);
}

View File

@@ -0,0 +1,13 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.js_works = () => {
let called = false;
wasm.run({
bar() {
called = true;
},
baz: 1,
});
assert.strictEqual(called, true);
};

View File

@@ -0,0 +1,32 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/structural.js")]
extern "C" {
fn js_works();
}
#[wasm_bindgen]
extern "C" {
pub type StructuralFoo;
#[wasm_bindgen(method, structural)]
fn bar(this: &StructuralFoo);
#[wasm_bindgen(method, getter, structural)]
fn baz(this: &StructuralFoo) -> u32;
#[wasm_bindgen(method, setter, structural)]
fn set_baz(this: &StructuralFoo, val: u32);
}
#[wasm_bindgen]
pub fn run(a: &StructuralFoo) {
a.bar();
assert_eq!(a.baz(), 1);
a.set_baz(2);
assert_eq!(a.baz(), 2);
}
#[wasm_bindgen_test]
fn works() {
js_works();
}

View File

@@ -0,0 +1,28 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn test_is_truthy() {
assert_eq!(JsValue::from(0).is_truthy(), false);
assert_eq!(JsValue::from("".to_string()).is_truthy(), false);
assert_eq!(JsValue::from(false).is_truthy(), false);
assert_eq!(JsValue::NULL.is_truthy(), false);
assert_eq!(JsValue::UNDEFINED.is_truthy(), false);
assert_eq!(JsValue::from(10).is_truthy(), true);
assert_eq!(JsValue::from("null".to_string()).is_truthy(), true);
assert_eq!(JsValue::from(true).is_truthy(), true);
}
#[wasm_bindgen_test]
fn test_is_falsy() {
assert_eq!(JsValue::from(0).is_falsy(), true);
assert_eq!(JsValue::from("".to_string()).is_falsy(), true);
assert_eq!(JsValue::from(false).is_falsy(), true);
assert_eq!(JsValue::NULL.is_falsy(), true);
assert_eq!(JsValue::UNDEFINED.is_falsy(), true);
assert_eq!(JsValue::from(10).is_falsy(), false);
assert_eq!(JsValue::from("null".to_string()).is_falsy(), false);
assert_eq!(JsValue::from(true).is_falsy(), false);
}

View File

@@ -0,0 +1,39 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
exports.isize_js_identity = a => a;
exports.usize_js_identity = a => a;
exports.js_works = async () => {
assert.strictEqual(wasm.usize_zero(), 0);
assert.strictEqual(wasm.usize_one(), 1);
assert.strictEqual(wasm.isize_neg_one(), -1);
assert.strictEqual(wasm.isize_i32_min(), -2147483648);
assert.strictEqual(wasm.isize_min(), -2147483648);
assert.strictEqual(wasm.usize_u32_max(), 4294967295);
assert.strictEqual(wasm.usize_max(), 4294967295);
assert.strictEqual(wasm.isize_rust_identity(0), 0);
assert.strictEqual(wasm.isize_rust_identity(1), 1);
assert.strictEqual(wasm.isize_rust_identity(-1), -1);
assert.strictEqual(wasm.usize_rust_identity(0), 0);
assert.strictEqual(wasm.usize_rust_identity(1), 1);
const usize_max = 4294967295;
const isize_min = -2147483648;
assert.strictEqual(wasm.isize_rust_identity(isize_min), isize_min);
assert.strictEqual(wasm.usize_rust_identity(usize_max), usize_max);
assert.deepStrictEqual(wasm.usize_slice([]), new Uint32Array());
assert.deepStrictEqual(wasm.isize_slice([]), new Int32Array());
const arr1 = new Uint32Array([1, 2]);
assert.deepStrictEqual(wasm.usize_slice([1, 2]), arr1);
const arr2 = new Int32Array([1, 2]);
assert.deepStrictEqual(wasm.isize_slice([1, 2]), arr2);
assert.deepStrictEqual(wasm.isize_slice([isize_min]), new Int32Array([isize_min]));
assert.deepStrictEqual(wasm.usize_slice([usize_max]), new Uint32Array([usize_max]));
assert.deepStrictEqual(await wasm.async_usize_one(), 1);
assert.deepStrictEqual(await wasm.async_isize_neg_one(), -1);
};

View File

@@ -0,0 +1,79 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/usize.js")]
extern "C" {
fn isize_js_identity(a: isize) -> isize;
fn usize_js_identity(a: usize) -> usize;
fn js_works();
}
#[wasm_bindgen]
pub fn usize_zero() -> usize {
0
}
#[wasm_bindgen]
pub fn usize_one() -> usize {
1
}
#[wasm_bindgen]
pub fn isize_neg_one() -> isize {
-1
}
#[wasm_bindgen]
pub fn isize_i32_min() -> isize {
i32::min_value() as isize
}
#[wasm_bindgen]
pub fn usize_u32_max() -> usize {
u32::max_value() as usize
}
#[wasm_bindgen]
pub fn isize_min() -> isize {
isize::min_value()
}
#[wasm_bindgen]
pub fn usize_max() -> usize {
usize::max_value()
}
#[wasm_bindgen]
pub fn isize_rust_identity(a: isize) -> isize {
isize_js_identity(a)
}
#[wasm_bindgen]
pub fn usize_rust_identity(a: usize) -> usize {
usize_js_identity(a)
}
#[wasm_bindgen]
pub fn isize_slice(a: &[isize]) -> Vec<isize> {
a.to_vec()
}
#[wasm_bindgen]
pub fn usize_slice(a: &[usize]) -> Vec<usize> {
a.to_vec()
}
#[wasm_bindgen]
pub async fn async_usize_one() -> usize {
1
}
#[wasm_bindgen]
pub async fn async_isize_neg_one() -> isize {
-1
}
#[wasm_bindgen_test]
fn works() {
js_works();
}

View File

@@ -0,0 +1,43 @@
const wasm = require('wasm-bindgen-test.js');
const assert = require('assert');
// NB: `wasm-pack` uses the presence of checks for moved values as a way to test
// whether it is correctly enabling `--debug` when configured to do so, so don't
// change this expected debug output without also updating `wasm-pack`'s tests.
const assertMovedPtrThrows = process.env.WASM_BINDGEN_NO_DEBUG == null
? f => assert.throws(f, /Attempt to use a moved value/)
: f => assert.throws(f, /null pointer passed to rust/);
const useMoved = () => {
const apple = new wasm.Fruit('apple');
apple.name();
wasm.eat(apple);
assertMovedPtrThrows(() => apple.name());
};
const moveMoved = () => {
const pear = new wasm.Fruit('pear');
pear.name();
wasm.eat(pear);
assertMovedPtrThrows(() => wasm.eat(pear));
};
const methodMoved = () => {
const quince = new wasm.Fruit('quince');
quince.name();
quince.rot();
assertMovedPtrThrows(() => quince.rot());
};
exports.js_works = () => {
useMoved();
moveMoved();
methodMoved();
const a = new wasm.Fruit('a');
a.prop;
assertMovedPtrThrows(() => a.prop);
const b = new wasm.Fruit('a');
b.prop = 3;
assertMovedPtrThrows(() => { b.prop = 4; });
};

View File

@@ -0,0 +1,44 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/validate_prt.js")]
extern "C" {
fn js_works();
}
#[wasm_bindgen]
pub struct Fruit {
name: String,
}
#[wasm_bindgen]
impl Fruit {
pub fn name(&self) -> String {
self.name.clone()
}
#[wasm_bindgen(constructor)]
pub fn new(name: String) -> Self {
Fruit { name }
}
pub fn rot(self) {
drop(self);
}
#[wasm_bindgen(getter)]
pub fn prop(self) -> u32 {
0
}
#[wasm_bindgen(setter)]
pub fn set_prop(self, _val: u32) {}
}
#[wasm_bindgen]
pub fn eat(_: Fruit) {}
#[wasm_bindgen_test]
fn works() {
js_works();
}

View File

@@ -0,0 +1,59 @@
const assert = require('assert');
// a function for testing numbers
function variadic_sum(...args) {
let answer = 0;
for(var i=0; i<args.length; i++) {
answer += args[i];
}
return answer;
}
exports.variadic_sum_u8 = variadic_sum;
exports.variadic_sum_u16 = variadic_sum;
exports.variadic_sum_u32 = variadic_sum;
exports.variadic_sum_u64 = variadic_sum;
exports.variadic_sum_i8 = variadic_sum;
exports.variadic_sum_i16 = variadic_sum;
exports.variadic_sum_i32 = variadic_sum;
exports.variadic_sum_i64 = variadic_sum;
exports.variadic_sum_f32 = variadic_sum;
exports.variadic_sum_f64 = variadic_sum;
exports.variadic_sum_rest_vec = variadic_sum;
// a function for testing nullable numbers
function variadic_sum_opt(...args) {
let answer = 0;
for(var i=0; i<args.length; i++) {
if(args[i] != null) {
answer += args[i];
}
}
return answer;
}
exports.variadic_sum_opt = variadic_sum_opt;
// a function for testing strings
function variadic_concat(...args) {
let answer = "";
for(var i=0; i<args.length; i++) {
answer = `${answer}${args[i]}`;
}
return answer;
}
exports.variadic_concat_str = variadic_concat;
exports.variadic_concat_string = variadic_concat;
// a test that takes any type of arguments (for testing JsValue).
function variadic_compare_pairs(...args) {
assert(args.length % 2 == 0, "args must be sequence of pairs");
for(var i=0; i<args.length; i++) {
const first = args[i++];
const second = args[i];
assert.equal(first, second);
}
}
exports.variadic_compare_pairs = variadic_compare_pairs;

View File

@@ -0,0 +1,134 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/variadic.js")]
extern "C" {
#[wasm_bindgen(variadic)]
fn variadic_sum_u8(first: u8, second: u8, rest: &[u8]) -> u8;
#[wasm_bindgen(variadic)]
fn variadic_sum_u16(first: u16, second: u16, rest: &[u16]) -> u16;
#[wasm_bindgen(variadic)]
fn variadic_sum_u32(first: u32, second: u32, rest: &[u32]) -> u32;
#[wasm_bindgen(variadic)]
fn variadic_sum_u64(first: u64, second: u64, rest: &[u64]) -> u64;
//#[wasm_bindgen(variadic)]
//fn variadic_sum_usize(first: usize, second: usize, rest: &[usize]) -> usize;
#[wasm_bindgen(variadic)]
fn variadic_sum_i8(first: i8, second: i8, rest: &[i8]) -> i8;
#[wasm_bindgen(variadic)]
fn variadic_sum_i16(first: i16, second: i16, rest: &[i16]) -> i16;
#[wasm_bindgen(variadic)]
fn variadic_sum_i32(first: i32, second: i32, rest: &[i32]) -> i32;
#[wasm_bindgen(variadic)]
fn variadic_sum_i64(first: i64, second: i64, rest: &[i64]) -> i64;
//#[wasm_bindgen(variadic)]
//fn variadic_sum_isize(first: isize, second: isize, rest: &[isize]) -> isize;
#[wasm_bindgen(variadic)]
fn variadic_sum_f32(first: f32, second: f32, rest: &[f32]) -> f32;
#[wasm_bindgen(variadic)]
fn variadic_sum_f64(first: f64, second: f64, rest: &[f64]) -> f64;
//#[wasm_bindgen(variadic)]
//fn variadic_sum_opt(first: Option<u32>, second: Option<u32>, rest: &[Option<u32>]) -> u32;
//#[wasm_bindgen(variadic)]
//fn variadic_concat_str(first: &str, second: &str, rest: &[&str]) -> String;
//#[wasm_bindgen(variadic)]
//fn variadic_concat_string(first: String,
// second: String,
// rest: Vec<String>) -> String;
#[wasm_bindgen(variadic)]
fn variadic_sum_rest_vec(first: u8, second: u8, rest: Vec<u8>) -> u8;
//#[wasm_bindgen(variadic)]
//fn variadic_compare_pairs(first: JsValue, second: JsValue, rest: &[JsValue]);
//TODO imported type
}
// ints
macro_rules! variadic_test_int {
($fn_name:ident, $extern_name:ident) => {
#[wasm_bindgen_test]
fn $fn_name() {
assert_eq!($extern_name(1, 2, &[]), 3);
assert_eq!($extern_name(1, 2, &[3]), 6);
assert_eq!($extern_name(1, 2, &[3, 4]), 10);
}
};
}
// The <int>64 tests throw js `Cannot mix BigInt and other types, use explicit conversions`
variadic_test_int!(u8, variadic_sum_u8);
variadic_test_int!(u16, variadic_sum_u16);
variadic_test_int!(u32, variadic_sum_u32);
//variadic_test_int!(u64, variadic_sum_u64);
//variadic_test_int!(usize, variadic_sum_usize);
variadic_test_int!(i8, variadic_sum_i8);
variadic_test_int!(i16, variadic_sum_i16);
variadic_test_int!(i32, variadic_sum_i32);
//variadic_test_int!(i64, variadic_sum_i64);
//variadic_test_int!(isize, variadic_sum_isize);
// floats
macro_rules! variadic_test_float {
($fn_name:ident, $extern_name:ident) => {
#[wasm_bindgen_test]
fn $fn_name() {
assert_eq!($extern_name(1., 2., &[]), 3.);
assert_eq!($extern_name(1., 2., &[3.]), 6.);
assert_eq!($extern_name(1., 2., &[3., 4.]), 10.);
}
};
}
variadic_test_float!(f32, variadic_sum_f32);
variadic_test_float!(f64, variadic_sum_f64);
// strings
// `the trait `wasm_bindgen::convert::IntoWasmAbi` is not implemented for `&[&str]`
/*
#[wasm_bindgen_test]
fn str() {
assert_eq!(variadic_concat_str("a ", "test", &[]), "a test");
assert_eq!(variadic_concat_str("a", "nother ", &["test"]), "another test");
assert_eq!(variadic_concat_str("yet ", "a", &["nother ", "test"]), "yet another test");
}
#[wasm_bindgen_test]
fn string() {
assert_eq!(variadic_concat_string("a ".into(), "test".into(), vec![]), "a test");
assert_eq!(variadic_concat_string("a".into(), "nother ".into(), vec!["test".into()]),
"another test");
assert_eq!(variadic_concat_string("yet ".into(),
"a".into(),
vec!["nother ".into(), "test".into()]),
"yet another test");
}
*/
// options
/*
#[wasm_bindgen_test]
fn opt() {
assert_eq!(variadic_sum_opt(Some(1), None, &[]), 1);
assert_eq!(variadic_sum_opt(Some(1), None, &[Some(2)]), 3);
assert_eq!(variadic_sum_opt(Some(1), None, &[None, Some(2)]), 3);
}
*/
// vec not slice
#[wasm_bindgen_test]
fn rest_vec() {
assert_eq!(variadic_sum_rest_vec(1, 2, vec![]), 3);
assert_eq!(variadic_sum_rest_vec(1, 2, vec![3]), 6);
assert_eq!(variadic_sum_rest_vec(1, 2, vec![3, 4]), 10);
}
// JsValue
//#[wasm_bindgen_test]
//fn jsvalue() {
// variadic_compare_pairs_jsvalue(true, true, vec![]);
// variadic_compare_pairs_jsvalue(false, false, vec![3, 3]);
//}

View File

@@ -0,0 +1,11 @@
exports.import_me = function() {};
global.webkitMySpecialApi = class {
foo() { return 123; }
};
global.MySpecialApi2 = class {
foo() { return 124; }
};
global.bMySpecialApi3 = class {
foo() { return 125; }
};

View File

@@ -0,0 +1,48 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
#[wasm_bindgen(module = "tests/wasm/vendor_prefix.js")]
extern "C" {
fn import_me(x: &str);
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(vendor_prefix = webkit)]
type MySpecialApi;
#[wasm_bindgen(constructor)]
fn new() -> MySpecialApi;
#[wasm_bindgen(method)]
fn foo(this: &MySpecialApi) -> u32;
#[wasm_bindgen(vendor_prefix = webkit)]
type MySpecialApi2;
#[wasm_bindgen(constructor)]
fn new() -> MySpecialApi2;
#[wasm_bindgen(method)]
fn foo(this: &MySpecialApi2) -> u32;
#[wasm_bindgen(vendor_prefix = a, vendor_prefix = b)]
type MySpecialApi3;
#[wasm_bindgen(constructor)]
fn new() -> MySpecialApi3;
#[wasm_bindgen(method)]
fn foo(this: &MySpecialApi3) -> u32;
// This API does not exist at all;
// test that Rust gets a chance to catch the error (#2437)
#[wasm_bindgen(vendor_prefix = a, vendor_prefix = b)]
type MyMissingApi;
#[wasm_bindgen(constructor, catch)]
fn new() -> Result<MyMissingApi, JsValue>;
}
#[wasm_bindgen_test]
pub fn polyfill_works() {
import_me("foo");
assert_eq!(MySpecialApi::new().foo(), 123);
assert_eq!(MySpecialApi2::new().foo(), 124);
assert_eq!(MySpecialApi3::new().foo(), 125);
assert!(MyMissingApi::new().is_err());
}