diff --git a/crates/webidl/src/util.rs b/crates/webidl/src/util.rs index 51297883..0b155558 100644 --- a/crates/webidl/src/util.rs +++ b/crates/webidl/src/util.rs @@ -129,6 +129,17 @@ impl<'a> FirstPassRecord<'a> { if ty.nullable { return None; } + let array = |base_ty: &str| { + match pos { + TypePosition::Argument => { + shared_ref(slice_ty(ident_ty(raw_ident(base_ty)))) + } + TypePosition::Return => { + vec_ty(ident_ty(raw_ident(base_ty))) + } + } + }; + Some(match ty.kind { // `any` becomes `::wasm_bindgen::JsValue`. webidl::ast::TypeKind::Any => { @@ -172,21 +183,30 @@ impl<'a> FirstPassRecord<'a> { webidl::ast::TypeKind::UnsignedLongLong => ident_ty(raw_ident("u64")), webidl::ast::TypeKind::UnsignedShort => ident_ty(raw_ident("u16")), - // `DOMString -> `&str` for arguments - webidl::ast::TypeKind::DOMString if pos == TypePosition::Argument => { - shared_ref(ident_ty(raw_ident("str"))) - } - webidl::ast::TypeKind::DOMString => { - ident_ty(raw_ident("String")) - }, + webidl::ast::TypeKind::Float32Array => array("f32"), + webidl::ast::TypeKind::Float64Array => array("f64"), + webidl::ast::TypeKind::Int8Array => array("i8"), + webidl::ast::TypeKind::Int16Array => array("i16"), + webidl::ast::TypeKind::Int32Array => array("i32"), + webidl::ast::TypeKind::Uint8Array => array("u8"), + webidl::ast::TypeKind::Uint8ClampedArray => array("u8"), + webidl::ast::TypeKind::Uint16Array => array("u16"), + webidl::ast::TypeKind::Uint32Array => array("u32"), - // `ByteString -> `&[u8]` for arguments - webidl::ast::TypeKind::ByteString if pos == TypePosition::Argument => { - shared_ref(slice_ty(ident_ty(raw_ident("u8")))) - } - // ... and `Vec` for arguments - webidl::ast::TypeKind::ByteString => { - vec_ty(ident_ty(raw_ident("u8"))) + // strings -> `&str` for arguments and `String` for return + // + // Note that DOMString mostly makes sense here, ByteString maps to + // String in JS [1], along with USVString + // + // [1]: https://developer.mozilla.org/en-US/docs/Web/API/ByteString + // [2]: https://developer.mozilla.org/en-US/docs/Web/API/USVString + webidl::ast::TypeKind::DOMString + | webidl::ast::TypeKind::ByteString + | webidl::ast::TypeKind::USVString => { + match pos { + TypePosition::Argument => shared_ref(ident_ty(raw_ident("str"))), + TypePosition::Return => ident_ty(raw_ident("String")), + } } // Support for these types is not yet implemented, so skip @@ -194,22 +214,12 @@ impl<'a> FirstPassRecord<'a> { webidl::ast::TypeKind::ArrayBuffer | webidl::ast::TypeKind::DataView | webidl::ast::TypeKind::Error - | webidl::ast::TypeKind::Float32Array - | webidl::ast::TypeKind::Float64Array | webidl::ast::TypeKind::FrozenArray(_) - | webidl::ast::TypeKind::Int16Array - | webidl::ast::TypeKind::Int32Array - | webidl::ast::TypeKind::Int8Array | webidl::ast::TypeKind::Object | webidl::ast::TypeKind::Promise(_) | webidl::ast::TypeKind::Record(..) | webidl::ast::TypeKind::Sequence(_) | webidl::ast::TypeKind::Symbol - | webidl::ast::TypeKind::USVString - | webidl::ast::TypeKind::Uint16Array - | webidl::ast::TypeKind::Uint32Array - | webidl::ast::TypeKind::Uint8Array - | webidl::ast::TypeKind::Uint8ClampedArray | webidl::ast::TypeKind::Union(_) => { return None; } diff --git a/crates/webidl/tests/all/array.rs b/crates/webidl/tests/all/array.rs new file mode 100644 index 00000000..c299f681 --- /dev/null +++ b/crates/webidl/tests/all/array.rs @@ -0,0 +1,134 @@ +use super::project; + +#[test] +fn take_and_return_a_bunch_of_slices() { + project() + .file( + "foo.webidl", + r#" + [Constructor()] + interface Foo { + DOMString strings(DOMString arg1); + ByteString byteStrings(ByteString arg1); + USVString usvStrings(USVString arg1); + + Float32Array f32(Float32Array a); + Float64Array f64(Float64Array a); + Int8Array i8(Int8Array a); + Int16Array i16(Int16Array a); + Int32Array i32(Int32Array a); + Uint8Array u8(Uint8Array a); + Uint8ClampedArray u8Clamped(Uint8ClampedArray a); + Uint16Array u16(Uint16Array a); + Uint32Array u32(Uint32Array a); + }; + "#, + ) + .file( + "foo.js", + r#" + import { strictEqual } from "assert"; + + export class Foo { + strings(x) { + strictEqual(x, 'y'); + return 'x'; + } + byteStrings(x) { + strictEqual(x, 'yz'); + return 'xx'; + } + usvStrings(x) { + strictEqual(x, 'abc'); + return 'efg'; + } + f32(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Float32Array([3, 4, 5]); + } + f64(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Float64Array([3, 4, 5]); + } + i8(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Int8Array([3, 4, 5]); + } + i16(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Int16Array([3, 4, 5]); + } + i32(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Int32Array([3, 4, 5]); + } + u8(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Uint8Array([3, 4, 5]); + } + u8Clamped(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Uint8ClampedArray([3, 4, 5]); + } + u16(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Uint16Array([3, 4, 5]); + } + u32(x) { + strictEqual(x.length, 2); + strictEqual(x[0], 1); + strictEqual(x[1], 2); + return new Uint32Array([3, 4, 5]); + } + } + "#, + ) + .file( + "src/lib.rs", + r#" + #![feature(use_extern_macros, wasm_import_module)] + + extern crate wasm_bindgen; + + use wasm_bindgen::prelude::*; + + pub mod foo; + + use foo::Foo; + + #[wasm_bindgen] + pub fn test() { + let f = Foo::new().unwrap(); + assert_eq!(f.strings("y"), "x"); + assert_eq!(f.byte_strings("yz"), "xx"); + assert_eq!(f.usv_strings("abc"), "efg"); + assert_eq!(f.f32(&[1.0, 2.0]), [3.0, 4.0, 5.0]); + assert_eq!(f.f64(&[1.0, 2.0]), [3.0, 4.0, 5.0]); + assert_eq!(f.i8(&[1, 2]), [3, 4, 5]); + assert_eq!(f.i16(&[1, 2]), [3, 4, 5]); + assert_eq!(f.i32(&[1, 2]), [3, 4, 5]); + assert_eq!(f.u8(&[1, 2]), [3, 4, 5]); + assert_eq!(f.u8_clamped(&[1, 2]), [3, 4, 5]); + assert_eq!(f.u16(&[1, 2]), [3, 4, 5]); + assert_eq!(f.u32(&[1, 2]), [3, 4, 5]); + } + "#, + ) + .test(); +} diff --git a/crates/webidl/tests/all/main.rs b/crates/webidl/tests/all/main.rs index 3815c632..1cbcd84e 100644 --- a/crates/webidl/tests/all/main.rs +++ b/crates/webidl/tests/all/main.rs @@ -5,3 +5,4 @@ mod consts; mod enums; mod simple; mod throws; +mod array;