From 1a7d6de1b2988e34b510a5c9714f9e28786bad26 Mon Sep 17 00:00:00 2001 From: Cameron Taggart Date: Tue, 23 Jun 2020 09:24:26 -0600 Subject: [PATCH] add dyn for Fn (#2212) * add dyn for Fn * revert invalid-imports changes * add one more dyn in doc comments --- .gitignore | 1 + guide/src/contributing/design/describe.md | 2 +- .../design/rust-type-conversions.md | 2 +- .../reference/passing-rust-closures-to-js.md | 14 +- guide/src/web-sys/type-translations.md | 2 +- src/closure.rs | 20 +-- tests/wasm/closures.rs | 134 +++++++++--------- 7 files changed, 88 insertions(+), 87 deletions(-) diff --git a/.gitignore b/.gitignore index 4bc7132f..2abb2923 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ yarn.lock /publish /publish.exe .vscode +webdriver.json diff --git a/guide/src/contributing/design/describe.md b/guide/src/contributing/design/describe.md index 5105b4e1..d8684b2f 100644 --- a/guide/src/contributing/design/describe.md +++ b/guide/src/contributing/design/describe.md @@ -40,7 +40,7 @@ In addition to the shims we talked about above which JS generates the macro ``` #[no_mangle] pub extern "C" fn __wbindgen_describe_greet() { - ::describe(); + ::describe(); } ``` diff --git a/guide/src/contributing/design/rust-type-conversions.md b/guide/src/contributing/design/rust-type-conversions.md index 2d36e25d..5565b684 100644 --- a/guide/src/contributing/design/rust-type-conversions.md +++ b/guide/src/contributing/design/rust-type-conversions.md @@ -86,7 +86,7 @@ functions imported into Rust. Mentioned above not all Rust types will fit within 32 bits. While we can communicate an `f64` we don't necessarily have the ability to use all the bits. Types like `&str` need to communicate two items, a pointer and a length (64 -bits). Other types like `&Closure` have even more information to +bits). Other types like `&Closure` have even more information to transmit. As a result we need a method of communicating more data through the signatures diff --git a/guide/src/reference/passing-rust-closures-to-js.md b/guide/src/reference/passing-rust-closures-to-js.md index 3d4a8723..1ebaef69 100644 --- a/guide/src/reference/passing-rust-closures-to-js.md +++ b/guide/src/reference/passing-rust-closures-to-js.md @@ -11,17 +11,17 @@ JavaScript in two variants: ## Stack-Lifetime Closures -Closures with a stack lifetime are passed to JavaScript as either `&Fn` or `&mut -FnMut` trait objects: +Closures with a stack lifetime are passed to JavaScript as either `&dyn Fn` or `&mut +dyn FnMut` trait objects: ```rust // Import JS functions that take closures #[wasm_bindgen] extern "C" { - fn takes_immutable_closure(f: &Fn()); + fn takes_immutable_closure(f: &dyn Fn()); - fn takes_mutable_closure(f: &mut FnMut()); + fn takes_mutable_closure(f: &mut dyn FnMut()); } // Usage @@ -45,7 +45,7 @@ Closures also support arguments and return values like exports do, for example: ```rust #[wasm_bindgen] extern "C" { - fn takes_closure_that_takes_int_and_returns_string(x: &Fn(u32) -> String); + fn takes_closure_that_takes_int_and_returns_string(x: &dyn Fn(u32) -> String); } takes_closure_that_takes_int_and_returns_string(&|x: u32| -> String { @@ -81,7 +81,7 @@ as arguments and returns. ```rust #[wasm_bindgen] extern "C" { - fn setInterval(closure: &Closure, millis: u32) -> f64; + fn setInterval(closure: &Closure, millis: u32) -> f64; fn cancelInterval(token: f64); #[wasm_bindgen(js_namespace = console)] @@ -90,7 +90,7 @@ extern "C" { #[wasm_bindgen] pub struct Interval { - closure: Closure, + closure: Closure, token: f64, } diff --git a/guide/src/web-sys/type-translations.md b/guide/src/web-sys/type-translations.md index 77a8dab1..9c2e7373 100644 --- a/guide/src/web-sys/type-translations.md +++ b/guide/src/web-sys/type-translations.md @@ -16,7 +16,7 @@ all Web APIs)][webidl] have relatively straightforward translations into * Callbacks are all represented as `js_sys::Function`. This means that all callbacks going through `web-sys` are a raw JS value. You can work with this by either juggling actual `js_sys::Function` instances or you can create a - `Closure`, extract the underlying `JsValue` with `as_ref`, and + `Closure`, extract the underlying `JsValue` with `as_ref`, and then use `JsCast::unchecked_ref` to convert it to a `js_sys::Function`. [webidl]: https://heycam.github.io/webidl/ diff --git a/src/closure.rs b/src/closure.rs index e1a2ffd1..745f02e2 100644 --- a/src/closure.rs +++ b/src/closure.rs @@ -48,7 +48,7 @@ use crate::UnwrapThrowExt; /// /// #[wasm_bindgen] /// extern "C" { -/// fn setInterval(closure: &Closure, time: u32) -> i32; +/// fn setInterval(closure: &Closure, time: u32) -> i32; /// fn clearInterval(id: i32); /// /// #[wasm_bindgen(js_namespace = console)] @@ -58,7 +58,7 @@ use crate::UnwrapThrowExt; /// #[wasm_bindgen] /// pub struct IntervalHandle { /// interval_id: i32, -/// _closure: Closure, +/// _closure: Closure, /// } /// /// impl Drop for IntervalHandle { @@ -73,7 +73,7 @@ use crate::UnwrapThrowExt; /// // a JS closure. /// let cb = Closure::wrap(Box::new(|| { /// log("interval elapsed!"); -/// }) as Box); +/// }) as Box); /// /// // Next we pass this via reference to the `setInterval` function, and /// // `setInterval` gets a handle to the corresponding JS closure. @@ -101,7 +101,7 @@ use crate::UnwrapThrowExt; /// #[wasm_bindgen] /// pub struct IntervalHandle { /// interval_id: i32, -/// _closure: Closure, +/// _closure: Closure, /// } /// /// impl Drop for IntervalHandle { @@ -115,7 +115,7 @@ use crate::UnwrapThrowExt; /// pub fn run() -> Result { /// let cb = Closure::wrap(Box::new(|| { /// web_sys::console::log_1(&"inverval elapsed!".into()); -/// }) as Box); +/// }) as Box); /// /// let window = web_sys::window().unwrap(); /// let interval_id = window.set_interval_with_callback_and_timeout_and_arguments_0( @@ -144,7 +144,7 @@ use crate::UnwrapThrowExt; /// /// #[wasm_bindgen] /// extern "C" { -/// fn requestAnimationFrame(closure: &Closure) -> u32; +/// fn requestAnimationFrame(closure: &Closure) -> u32; /// fn cancelAnimationFrame(id: u32); /// /// #[wasm_bindgen(js_namespace = console)] @@ -154,7 +154,7 @@ use crate::UnwrapThrowExt; /// #[wasm_bindgen] /// pub struct AnimationFrameHandle { /// animation_id: u32, -/// _closure: Closure, +/// _closure: Closure, /// } /// /// impl Drop for AnimationFrameHandle { @@ -377,12 +377,12 @@ where // NB: we use a specific `T` for this `Closure` impl block to avoid every // call site having to provide an explicit, turbo-fished type like -// `Closure::::once(...)`. +// `Closure::::once(...)`. impl Closure { /// Create a `Closure` from a function that can only be called once. /// /// Since we have no way of enforcing that JS cannot attempt to call this - /// `FnOne(A...) -> R` more than once, this produces a `Closure R` more than once, this produces a `Closure R>` that will dynamically throw a JavaScript error if called more /// than once. /// @@ -404,7 +404,7 @@ impl Closure { /// /// // Create a `Closure` from `f`. Note that the `Closure`'s type parameter /// // is `FnMut`, even though `f` is `FnOnce`. - /// let closure: Closure String> = Closure::once(f); + /// let closure: Closure String> = Closure::once(f); /// ``` pub fn once(fn_once: F) -> Closure where diff --git a/tests/wasm/closures.rs b/tests/wasm/closures.rs index 925ca6b1..d1dc6976 100644 --- a/tests/wasm/closures.rs +++ b/tests/wasm/closures.rs @@ -7,89 +7,89 @@ use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/closures.js")] extern "C" { - fn works_call(a: &Fn()); - fn works_thread(a: &Fn(u32) -> u32) -> u32; + fn works_call(a: &dyn Fn()); + fn works_thread(a: &dyn Fn(u32) -> u32) -> u32; - fn cannot_reuse_call(a: &Fn()); + fn cannot_reuse_call(a: &dyn Fn()); #[wasm_bindgen(catch)] fn cannot_reuse_call_again() -> Result<(), JsValue>; - fn long_lived_call1(a: &Closure); - fn long_lived_call2(a: &Closure u32>) -> u32; + fn long_lived_call1(a: &Closure); + fn long_lived_call2(a: &Closure u32>) -> u32; - fn many_arity_call1(a: &Closure); - fn many_arity_call2(a: &Closure); - fn many_arity_call3(a: &Closure); - fn many_arity_call4(a: &Closure); - fn many_arity_call5(a: &Closure); - fn many_arity_call6(a: &Closure); - fn many_arity_call7(a: &Closure); - fn many_arity_call8(a: &Closure); - fn many_arity_call9(a: &Closure); + fn many_arity_call1(a: &Closure); + fn many_arity_call2(a: &Closure); + fn many_arity_call3(a: &Closure); + fn many_arity_call4(a: &Closure); + fn many_arity_call5(a: &Closure); + fn many_arity_call6(a: &Closure); + fn many_arity_call7(a: &Closure); + fn many_arity_call8(a: &Closure); + fn many_arity_call9(a: &Closure); #[wasm_bindgen(js_name = many_arity_call1)] - fn many_arity_call_mut1(a: &Closure); + fn many_arity_call_mut1(a: &Closure); #[wasm_bindgen(js_name = many_arity_call2)] - fn many_arity_call_mut2(a: &Closure); + fn many_arity_call_mut2(a: &Closure); #[wasm_bindgen(js_name = many_arity_call3)] - fn many_arity_call_mut3(a: &Closure); + fn many_arity_call_mut3(a: &Closure); #[wasm_bindgen(js_name = many_arity_call4)] - fn many_arity_call_mut4(a: &Closure); + fn many_arity_call_mut4(a: &Closure); #[wasm_bindgen(js_name = many_arity_call5)] - fn many_arity_call_mut5(a: &Closure); + fn many_arity_call_mut5(a: &Closure); #[wasm_bindgen(js_name = many_arity_call6)] - fn many_arity_call_mut6(a: &Closure); + fn many_arity_call_mut6(a: &Closure); #[wasm_bindgen(js_name = many_arity_call7)] - fn many_arity_call_mut7(a: &Closure); + fn many_arity_call_mut7(a: &Closure); #[wasm_bindgen(js_name = many_arity_call8)] - fn many_arity_call_mut8(a: &Closure); + fn many_arity_call_mut8(a: &Closure); #[wasm_bindgen(js_name = many_arity_call9)] - fn many_arity_call_mut9(a: &Closure); + fn many_arity_call_mut9(a: &Closure); #[wasm_bindgen(js_name = many_arity_call1)] - fn many_arity_stack1(a: &Fn()); + fn many_arity_stack1(a: &dyn Fn()); #[wasm_bindgen(js_name = many_arity_call2)] - fn many_arity_stack2(a: &Fn(u32)); + fn many_arity_stack2(a: &dyn Fn(u32)); #[wasm_bindgen(js_name = many_arity_call3)] - fn many_arity_stack3(a: &Fn(u32, u32)); + fn many_arity_stack3(a: &dyn Fn(u32, u32)); #[wasm_bindgen(js_name = many_arity_call4)] - fn many_arity_stack4(a: &Fn(u32, u32, u32)); + fn many_arity_stack4(a: &dyn Fn(u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call5)] - fn many_arity_stack5(a: &Fn(u32, u32, u32, u32)); + fn many_arity_stack5(a: &dyn Fn(u32, u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call6)] - fn many_arity_stack6(a: &Fn(u32, u32, u32, u32, u32)); + fn many_arity_stack6(a: &dyn Fn(u32, u32, u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call7)] - fn many_arity_stack7(a: &Fn(u32, u32, u32, u32, u32, u32)); + 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: &Fn(u32, u32, u32, u32, u32, u32, u32)); + 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: &Fn(u32, u32, u32, u32, u32, u32, u32, u32)); + fn many_arity_stack9(a: &dyn Fn(u32, u32, u32, u32, u32, u32, u32, u32)); - fn long_lived_dropping_cache(a: &Closure); + fn long_lived_dropping_cache(a: &Closure); #[wasm_bindgen(catch)] fn long_lived_dropping_call() -> Result<(), JsValue>; - fn long_fnmut_recursive_cache(a: &Closure); + fn long_fnmut_recursive_cache(a: &Closure); #[wasm_bindgen(catch)] fn long_fnmut_recursive_call() -> Result<(), JsValue>; - fn fnmut_call(a: &mut FnMut()); - fn fnmut_thread(a: &mut FnMut(u32) -> u32) -> u32; + fn fnmut_call(a: &mut dyn FnMut()); + fn fnmut_thread(a: &mut dyn FnMut(u32) -> u32) -> u32; - fn fnmut_bad_call(a: &mut FnMut()); + 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 FnMut(String)); + fn string_arguments_call(a: &mut dyn FnMut(String)); - fn string_ret_call(a: &mut FnMut(String) -> String); + fn string_ret_call(a: &mut dyn FnMut(String) -> String); - fn drop_during_call_save(a: &Closure); + fn drop_during_call_save(a: &Closure); fn drop_during_call_call(); fn js_test_closure_returner(); - fn calling_it_throws(a: &Closure) -> bool; + fn calling_it_throws(a: &Closure) -> bool; fn call_val(f: &JsValue); @@ -98,18 +98,18 @@ extern "C" { fn pass_reference_first_arg_twice( a: RefFirstArgument, - b: &Closure, - c: &Closure, + b: &Closure, + c: &Closure, ); #[wasm_bindgen(js_name = pass_reference_first_arg_twice)] fn pass_reference_first_arg_twice2( a: RefFirstArgument, - b: &mut FnMut(&RefFirstArgument), - c: &mut FnMut(&RefFirstArgument), + b: &mut dyn FnMut(&RefFirstArgument), + c: &mut dyn FnMut(&RefFirstArgument), ); fn call_destroyed(a: &JsValue); - fn js_store_forgotten_closure(closure: &Closure); + fn js_store_forgotten_closure(closure: &Closure); fn js_call_forgotten_closure(); } @@ -130,7 +130,7 @@ fn cannot_reuse() { #[wasm_bindgen_test] fn debug() { - let closure = Closure::wrap(Box::new(|| {}) as Box); + let closure = Closure::wrap(Box::new(|| {}) as Box); assert_eq!(&format!("{:?}", closure), "Closure { ... }"); } @@ -379,7 +379,7 @@ fn drop_drops() { } } let a = A; - let x: Closure = Closure::new(move || drop(&a)); + let x: Closure = Closure::new(move || drop(&a)); drop(x); unsafe { assert!(HIT); @@ -402,7 +402,7 @@ fn drop_during_call_ok() { let rc2 = rc.clone(); let x = 3; let a = A; - let x: Closure = Closure::new(move || { + let x: Closure = Closure::new(move || { // "drop ourselves" drop(rc2.borrow_mut().take().unwrap()); @@ -437,7 +437,7 @@ fn drop_during_call_ok() { #[wasm_bindgen_test] fn test_closure_returner() { - type ClosureType = FnMut() -> BadStruct; + type ClosureType = dyn FnMut() -> BadStruct; use js_sys::{Object, Reflect}; use wasm_bindgen::JsCast; @@ -481,22 +481,22 @@ pub struct RefFirstArgument { fn reference_as_first_argument_builds_at_all() { #[wasm_bindgen] extern "C" { - fn ref_first_arg1(a: &Fn(&JsValue)); - fn ref_first_arg2(a: &mut FnMut(&JsValue)); - fn ref_first_arg3(a: &Closure); - fn ref_first_arg4(a: &Closure); - fn ref_first_custom1(a: &Fn(&RefFirstArgument)); - fn ref_first_custom2(a: &mut FnMut(&RefFirstArgument)); - fn ref_first_custom3(a: &Closure); - fn ref_first_custom4(a: &Closure); + fn ref_first_arg1(a: &dyn Fn(&JsValue)); + fn ref_first_arg2(a: &mut dyn FnMut(&JsValue)); + fn ref_first_arg3(a: &Closure); + fn ref_first_arg4(a: &Closure); + fn ref_first_custom1(a: &dyn Fn(&RefFirstArgument)); + fn ref_first_custom2(a: &mut dyn FnMut(&RefFirstArgument)); + fn ref_first_custom3(a: &Closure); + fn ref_first_custom4(a: &Closure); } - Closure::wrap(Box::new(|_: &JsValue| ()) as Box); - Closure::wrap(Box::new(|_: &JsValue| ()) as Box); + Closure::wrap(Box::new(|_: &JsValue| ()) as Box); + Closure::wrap(Box::new(|_: &JsValue| ()) as Box); Closure::once(|_: &JsValue| ()); Closure::once_into_js(|_: &JsValue| ()); - Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box); - Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box); + Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box); + Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box); Closure::once(|_: &RefFirstArgument| ()); Closure::once_into_js(|_: &RefFirstArgument| ()); } @@ -553,25 +553,25 @@ fn call_destroyed_doesnt_segfault() { } let a = A(1, 1); - let a = Closure::wrap(Box::new(move || drop(&a)) as Box); + let a = Closure::wrap(Box::new(move || drop(&a)) as Box); 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); + let a = Closure::wrap(Box::new(move || drop(&a)) as Box); 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); + let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box); 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); + let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box); let b = a.as_ref().clone(); drop(a); call_destroyed(&b); @@ -579,7 +579,7 @@ fn call_destroyed_doesnt_segfault() { #[wasm_bindgen_test] fn forget_works() { - let a = Closure::wrap(Box::new(|| {}) as Box); + let a = Closure::wrap(Box::new(|| {}) as Box); js_store_forgotten_closure(&a); a.forget(); js_call_forgotten_closure();