Skip to content

Commit

Permalink
Implement OptionIntoWasmAbi for Closure references (#2768)
Browse files Browse the repository at this point in the history
* Implement OptionIntoWasmAbi for Closure references

* Add tests for optional closure arguments

* Uncomment None test for optional closure argument

* Tighten None test for optional closure argument

* Add tests for dropping optional closures

Co-authored-by: Billy Bradley <billy@squeno.com>
  • Loading branch information
sinking-point and sinking-point authored Jan 18, 2022
1 parent c25c1f4 commit 3701c9d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,15 @@ where
}
}

impl<'a, T> OptionIntoWasmAbi for &'a Closure<T>
where
T: WasmClosure + ?Sized,
{
fn none() -> Self::Abi {
0
}
}

fn _check() {
fn _assert<T: IntoWasmAbi>() {}
_assert::<&Closure<dyn Fn()>>();
Expand Down
26 changes: 26 additions & 0 deletions tests/wasm/closures.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ 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 => {
Expand All @@ -60,6 +72,20 @@ 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 => {
Expand Down
49 changes: 49 additions & 0 deletions tests/wasm/closures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ extern "C" {
#[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)]
Expand All @@ -69,6 +73,10 @@ extern "C" {
#[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>;
Expand Down Expand Up @@ -235,6 +243,29 @@ fn many_arity() {
);
}

#[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) {
Expand Down Expand Up @@ -300,6 +331,24 @@ fn long_lived_dropping() {
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(|| {
Expand Down

0 comments on commit 3701c9d

Please sign in to comment.