From b698eb5d6a3703d691da7231db04b5aaf08d7077 Mon Sep 17 00:00:00 2001 From: Frazer McLean Date: Wed, 15 Aug 2018 22:47:49 +0200 Subject: [PATCH] Add more WebAssembly bindings --- crates/js-sys/Cargo.toml | 2 + crates/js-sys/src/lib.rs | 168 ++++++++++++++++++++++-- crates/js-sys/tests/wasm/WebAssembly.js | 23 ++++ crates/js-sys/tests/wasm/WebAssembly.rs | 134 ++++++++++++++++++- crates/js-sys/tests/wasm/main.rs | 2 + 5 files changed, 314 insertions(+), 15 deletions(-) create mode 100644 crates/js-sys/tests/wasm/WebAssembly.js diff --git a/crates/js-sys/Cargo.toml b/crates/js-sys/Cargo.toml index 2ff5c8b5..2bd93a7c 100644 --- a/crates/js-sys/Cargo.toml +++ b/crates/js-sys/Cargo.toml @@ -18,7 +18,9 @@ test = false doctest = false [dependencies] +futures = "0.1.20" wasm-bindgen = { path = "../..", version = "0.2.16" } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = { path = '../test', version = '=0.2.16' } +wasm-bindgen-futures = { path = '../futures', version = '=0.2.16' } diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index bed5d2e7..c5efcbe0 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -2843,19 +2843,163 @@ extern "C" { pub fn delete(this: &WeakSet, value: &Object) -> bool; } -// WebAssembly -#[wasm_bindgen] -extern "C" { - #[derive(Clone, Debug)] - pub type WebAssembly; +#[allow(non_snake_case)] +pub mod WebAssembly { + use super::*; - /// The `WebAssembly.validate()` function validates a given typed - /// array of WebAssembly binary code, returning whether the bytes - /// form a valid wasm module (`true`) or not (`false`). - /// - /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate - #[wasm_bindgen(static_method_of = WebAssembly, catch)] - pub fn validate(bufferSource: &JsValue) -> Result; + // WebAssembly + #[wasm_bindgen] + extern "C" { + /// `The WebAssembly.compile()` function compiles a `WebAssembly.Module` + /// from WebAssembly binary code. This function is useful if it is + /// necessary to a compile a module before it can be instantiated + /// (otherwise, the `WebAssembly.instantiate()` function should be used). + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/compile + #[wasm_bindgen(js_namespace = WebAssembly)] + pub fn compile(buffer_source: &JsValue) -> Promise; + + /// The `WebAssembly.validate()` function validates a given typed + /// array of WebAssembly binary code, returning whether the bytes + /// form a valid wasm module (`true`) or not (`false`). + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate + #[wasm_bindgen(js_namespace = WebAssembly, catch)] + pub fn validate(buffer_source: &JsValue) -> Result; + } + + // WebAssembly.CompileError + #[wasm_bindgen] + extern "C" { + /// The `WebAssembly.CompileError()` constructor creates a new + /// WebAssembly `CompileError` object, which indicates an error during + /// WebAssembly decoding or validation. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/CompileError + #[wasm_bindgen(extends = Error, js_namespace = WebAssembly)] + #[derive(Clone, Debug)] + pub type CompileError; + + /// The `WebAssembly.CompileError()` constructor creates a new + /// WebAssembly `CompileError` object, which indicates an error during + /// WebAssembly decoding or validation. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/CompileError + #[wasm_bindgen(constructor, js_namespace = WebAssembly)] + pub fn new(message: &str) -> CompileError; + } + + // WebAssembly.LinkError + #[wasm_bindgen] + extern "C" { + /// The `WebAssembly.LinkError()` constructor creates a new WebAssembly + /// LinkError object, which indicates an error during module + /// instantiation (besides traps from the start function). + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/LinkError + #[wasm_bindgen(extends = Error, js_namespace = WebAssembly)] + #[derive(Clone, Debug)] + pub type LinkError; + + /// The `WebAssembly.LinkError()` constructor creates a new WebAssembly + /// LinkError object, which indicates an error during module + /// instantiation (besides traps from the start function). + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/LinkError + #[wasm_bindgen(constructor, js_namespace = WebAssembly)] + pub fn new(message: &str) -> LinkError; + } + + // WebAssembly.RuntimeError + #[wasm_bindgen] + extern "C" { + /// The `WebAssembly.RuntimeError()` constructor creates a new WebAssembly + /// `RuntimeError` object — the type that is thrown whenever WebAssembly + /// specifies a trap. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/RuntimeError + #[wasm_bindgen(extends = Error, js_namespace = WebAssembly)] + #[derive(Clone, Debug)] + pub type RuntimeError; + + /// The `WebAssembly.RuntimeError()` constructor creates a new WebAssembly + /// `RuntimeError` object — the type that is thrown whenever WebAssembly + /// specifies a trap. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/RuntimeError + #[wasm_bindgen(constructor, js_namespace = WebAssembly)] + pub fn new(message: &str) -> RuntimeError; + } + + // WebAssembly.Module + #[wasm_bindgen] + extern "C" { + /// A `WebAssembly.Module` object contains stateless WebAssembly code + /// that has already been compiled by the browser and can be + /// efficiently shared with Workers, and instantiated multiple times. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module + #[wasm_bindgen(js_namespace = WebAssembly, extends = Object)] + #[derive(Clone, Debug)] + pub type Module; + + /// A `WebAssembly.Module` object contains stateless WebAssembly code + /// that has already been compiled by the browser and can be + /// efficiently shared with Workers, and instantiated multiple times. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module + #[wasm_bindgen(constructor, js_namespace = WebAssembly)] + pub fn new(buffer_source: &JsValue) -> Module; + + /// The `WebAssembly.customSections()` function returns a copy of the + /// contents of all custom sections in the given module with the given + /// string name. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections + #[wasm_bindgen(static_method_of = Module, js_namespace = WebAssembly, js_name = customSections, catch)] + pub fn custom_sections(module: &Module, sectionName: &str) -> Result; + + /// The `WebAssembly.exports()` function returns an array containing + /// descriptions of all the declared exports of the given `Module`. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports + #[wasm_bindgen(static_method_of = Module, js_namespace = WebAssembly, catch)] + pub fn exports(module: &Module) -> Result; + + /// The `WebAssembly.imports()` function returns an array containing + /// descriptions of all the declared imports of the given `Module`. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports + #[wasm_bindgen(static_method_of = Module, js_namespace = WebAssembly, catch)] + pub fn imports(module: &Module) -> Result; + } + + // WebAssembly.Table + #[wasm_bindgen] + extern "C" { + /// The `WebAssembly.Table()` constructor creates a new `Table` object + /// of the given size and element type. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table + #[wasm_bindgen(js_namespace = WebAssembly, extends = Object)] + #[derive(Clone, Debug)] + pub type Table; + + /// The `WebAssembly.Table()` constructor creates a new `Table` object + /// of the given size and element type. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table + #[wasm_bindgen(constructor, js_namespace = WebAssembly)] + pub fn new(table_descriptor: &JsValue) -> Table; + + /// The `length` prototype property of the `WebAssembly.Table` object + /// returns the length of the table, i.e. the number of elements in the + /// table. + /// + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length + #[wasm_bindgen(method, getter, js_namespace = WebAssembly)] + pub fn length(this: &Table) -> u32; + } } // JSON diff --git a/crates/js-sys/tests/wasm/WebAssembly.js b/crates/js-sys/tests/wasm/WebAssembly.js new file mode 100644 index 00000000..ec9310a3 --- /dev/null +++ b/crates/js-sys/tests/wasm/WebAssembly.js @@ -0,0 +1,23 @@ +const { TextEncoder } = require("util"); + +const data = + "\u0000asm\u0001\u0000\u0000\u0000\u0001\b\u0002`\u0001\u007f\u0000`\u0000" + + "\u0000\u0002\u0019\u0001\u0007imports\rimported_func\u0000\u0000\u0003" + + "\u0002\u0001\u0001\u0007\u0011\u0001\rexported_func\u0000\u0001\n\b\u0001" + + "\u0006\u0000A*\u0010\u0000\u000b"; + +const encoder = new TextEncoder(); +const wasmArray = encoder.encode(data); + +function getWasmArray() { + return wasmArray; +} + +function getTableObject() { + return { element: "anyfunc", initial: 1 } +} + +module.exports = { + getWasmArray, + getTableObject, +}; diff --git a/crates/js-sys/tests/wasm/WebAssembly.rs b/crates/js-sys/tests/wasm/WebAssembly.rs index 14fc5307..6a2a9cc3 100644 --- a/crates/js-sys/tests/wasm/WebAssembly.rs +++ b/crates/js-sys/tests/wasm/WebAssembly.rs @@ -1,9 +1,137 @@ -use wasm_bindgen_test::*; +use futures::Future; use js_sys::*; +use wasm_bindgen::{JsCast, prelude::*}; +use wasm_bindgen_futures::JsFuture; +use wasm_bindgen_test::*; + +#[wasm_bindgen(module = "tests/wasm/WebAssembly.js")] +extern { + #[wasm_bindgen(js_name = getWasmArray)] + fn get_wasm_array() -> Uint8Array; + + #[wasm_bindgen(js_name = getTableObject)] + fn get_table_object() -> Object; +} + +fn get_invalid_wasm() -> JsValue { + ArrayBuffer::new(42).into() +} + +fn get_bad_type_wasm() -> JsValue { + 2.into() +} + +fn get_valid_wasm() -> JsValue { + get_wasm_array().into() +} #[wasm_bindgen_test] fn validate() { - assert!(!WebAssembly::validate(&ArrayBuffer::new(42).into()).unwrap()); + assert!(!WebAssembly::validate(&get_invalid_wasm()).unwrap()); - assert!(WebAssembly::validate(&2.into()).is_err()); + assert!(WebAssembly::validate(&get_bad_type_wasm()).is_err()); +} + +#[wasm_bindgen_test(async)] +fn compile_compile_error() -> impl Future { + let p = WebAssembly::compile(&get_invalid_wasm()); + JsFuture::from(p) + .map(|_| unreachable!()) + .or_else(|e| { + assert!(e.is_instance_of::()); + Ok(()) + }) +} + +#[wasm_bindgen_test(async)] +fn compile_type_error() -> impl Future { + let p = WebAssembly::compile(&get_bad_type_wasm()); + JsFuture::from(p) + .map(|_| unreachable!()) + .or_else(|e| { + assert!(e.is_instance_of::()); + Ok(()) + }) +} + +#[wasm_bindgen_test(async)] +fn compile_valid() -> impl Future { + let p = WebAssembly::compile(&get_valid_wasm()); + JsFuture::from(p) + .map(|module| { + assert!(module.is_instance_of::()); + }) + .map_err(|_| unreachable!()) +} + +#[wasm_bindgen_test] +fn module_inheritance() { + let module = WebAssembly::Module::new(&get_valid_wasm()); + assert!(module.is_instance_of::()); + assert!(module.is_instance_of::()); + + let _: &Object = module.as_ref(); +} + +#[wasm_bindgen_test] +fn module_custom_sections() { + let module = WebAssembly::Module::new(&get_valid_wasm()); + let cust_sec = WebAssembly::Module::custom_sections(&module, "abcd").unwrap(); + assert_eq!(cust_sec.length(), 0); +} + +#[wasm_bindgen_test] +fn module_exports() { + let module = WebAssembly::Module::new(&get_valid_wasm()); + let exports = WebAssembly::Module::exports(&module).unwrap(); + assert_eq!(exports.length(), 1); +} + +#[wasm_bindgen_test] +fn module_imports() { + let module = WebAssembly::Module::new(&get_valid_wasm()); + let imports = WebAssembly::Module::imports(&module).unwrap(); + assert_eq!(imports.length(), 1); +} + +#[wasm_bindgen_test] +fn table_inheritance() { + let table = WebAssembly::Table::new(&get_table_object().into()); + assert!(table.is_instance_of::()); + assert!(table.is_instance_of::()); + + let _: &Object = table.as_ref(); +} + +#[wasm_bindgen_test] +fn table() { + let table = WebAssembly::Table::new(&get_table_object().into()); + assert_eq!(table.length(), 1); +} + +#[wasm_bindgen_test] +fn compile_error_inheritance() { + let error = WebAssembly::CompileError::new(""); + assert!(error.is_instance_of::()); + assert!(error.is_instance_of::()); + + let _: &Error = error.as_ref(); +} + +#[wasm_bindgen_test] +fn link_error_inheritance() { + let error = WebAssembly::LinkError::new(""); + assert!(error.is_instance_of::()); + assert!(error.is_instance_of::()); + + let _: &Error = error.as_ref(); +} + +#[wasm_bindgen_test] +fn runtime_error_inheritance() { + let error = WebAssembly::RuntimeError::new(""); + assert!(error.is_instance_of::()); + assert!(error.is_instance_of::()); + + let _: &Error = error.as_ref(); } diff --git a/crates/js-sys/tests/wasm/main.rs b/crates/js-sys/tests/wasm/main.rs index 36271531..35202a2d 100755 --- a/crates/js-sys/tests/wasm/main.rs +++ b/crates/js-sys/tests/wasm/main.rs @@ -2,8 +2,10 @@ #![feature(use_extern_macros)] #![allow(non_snake_case)] +extern crate futures; extern crate js_sys; extern crate wasm_bindgen; +extern crate wasm_bindgen_futures; extern crate wasm_bindgen_test; pub mod global_fns;