wasm-bindgen/guide/src/feature-reference.md
Alex Crichton cbeb301371
Add support for optional slice types (#507)
* Shard the `convert.rs` module into sub-modules

Hopefully this'll make the organization a little nicer over time!

* Start adding support for optional types

This commit starts adding support for optional types to wasm-bindgen as
arguments/return values to functions. The strategy here is to add two new
traits, `OptionIntoWasmAbi` and `OptionFromWasmAbi`. These two traits are used
as a blanket impl to implement `IntoWasmAbi` and `FromWasmAbi` for `Option<T>`.

Some consequences of this design:

* It should be possible to ensure `Option<SomeForeignType>` implements to/from
  wasm traits. This is because the option-based traits can be implemented for
  foreign types.
* A specialized implementation is possible for all types, so there's no need for
  `Option<T>` to introduce unnecessary overhead.
* Two new traits is a bit unforutnate but I can't currently think of an
  alternative design that works for the above two constraints, although it
  doesn't mean one doesn't exist!
* The error messages for "can't use this type here" is actually halfway decent
  because it says these new traits need to be implemented, which provides a good
  place to document and talk about what's going on here!
* Nested references like `Option<&T>` can't implement `FromWasmAbi`. This means
  that you can't define a function in Rust which takes `Option<&str>`. It may be
  possible to do this one day but it'll likely require more trait trickery than
  I'm capable of right now.

* Add support for optional slices

This commit adds support for optional slice types, things like strings and
arrays. The null representation of these has a pointer value of 0, which should
never happen in normal Rust. Otherwise the various plumbing is done throughout
the tooling to enable these types in all locations.

* Fix `takeObject` on global sentinels

These don't have a reference count as they're always expected to work, so avoid
actually dropping a reference on them.

* Remove some no longer needed bindings

* Add support for optional anyref types

This commit adds support for optional imported class types. Each type imported
with `#[wasm_bindgen]` automatically implements the relevant traits and now
supports `Option<Foo>` in various argument/return positions.

* Fix building without the `std` feature

* Actually fix the build...

* Add support for optional types to WebIDL

Closes #502
2018-07-19 14:44:23 -05:00

52 lines
2.6 KiB
Markdown

# Feature Reference
Here this section will attempt to be a reference for the various features
implemented in this project. This is likely not exhaustive but the [tests]
should also be a great place to look for examples.
[tests]: https://github.com/rustwasm/wasm-bindgen/tree/master/tests
The `#[wasm_bindgen]` attribute can be attached to functions, structs,
impls, and foreign modules. Impls can only contain functions, and the attribute
cannot be attached to functions in an impl block or functions in a foreign
module. No lifetime parameters or type parameters are allowed on any of these
types. Foreign modules must have the `"C"` abi (or none listed). Free functions
with `#[wasm_bindgen]` might not have the `"C"` abi or none listed, and it's also not
necessary to annotate with the `#[no_mangle]` attribute.
All structs referenced through arguments to functions should be defined in the
macro itself. Arguments allowed implement the `WasmBoundary` trait, and examples
are:
* Integers (u64/i64 require `BigInt` support)
* Floats
* Borrowed strings (`&str`)
* Owned strings (`String`)
* Exported structs (`Foo`, annotated with `#[wasm_bindgen]`)
* Exported C-like enums (`Foo`, annotated with `#[wasm_bindgen]`)
* Imported types in a foreign module annotated with `#[wasm_bindgen]`
* Borrowed exported structs (`&Foo` or `&mut Bar`)
* The `JsValue` type and `&JsValue` (not mutable references)
* Vectors and slices of supported integer types and of the `JsValue` type.
* Optional vectors/slices
All of the above can also be returned except borrowed references. Passing
`Vec<JsValue>` as an argument to a function is not currently supported. Strings are
implemented with shim functions to copy data in/out of the Rust heap. That is, a
string passed to Rust from JS is copied to the Rust heap (using a generated shim
to malloc some space) and then will be freed appropriately.
Owned values are implemented through boxes. When you return a `Foo` it's
actually turned into `Box<RefCell<Foo>>` under the hood and returned to JS as a
pointer. The pointer is to have a defined ABI, and the `RefCell` is to ensure
safety with reentrancy and aliasing in JS. In general you shouldn't see
`RefCell` panics with normal usage.
JS-values-in-Rust are implemented through indexes that index a table generated
as part of the JS bindings. This table is managed via the ownership specified in
Rust and through the bindings that we're returning. More information about this
can be found in the [design doc].
All of these constructs currently create relatively straightforward code on the
JS side of things, mostly having a 1:1 match in Rust with JS.