Skip to content

Commit

Permalink
Implement NonNull descriptor
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Feb 24, 2024
1 parent b2ca0e6 commit 5f49913
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 5 deletions.
3 changes: 3 additions & 0 deletions crates/cli-support/src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ tys! {
RESULT
UNIT
CLAMPED
NONNULL
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -72,6 +73,7 @@ pub enum Descriptor {
Option(Box<Descriptor>),
Result(Box<Descriptor>),
Unit,
NonNull,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -165,6 +167,7 @@ impl Descriptor {
CHAR => Descriptor::Char,
UNIT => Descriptor::Unit,
CLAMPED => Descriptor::_decode(data, true),
NONNULL => Descriptor::NonNull,
other => panic!("unknown descriptor: {}", other),
}
}
Expand Down
15 changes: 14 additions & 1 deletion crates/cli-support/src/js/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,18 @@ fn instruction(
let val = js.pop();
js.push(format!("{0} === {1} ? undefined : {0}", val, hole));
}

Instruction::InNonNullSentinel => {
let val = js.pop();
js.cx.expose_is_like_none();
js.assert_optional_number(&val);
js.push(format!("isLikeNone({0}) ? 0 : {0}", val));
}

Instruction::OutNonNullSentinel => {
let val = js.pop();
js.push(format!("{0} === 0 ? undefined : {0}", val));
}
}
Ok(())
}
Expand Down Expand Up @@ -1324,7 +1336,8 @@ fn adapter2ts(ty: &AdapterType, dst: &mut String) {
| AdapterType::U16
| AdapterType::U32
| AdapterType::F32
| AdapterType::F64 => dst.push_str("number"),
| AdapterType::F64
| AdapterType::NonNull => dst.push_str("number"),
AdapterType::I64 | AdapterType::S64 | AdapterType::U64 => dst.push_str("bigint"),
AdapterType::String => dst.push_str("string"),
AdapterType::Externref => dst.push_str("any"),
Expand Down
8 changes: 8 additions & 0 deletions crates/cli-support/src/wit/incoming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ impl InstructionBuilder<'_, '_> {

// Largely synthetic and can't show up
Descriptor::ClampedU8 => unreachable!(),

Descriptor::NonNull => self.number(AdapterType::NonNull, WasmVT::I32),
}
Ok(())
}
Expand Down Expand Up @@ -331,6 +333,12 @@ impl InstructionBuilder<'_, '_> {
);
}

Descriptor::NonNull => self.instruction(
&[AdapterType::NonNull.option()],
Instruction::InNonNullSentinel,
&[AdapterType::I32],
),

_ => bail!(
"unsupported optional argument type for calling Rust function from JS: {:?}",
arg
Expand Down
11 changes: 10 additions & 1 deletion crates/cli-support/src/wit/outgoing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ impl InstructionBuilder<'_, '_> {

// Largely synthetic and can't show up
Descriptor::ClampedU8 => unreachable!(),

Descriptor::NonNull => self.outgoing_i32(AdapterType::NonNull),
}
Ok(())
}
Expand Down Expand Up @@ -319,6 +321,12 @@ impl InstructionBuilder<'_, '_> {
);
}

Descriptor::NonNull => self.instruction(
&[AdapterType::I32],
Instruction::OutNonNullSentinel,
&[AdapterType::NonNull.option()],
),

_ => bail!(
"unsupported optional argument type for calling JS function from Rust: {:?}",
arg
Expand Down Expand Up @@ -350,7 +358,8 @@ impl InstructionBuilder<'_, '_> {
| Descriptor::CachedString
| Descriptor::Option(_)
| Descriptor::Vector(_)
| Descriptor::Unit => {
| Descriptor::Unit
| Descriptor::NonNull => {
// We must throw before reading the Ok type, if there is an error. However, the
// structure of ResultAbi is that the Err value + discriminant come last (for
// alignment reasons). So the UnwrapResult instruction must come first, but the
Expand Down
3 changes: 3 additions & 0 deletions crates/cli-support/src/wit/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub enum AdapterType {
Enum(String),
NamedExternref(String),
Function,
NonNull,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -308,6 +309,8 @@ pub enum Instruction {
OptionEnumFromI32 {
hole: u32,
},
InNonNullSentinel,
OutNonNullSentinel,
}

impl AdapterType {
Expand Down
3 changes: 2 additions & 1 deletion src/describe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ tys! {
RESULT
UNIT
CLAMPED
NONNULL
}

#[inline(always)] // see the wasm-interpreter crate
Expand Down Expand Up @@ -118,7 +119,7 @@ impl<T> WasmDescribe for *mut T {

impl<T> WasmDescribe for NonNull<T> {
fn describe() {
inform(U32)
inform(NONNULL)
}
}

Expand Down
9 changes: 9 additions & 0 deletions tests/wasm/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,12 @@ exports.test_string_roundtrip = () => {
test('a longer string');
test('a longer 💖 string');
};

exports.test_non_null = function() {
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);

assert.strictEqual(wasm.simple_option_nonnull_work(wasm.simple_return_non_null()), 42);
assert.strictEqual(wasm.simple_option_nonnull_work(wasm.simple_return_option_non_null(43)), 43);
};
21 changes: 19 additions & 2 deletions tests/wasm/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ extern "C" {
fn new_renamed() -> Renamed;

fn test_string_roundtrip();

fn test_non_null();
}

#[wasm_bindgen_test]
Expand Down Expand Up @@ -74,8 +76,23 @@ pub unsafe fn simple_option_raw_pointers_work(
}

#[wasm_bindgen]
pub fn simple_option_nonnull_work(a: Option<NonNull<u32>>) -> Option<NonNull<u32>> {
a
pub fn simple_return_non_null() -> NonNull<u32> {
NonNull::from(Box::leak(Box::new(42)))
}

#[wasm_bindgen]
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_option_nonnull_work(a: Option<NonNull<u32>>) -> Option<u32> {
a.map(|ptr| *Box::from_raw(ptr.as_ptr()))
}

#[wasm_bindgen_test]
fn non_null() {
test_non_null();
}

#[wasm_bindgen_test]
Expand Down

0 comments on commit 5f49913

Please sign in to comment.