Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# tsify Changelog

## v0.5.7

- Added `Ts<T>`, a wrapper for `#[wasm_bindgen]` parameters and return types. `#[tsify(from_wasm_abi)]` deserializes at the ABI boundary, which cannot report failure, so bad input from JavaScript ends in `wasm_bindgen::throw_str` — a catchable JS exception that skips destructors, leaking a little on every failure until the instance dies. `Ts<T>` keeps the boundary infallible and moves the conversion into the function body, where it is an ordinary `Result`. Addresses #65, #47 and #86. @cormacrelf contributed #71
- Deprecated `into_wasm_abi` and `from_wasm_abi` in favour of `Ts<T>`. `into_wasm_abi` panics rather than leaks on failure, but it has the same root cause and the same fix. The attributes still work, and no removal is planned; see the README for details
- `Ts<T>` can now be returned from `async fn`. @hgiesel contributed #84
- `#[tsify(namespace)]` enums now emit `export type E = E.A | E.B` instead of repeating each variant's shape in the union. @hgiesel contributed #78
- Fixed raw string artifacts in doc comments copied into the generated TypeScript. @samkearney contributed the fix

## v0.5.6

- Resolve the issue with default parameters in generics
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tsify"
version = "0.5.6"
version = "0.5.7"
edition = "2021"
authors = [
"Madono Haru <madonoharu@gmail.com>",
Expand All @@ -14,7 +14,7 @@ keywords = ["wasm", "wasm-bindgen", "typescript"]
categories = ["wasm"]

[dependencies]
tsify-macros = { path = "tsify-macros", version = "0.5.5" }
tsify-macros = { path = "tsify-macros", version = "0.5.7" }
wasm-bindgen = { version = "0.2.104", optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }
serde_json = { version = "1.0", optional = true }
Expand Down
22 changes: 7 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Click to show Cargo.toml.

```toml
[dependencies]
tsify = "0.5.5"
tsify = "0.5.7"
serde = { version = "1.0", features = ["derive"] }
wasm-bindgen = { version = "0.2" }
```
Expand Down Expand Up @@ -53,18 +53,15 @@ Will generate the following `.d.ts` file:
```ts
/* tslint:disable */
/* eslint-disable */
/**
* @returns {Point}
*/
export function into_js(): Point;
/**
* @param {Point} point
*/
export function from_js(point: Point): void;
export interface Point {
x: number;
y: number;
}


export function from_js(point: Point): void;

export function into_js(): Point;
```

This is the behavior due to [`typescript_custom_section`](https://rustwasm.github.io/docs/wasm-bindgen/reference/attributes/on-rust-exports/typescript_custom_section.html) and [`Rust Type conversions`](https://rustwasm.github.io/docs/wasm-bindgen/contributing/design/rust-type-conversions.html).
Expand Down Expand Up @@ -233,12 +230,7 @@ declare namespace Color {
};
}

export type Color =
| "Red"
| "Blue"
| "Green"
| { Rgb: [number, number, number] }
| { Hsv: { hue: number; saturation: number; value: number } };
export type Color = Color.Red | Color.Blue | Color.Green | Color.Rgb | Color.Hsv;
```

## Type Aliases
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub struct SerializationConfig {
/// `Tsify` is a trait that allows you to convert a type to and from JavaScript.
/// Can be implemented manually if you need to customize the serialization or deserialization.
pub trait Tsify {
/// Must be a type imported through `#[wasm_bindgen] extern "C" { .. }`.
/// [`Ts<T>`] is `#[repr(transparent)]` over this and passes it across the
/// ABI as a plain JS handle, which any other representation would break.
#[cfg(feature = "wasm-bindgen")]
type JsType: JsCast;

Expand Down
13 changes: 7 additions & 6 deletions src/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ use wasm_bindgen::{JsCast, JsValue};
/// y: f64,
/// }
///
/// /// The panicking version
/// #[wasm_bindgen]
/// pub fn rotate(v: Ts<Vec2>, theta_rad: f64) -> Result<Ts<Vec2>, JsError> {
/// // Deserialize to rust type, throw deserialization error if fails
Expand Down Expand Up @@ -69,7 +68,7 @@ where
Self(js, std::marker::PhantomData)
}

/// Returns the inner JsValue representation. This is a zero cost operation.
/// Returns the inner JsValue representation, cloning the JS handle.
pub fn js_value(&self) -> JsValue
where
<T as Tsify>::JsType: JsCast,
Expand Down Expand Up @@ -148,14 +147,16 @@ where
self.0.into_abi()
}
}
impl<T> IntoWasmAbi for &Ts<T>
impl<'a, T> IntoWasmAbi for &'a Ts<T>
where
T: Tsify,
<T as Tsify>::JsType: IntoWasmAbi + Clone,
<T as Tsify>::JsType: JsCast + WasmDescribe,
{
type Abi = <T::JsType as IntoWasmAbi>::Abi;
type Abi = <&'a JsValue as IntoWasmAbi>::Abi;
// Borrowed, so the handle stays owned here. Cloning it would hand JS an
// extra table slot that the borrowed-argument shim never releases.
fn into_abi(self) -> Self::Abi {
self.0.clone().into_abi()
self.0.unchecked_ref::<JsValue>().into_abi()
}
}
impl<T> FromWasmAbi for Ts<T>
Expand Down
5 changes: 5 additions & 0 deletions tests-e2e/build_all.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#!/bin/bash

# Without this a failed `wasm-pack build` is followed by a successful `popd`,
# so the script reports success and compare_output.sh then compares stale
# artifacts.
set -e

# Define the root directory for the search
ROOT_DIR="tests-e2e"

Expand Down
5 changes: 5 additions & 0 deletions tests-e2e/reference_output/compare_output.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ for FOLDERNAME in $(find . -maxdepth 1 -type d); do
else
echo " Files are identical"
fi
else
# A reference with no counterpart means the build stopped emitting
# it; skipping would report that regression as success.
echo "Missing generated file: $OTHER_FILE"
DIFF_FOUND=1
fi
done
done
Expand Down
4 changes: 2 additions & 2 deletions tests/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,10 @@ fn test_generics_with_default_params() {
struct DeNamedTuple<A = i32, B = String, C = ()>(A, B, C);

let expected = indoc! {r#"
export type SerNamedTuple<A, B, C> = [A, B, C];"#
export type DeNamedTuple<A, B, C> = [A, B, C];"#
};

assert_eq!(SerNamedTuple::<(), (), ()>::DECL, expected);
assert_eq!(DeNamedTuple::<(), (), ()>::DECL, expected);

#[derive(Serialize, Tsify)]
#[tsify(into_wasm_abi)]
Expand Down
2 changes: 1 addition & 1 deletion tsify-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tsify-macros"
version = "0.5.6"
version = "0.5.7"
edition = "2021"
authors = [
"Madono Haru <madonoharu@gmail.com>",
Expand Down
Loading