diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index c2d2bd3a..843eb404 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -2896,6 +2896,29 @@ pub mod WebAssembly { pub fn new(message: &str) -> CompileError; } + // WebAssembly.Instance + #[wasm_bindgen] + extern "C" { + /// A `WebAssembly.Instance` object is a stateful, executable instance + /// of a `WebAssembly.Module`. Instance objects contain all the exported + /// WebAssembly functions that allow calling into WebAssembly code from + /// JavaScript. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) + #[wasm_bindgen(extends = Object, js_namespace = WebAssembly)] + #[derive(Clone, Debug)] + pub type Instance; + + /// The `WebAssembly.Instance()` constructor function can be called to + /// synchronously instantiate a given `WebAssembly.Module` + /// object. However, the primary way to get an `Instance` is through the + /// asynchronous `WebAssembly.instantiateStreaming()` function. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) + #[wasm_bindgen(catch, constructor, js_namespace = WebAssembly)] + pub fn new(module: &Module, imports: &Object) -> Result; + } + // WebAssembly.LinkError #[wasm_bindgen] extern "C" { diff --git a/crates/js-sys/tests/wasm/WebAssembly.js b/crates/js-sys/tests/wasm/WebAssembly.js index 51d0c343..a24342f5 100644 --- a/crates/js-sys/tests/wasm/WebAssembly.js +++ b/crates/js-sys/tests/wasm/WebAssembly.js @@ -21,8 +21,19 @@ function getInvalidTableObject() { return { element: "anyfunc", initial: 1, maximum: 0 } } +function getImports() { + return { + imports: { + imported_func: function () { + return 1; + } + } + }; +} + module.exports = { getInvalidTableObject, getTableObject, getWasmArray, + getImports, }; diff --git a/crates/js-sys/tests/wasm/WebAssembly.rs b/crates/js-sys/tests/wasm/WebAssembly.rs index 35207f96..ad363acc 100644 --- a/crates/js-sys/tests/wasm/WebAssembly.rs +++ b/crates/js-sys/tests/wasm/WebAssembly.rs @@ -1,11 +1,11 @@ use futures::Future; use js_sys::*; -use wasm_bindgen::{JsCast, prelude::*}; +use wasm_bindgen::{prelude::*, JsCast}; use wasm_bindgen_futures::JsFuture; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/WebAssembly.js")] -extern { +extern "C" { #[wasm_bindgen(js_name = getWasmArray)] fn get_wasm_array() -> Uint8Array; @@ -14,6 +14,9 @@ extern { #[wasm_bindgen(js_name = getInvalidTableObject)] fn get_invalid_table_object() -> Object; + + #[wasm_bindgen(js_name = getImports)] + fn get_imports() -> Object; } fn get_invalid_wasm() -> JsValue { @@ -38,23 +41,19 @@ fn validate() { #[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(()) - }) + 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(()) - }) + JsFuture::from(p).map(|_| unreachable!()).or_else(|e| { + assert!(e.is_instance_of::()); + Ok(()) + }) } #[wasm_bindgen_test(async)] @@ -63,8 +62,7 @@ fn compile_valid() -> impl Future { JsFuture::from(p) .map(|module| { assert!(module.is_instance_of::()); - }) - .map_err(|_| unreachable!()) + }).map_err(|_| unreachable!()) } #[wasm_bindgen_test] @@ -81,7 +79,9 @@ fn module_error() { let error = WebAssembly::Module::new(&get_invalid_wasm()).err().unwrap(); assert!(error.is_instance_of::()); - let error = WebAssembly::Module::new(&get_bad_type_wasm()).err().unwrap(); + let error = WebAssembly::Module::new(&get_bad_type_wasm()) + .err() + .unwrap(); assert!(error.is_instance_of::()); } @@ -117,7 +117,9 @@ fn table_inheritance() { #[wasm_bindgen_test] fn table_error() { - let error = WebAssembly::Table::new(&get_invalid_table_object()).err().unwrap(); + let error = WebAssembly::Table::new(&get_invalid_table_object()) + .err() + .unwrap(); assert!(error.is_instance_of::()); } @@ -154,6 +156,16 @@ fn runtime_error_inheritance() { let _: &Error = error.as_ref(); } +#[wasm_bindgen_test] +fn instance_constructor_and_inheritance() { + let module = WebAssembly::Module::new(&get_valid_wasm()).unwrap(); + let imports = get_imports(); + let instance = WebAssembly::Instance::new(&module, &imports).unwrap(); + assert!(instance.is_instance_of::()); + assert!(instance.is_instance_of::()); + let _: &Object = instance.as_ref(); +} + #[wasm_bindgen_test] fn memory_works() { let obj = Object::new(); @@ -166,7 +178,10 @@ fn memory_works() { assert_eq!(mem.grow(2), 2); assert_eq!(mem.grow(3), 4); assert_eq!( - mem.buffer().dyn_into::().unwrap().byte_length(), + mem.buffer() + .dyn_into::() + .unwrap() + .byte_length(), 7 * 64 * 1024, ); }