mirror of
https://github.com/tlsnotary/wasm-bindgen.git
synced 2026-01-09 21:58:02 -05:00
Add NonNull<T> as parameter (#3857)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
* Add support for `Option<*const T>`, `Option<*mut T>` and `NonNull<T>`.
|
||||
[#3852](https://github.com/rustwasm/wasm-bindgen/pull/3852)
|
||||
[#3857](https://github.com/rustwasm/wasm-bindgen/pull/3857)
|
||||
|
||||
* Allow overriding the URL used for headless tests by setting `WASM_BINDGEN_TEST_ADDRESS`.
|
||||
[#3861](https://github.com/rustwasm/wasm-bindgen/pull/3861)
|
||||
|
||||
@@ -497,6 +497,11 @@ impl<'a, 'b> JsBuilder<'a, 'b> {
|
||||
self.prelude("}");
|
||||
}
|
||||
|
||||
fn assert_non_null(&mut self, arg: &str) {
|
||||
self.cx.expose_assert_non_null();
|
||||
self.prelude(&format!("_assertNonNull({});", arg));
|
||||
}
|
||||
|
||||
fn assert_optional_bigint(&mut self, arg: &str) {
|
||||
if !self.cx.config.debug {
|
||||
return;
|
||||
@@ -1218,6 +1223,12 @@ fn instruction(
|
||||
js.push(format!("{0} === {1} ? undefined : {0}", val, hole));
|
||||
}
|
||||
|
||||
Instruction::I32FromNonNull => {
|
||||
let val = js.pop();
|
||||
js.assert_non_null(&val);
|
||||
js.push(val);
|
||||
}
|
||||
|
||||
Instruction::I32FromOptionNonNull => {
|
||||
let val = js.pop();
|
||||
js.cx.expose_is_like_none();
|
||||
|
||||
@@ -2103,6 +2103,19 @@ impl<'a> Context<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
fn expose_assert_non_null(&mut self) {
|
||||
if !self.should_write_global("assert_non_null") {
|
||||
return;
|
||||
}
|
||||
self.global(
|
||||
"
|
||||
function _assertNonNull(n) {
|
||||
if (typeof(n) !== 'number' || n === 0) throw new Error(`expected a number argument that is not 0, found ${n}`);
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
fn expose_make_mut_closure(&mut self) -> Result<(), Error> {
|
||||
if !self.should_write_global("make_mut_closure") {
|
||||
return Ok(());
|
||||
|
||||
@@ -156,7 +156,11 @@ impl InstructionBuilder<'_, '_> {
|
||||
// Largely synthetic and can't show up
|
||||
Descriptor::ClampedU8 => unreachable!(),
|
||||
|
||||
Descriptor::NonNull => unimplemented!("converting `NonNull<T>` from Wasm to Rust is not implemented"),
|
||||
Descriptor::NonNull => self.instruction(
|
||||
&[AdapterType::NonNull],
|
||||
Instruction::I32FromNonNull,
|
||||
&[AdapterType::I32],
|
||||
),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -311,6 +311,7 @@ pub enum Instruction {
|
||||
},
|
||||
I32FromOptionNonNull,
|
||||
OptionNonNullFromI32,
|
||||
I32FromNonNull,
|
||||
}
|
||||
|
||||
impl AdapterType {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
| `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<T>` parameter | `Option<T>` return value | JavaScript representation |
|
||||
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| No | No | No | Yes | Yes | Yes | A JavaScript number value |
|
||||
| Yes | No | No | Yes | Yes | Yes | A JavaScript number value |
|
||||
|
||||
## Example Rust Usage
|
||||
|
||||
|
||||
@@ -294,12 +294,20 @@ impl<T> OptionIntoWasmAbi for NonNull<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FromWasmAbi for Option<NonNull<T>> {
|
||||
impl<T> FromWasmAbi for NonNull<T> {
|
||||
type Abi = u32;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_abi(js: Self::Abi) -> Self {
|
||||
NonNull::new(js as *mut T)
|
||||
// SAFETY: Checked in bindings.
|
||||
NonNull::new_unchecked(js as *mut T)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OptionFromWasmAbi for NonNull<T> {
|
||||
#[inline]
|
||||
fn is_none(js: &u32) -> bool {
|
||||
*js == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,9 @@ exports.test_raw_pointers = function() {
|
||||
};
|
||||
|
||||
exports.test_non_null = function() {
|
||||
assert.strictEqual(wasm.simple_nonnull_work(wasm.simple_return_non_null()), 42);
|
||||
assert.throws(() => wasm.simple_nonnull_work(0), /expected a number argument that is not 0/);
|
||||
|
||||
assert.strictEqual(wasm.simple_option_nonnull_work(0), undefined);
|
||||
assert.strictEqual(wasm.simple_option_nonnull_work(null), undefined);
|
||||
assert.strictEqual(wasm.simple_option_nonnull_work(undefined), undefined);
|
||||
|
||||
@@ -113,6 +113,11 @@ pub fn simple_return_option_non_null(value: u32) -> Option<NonNull<u32>> {
|
||||
Some(NonNull::from(Box::leak(Box::new(value))))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub unsafe fn simple_nonnull_work(a: NonNull<u32>) -> u32 {
|
||||
*Box::from_raw(a.as_ptr())
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub unsafe fn simple_option_nonnull_work(a: Option<NonNull<u32>>) -> Option<u32> {
|
||||
a.map(|ptr| *Box::from_raw(ptr.as_ptr()))
|
||||
|
||||
Reference in New Issue
Block a user