Skip to content

Commit 4a0c69f

Browse files
afdwalexcrichton
authored andcommitted
Add support for optional bools
1 parent 0ef5281 commit 4a0c69f

File tree

5 files changed

+74
-4
lines changed

5 files changed

+74
-4
lines changed

crates/cli-support/src/js/js2rust.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,26 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
259259
return Ok(self);
260260
}
261261

262-
bail!("unsupported optional argument type for calling Rust function from JS: {:?}", arg);
262+
match *arg {
263+
Descriptor::Boolean => {
264+
self.cx.expose_is_like_none();
265+
self.js_arguments.push((name.clone(), "boolean".to_string()));
266+
if self.cx.config.debug {
267+
self.cx.expose_assert_bool();
268+
self.prelude(&format!(
269+
"
270+
if (!isLikeNone({0})) {{
271+
_assertBoolean({0});
272+
}}
273+
",
274+
name,
275+
));
276+
}
277+
self.rust_arguments.push(format!("isLikeNone({0}) ? 0xFFFFFF : {0} ? 1 : 0", name));
278+
return Ok(self);
279+
},
280+
_ => bail!("unsupported optional argument type for calling Rust function from JS: {:?}", arg),
281+
};
263282
}
264283

265284
if let Some(s) = arg.rust_struct() {
@@ -486,7 +505,17 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
486505
return Ok(self);
487506
}
488507

489-
bail!("unsupported optional return type for calling Rust function from JS: {:?}", ty);
508+
match *ty {
509+
Descriptor::Boolean => {
510+
self.ret_ty = "boolean".to_string();
511+
self.ret_expr = "
512+
const ret = RET;
513+
return ret === 0xFFFFFF ? undefined : ret !== 0;
514+
".to_string();
515+
return Ok(self);
516+
},
517+
_ => bail!("unsupported optional return type for calling Rust function from JS: {:?}", ty),
518+
};
490519
}
491520

492521
if ty.is_ref_anyref() {

crates/cli-support/src/js/rust2js.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,13 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
173173
return Ok(());
174174
}
175175

176-
bail!("unsupported optional argument type for calling JS function from Rust: {:?}", arg);
176+
match *arg {
177+
Descriptor::Boolean => {
178+
self.js_arguments.push(format!("{0} === 0xFFFFFF ? undefined : {0} !== 0", abi));
179+
return Ok(())
180+
},
181+
_ => bail!("unsupported optional argument type for calling JS function from Rust: {:?}", arg),
182+
};
177183
}
178184

179185
if let Some(signed) = arg.get_64() {
@@ -424,7 +430,17 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
424430
return Ok(());
425431
}
426432

427-
bail!("unsupported optional return type for calling JS function from Rust: {:?}", ty);
433+
match *ty {
434+
Descriptor::Boolean => {
435+
self.cx.expose_is_like_none();
436+
self.ret_expr = "
437+
const val = JS;
438+
return isLikeNone(val) ? 0xFFFFFF : val ? 1 : 0;
439+
".to_string();
440+
return Ok(());
441+
},
442+
_ => bail!("unsupported optional return type for calling JS function from Rust: {:?}", ty),
443+
};
428444
}
429445
if ty.is_number() {
430446
self.ret_expr = "return JS;".to_string();

src/convert/impls.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,16 @@ impl FromWasmAbi for bool {
220220
}
221221
}
222222

223+
impl OptionIntoWasmAbi for bool {
224+
#[inline]
225+
fn none() -> u32 { 0xFFFFFFu32 }
226+
}
227+
228+
impl OptionFromWasmAbi for bool {
229+
#[inline]
230+
fn is_none(js: &u32) -> bool { *js == 0xFFFFFFu32 }
231+
}
232+
223233
impl IntoWasmAbi for char {
224234
type Abi = u32;
225235

tests/wasm/optional_numbers.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ exports.test_works = function() {
7676
assert.strictEqual(wasm.u64_identity(wasm.u64_one()), BigInt('1'));
7777
assert.strictEqual(wasm.u64_identity(wasm.u64_max()), BigInt('18446744073709551615'));
7878
assert.strictEqual(wasm.u64_identity(wasm.u64_min()), BigInt('0'));
79+
80+
assert.strictEqual(wasm.bool_identity(wasm.bool_none()), undefined);
81+
assert.strictEqual(wasm.bool_identity(wasm.bool_false()), false);
82+
assert.strictEqual(wasm.bool_identity(wasm.bool_true()), true);
7983
};
8084

8185
exports.i32_js_identity = function(a) { return a; };
@@ -90,3 +94,4 @@ exports.i16_js_identity = function(a) { return a; };
9094
exports.u16_js_identity = function(a) { return a; };
9195
exports.i64_js_identity = function(a) { return a; };
9296
exports.u64_js_identity = function(a) { return a; };
97+
exports.bool_js_identity = function(a) { return a; };

tests/wasm/optional_numbers.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern {
1515
fn u16_js_identity(a: Option<u16>) -> Option<u16>;
1616
fn i64_js_identity(a: Option<i64>) -> Option<i64>;
1717
fn u64_js_identity(a: Option<u64>) -> Option<u64>;
18+
fn bool_js_identity(a: Option<bool>) -> Option<bool>;
1819

1920
fn test_works();
2021
}
@@ -181,6 +182,15 @@ pub fn u64_min() -> Option<u64> { Some(u64::min_value()) }
181182
#[wasm_bindgen]
182183
pub fn u64_identity(a: Option<u64>) -> Option<u64> { u64_js_identity(a) }
183184

185+
#[wasm_bindgen]
186+
pub fn bool_none() -> Option<bool> { None }
187+
#[wasm_bindgen]
188+
pub fn bool_false() -> Option<bool> { Some(false) }
189+
#[wasm_bindgen]
190+
pub fn bool_true() -> Option<bool> { Some(true) }
191+
#[wasm_bindgen]
192+
pub fn bool_identity(a: Option<bool>) -> Option<bool> { bool_js_identity(a) }
193+
184194
#[wasm_bindgen_test]
185195
fn works() {
186196
test_works();

0 commit comments

Comments
 (0)