wasm_bindgen/convert/traits.rs
1use core::borrow::Borrow;
2use core::ops::{Deref, DerefMut};
3use core::panic::AssertUnwindSafe;
4
5use crate::sys::{JsNullable, JsOption};
6use crate::{describe::*, JsCast};
7use crate::{ErasableGeneric, JsValue};
8
9/// A trait for anything that can be converted into a type that can cross the
10/// Wasm ABI directly, eg `u32` or `f64`.
11///
12/// This is the opposite of `FromWasmAbi` and `Ref[Mut]FromWasmAbi`.
13///
14/// # ⚠️ Unstable
15///
16/// This is part of the internal [`convert`](crate::convert) module, **no
17/// stability guarantees** are provided. Use at your own risk. See its
18/// documentation for more details.
19pub trait IntoWasmAbi: WasmDescribe {
20 /// The Wasm ABI type that this converts into when crossing the ABI
21 /// boundary.
22 type Abi: WasmAbi;
23
24 /// Convert `self` into `Self::Abi` so that it can be sent across the wasm
25 /// ABI boundary.
26 fn into_abi(self) -> Self::Abi;
27}
28
29/// A type whose shared references can cross the Wasm ABI, i.e.
30/// `for<'a> &'a Self: IntoWasmAbi`.
31///
32/// Rust does not imply a trait's `where` clauses on `Self` the way it implies
33/// supertraits, so an alias trait for that higher-ranked bound would not let
34/// generic code use `&T: IntoWasmAbi`. This trait carries the conversion
35/// itself instead, and `experimental_generic_mono` imports marshal a `&T`
36/// argument through it, so `T: RefIntoWasmAbi` is the bound they declare. It
37/// is sealed, holding exactly where the higher-ranked bound does.
38///
39/// # ⚠️ Unstable
40///
41/// This is part of the internal [`convert`](crate::convert) module, **no
42/// stability guarantees** are provided. Use at your own risk. See its
43/// documentation for more details.
44pub trait RefIntoWasmAbi: ref_into_wasm_abi::Sealed {
45 /// The Wasm ABI type that `&Self` converts into.
46 type Abi: WasmAbi;
47
48 /// Describe `&Self`.
49 fn describe_ref();
50
51 /// Convert `&self` into `Self::Abi`.
52 fn ref_into_abi(&self) -> Self::Abi;
53}
54
55mod ref_into_wasm_abi {
56 use super::IntoWasmAbi;
57
58 pub trait Sealed {}
59
60 impl<T: ?Sized> Sealed for T where for<'a> &'a T: IntoWasmAbi {}
61}
62
63impl<T: ?Sized, A: WasmAbi> RefIntoWasmAbi for T
64where
65 for<'a> &'a T: IntoWasmAbi<Abi = A>,
66{
67 type Abi = A;
68
69 #[inline]
70 fn describe_ref() {
71 <&T as WasmDescribe>::describe()
72 }
73
74 #[inline]
75 fn ref_into_abi(&self) -> A {
76 IntoWasmAbi::into_abi(self)
77 }
78}
79
80/// A trait for anything that can be recovered by-value from the Wasm ABI
81/// boundary, eg a Rust `u8` can be recovered from the Wasm ABI `u32` type.
82///
83/// This is the by-value variant of the opposite operation as `IntoWasmAbi`.
84///
85/// # ⚠️ Unstable
86///
87/// This is part of the internal [`convert`](crate::convert) module, **no
88/// stability guarantees** are provided. Use at your own risk. See its
89/// documentation for more details.
90pub trait FromWasmAbi: WasmDescribe {
91 /// The Wasm ABI type that this converts from when coming back out from the
92 /// ABI boundary.
93 type Abi: WasmAbi;
94
95 /// Recover a `Self` from `Self::Abi`.
96 ///
97 /// # Safety
98 ///
99 /// This is only safe to call when -- and implementations may assume that --
100 /// the supplied `Self::Abi` was previously generated by a call to `<Self as
101 /// IntoWasmAbi>::into_abi()` or the moral equivalent in JS.
102 unsafe fn from_abi(js: Self::Abi) -> Self;
103
104 /// Recover a `Self` from `Self::Abi`, or the message to throw when JS
105 /// passed a value that `Self` rejects.
106 ///
107 /// A throw runs no destructors, so the generated wrappers convert every
108 /// argument with this and throw only once all of them are released.
109 /// Implementations must release anything `js` owns before returning an
110 /// error.
111 ///
112 /// # Safety
113 ///
114 /// Same as `from_abi`.
115 #[doc(hidden)]
116 #[inline]
117 unsafe fn try_from_abi(js: Self::Abi) -> Result<Self, &'static str>
118 where
119 Self: Sized,
120 {
121 Ok(Self::from_abi(js))
122 }
123}
124
125/// A trait for anything that can be recovered as some sort of shared reference
126/// from the Wasm ABI boundary.
127///
128/// This is the shared reference variant of the opposite operation as
129/// `IntoWasmAbi`.
130///
131/// # ⚠️ Unstable
132///
133/// This is part of the internal [`convert`](crate::convert) module, **no
134/// stability guarantees** are provided. Use at your own risk. See its
135/// documentation for more details.
136pub trait RefFromWasmAbi: WasmDescribe {
137 /// The Wasm ABI type references to `Self` are recovered from.
138 type Abi: WasmAbi;
139
140 /// The type that holds the reference to `Self` for the duration of the
141 /// invocation of the function that has an `&Self` parameter. This is
142 /// required to ensure that the lifetimes don't persist beyond one function
143 /// call, and so that they remain anonymous.
144 type Anchor: Deref<Target = Self>;
145
146 /// Recover a `Self::Anchor` from `Self::Abi`.
147 ///
148 /// # Safety
149 ///
150 /// Same as `FromWasmAbi::from_abi`.
151 unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor;
152
153 /// The fallible form of `ref_from_abi`, see `FromWasmAbi::try_from_abi`.
154 ///
155 /// # Safety
156 ///
157 /// Same as `FromWasmAbi::from_abi`.
158 #[doc(hidden)]
159 #[inline]
160 unsafe fn try_ref_from_abi(js: Self::Abi) -> Result<Self::Anchor, &'static str> {
161 Ok(Self::ref_from_abi(js))
162 }
163}
164
165/// A version of the `RefFromWasmAbi` trait with the additional requirement
166/// that the reference must remain valid as long as the anchor isn't dropped.
167///
168/// This isn't the case for `JsValue`'s `RefFromWasmAbi` implementation. To
169/// avoid having to allocate a spot for the `JsValue` on the `JsValue` heap,
170/// the `JsValue` is instead pushed onto the `JsValue` stack, and popped off
171/// again after the function that the reference was passed to returns. So,
172/// `JsValue` has a different `LongRefFromWasmAbi` implementation that behaves
173/// the same as `FromWasmAbi`, putting the value on the heap.
174///
175/// This is needed for async functions, where the reference needs to be valid
176/// for the whole length of the `Future`, rather than the initial synchronous
177/// call.
178///
179/// 'long ref' is short for 'long-lived reference'.
180///
181/// # ⚠️ Unstable
182///
183/// This is part of the internal [`convert`](crate::convert) module, **no
184/// stability guarantees** are provided. Use at your own risk. See its
185/// documentation for more details.
186pub trait LongRefFromWasmAbi: WasmDescribe {
187 /// Same as `RefFromWasmAbi::Abi`
188 type Abi: WasmAbi;
189
190 /// Same as `RefFromWasmAbi::Anchor`
191 type Anchor: Borrow<Self>;
192
193 /// Same as `RefFromWasmAbi::ref_from_abi`
194 unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor;
195
196 /// The fallible form of `long_ref_from_abi`, see
197 /// `FromWasmAbi::try_from_abi`.
198 ///
199 /// # Safety
200 ///
201 /// Same as `FromWasmAbi::from_abi`.
202 #[doc(hidden)]
203 #[inline]
204 unsafe fn try_long_ref_from_abi(js: Self::Abi) -> Result<Self::Anchor, &'static str> {
205 Ok(Self::long_ref_from_abi(js))
206 }
207}
208
209/// Dual of the `RefFromWasmAbi` trait, except for mutable references.
210///
211/// # ⚠️ Unstable
212///
213/// This is part of the internal [`convert`](crate::convert) module, **no
214/// stability guarantees** are provided. Use at your own risk. See its
215/// documentation for more details.
216pub trait RefMutFromWasmAbi: WasmDescribe {
217 /// Same as `RefFromWasmAbi::Abi`
218 type Abi: WasmAbi;
219 /// Same as `RefFromWasmAbi::Anchor`
220 type Anchor: DerefMut<Target = Self>;
221 /// Same as `RefFromWasmAbi::ref_from_abi`
222 unsafe fn ref_mut_from_abi(js: Self::Abi) -> Self::Anchor;
223
224 /// The fallible form of `ref_mut_from_abi`, see
225 /// `FromWasmAbi::try_from_abi`.
226 ///
227 /// # Safety
228 ///
229 /// Same as `FromWasmAbi::from_abi`.
230 #[doc(hidden)]
231 #[inline]
232 unsafe fn try_ref_mut_from_abi(js: Self::Abi) -> Result<Self::Anchor, &'static str> {
233 Ok(Self::ref_mut_from_abi(js))
234 }
235}
236
237/// Indicates that this type can be passed to JS as `Option<Self>` over its own
238/// ABI, which has a spare value for `None`.
239///
240/// Implementing it provides [`MaybeIntoWasmAbi`], which `Option<T>` converts
241/// through; a type whose ABI has no spare value implements that trait
242/// directly instead.
243///
244/// # ⚠️ Unstable
245///
246/// This is part of the internal [`convert`](crate::convert) module, **no
247/// stability guarantees** are provided. Use at your own risk. See its
248/// documentation for more details.
249pub trait OptionIntoWasmAbi: IntoWasmAbi {
250 /// Returns an ABI instance indicating "none", which JS will interpret as
251 /// the `None` branch of this option.
252 ///
253 /// It should be guaranteed that the `IntoWasmAbi` can never produce the ABI
254 /// value returned here.
255 fn none() -> Self::Abi;
256}
257
258/// Indicates that this type can be received from JS as `Option<Self>` over
259/// its own ABI. See [`OptionIntoWasmAbi`].
260///
261/// # ⚠️ Unstable
262///
263/// This is part of the internal [`convert`](crate::convert) module, **no
264/// stability guarantees** are provided. Use at your own risk. See its
265/// documentation for more details.
266pub trait OptionFromWasmAbi: FromWasmAbi {
267 /// Tests whether the argument is a "none" instance. If so it will be
268 /// deserialized as `None`, and otherwise it will be passed to
269 /// `FromWasmAbi`.
270 fn is_none(abi: &Self::Abi) -> bool;
271}
272
273/// The ABI of `Option<Self>`.
274///
275/// `Option<T>` takes its conversion from this trait, so every `T` implementing
276/// it can be wrapped, including under a generic bound such as
277/// `Option<impl JsNumberOrStringLike>`. A type whose own ABI has a spare value
278/// for `None` implements [`OptionIntoWasmAbi`] instead and gets this trait
279/// from the blanket impl; a type without one, such as `i32` or `f64`, picks a
280/// wider `MaybeAbi` here.
281///
282/// # ⚠️ Unstable
283///
284/// This is part of the internal [`convert`](crate::convert) module, **no
285/// stability guarantees** are provided. Use at your own risk. See its
286/// documentation for more details.
287pub trait MaybeIntoWasmAbi: IntoWasmAbi {
288 /// The ABI of `Option<Self>`.
289 type MaybeAbi: WasmAbi;
290
291 /// Converts a value into the `Option<Self>` ABI.
292 fn into_maybe_abi(self) -> Self::MaybeAbi;
293
294 /// Returns the ABI value for `None`, which JS reads as `undefined`.
295 ///
296 /// It should be guaranteed that
297 /// [`into_maybe_abi`](Self::into_maybe_abi) can never produce this value.
298 fn none() -> Self::MaybeAbi;
299}
300
301/// The ABI of `Option<Self>` received from JS. See [`MaybeIntoWasmAbi`].
302///
303/// # ⚠️ Unstable
304///
305/// This is part of the internal [`convert`](crate::convert) module, **no
306/// stability guarantees** are provided. Use at your own risk. See its
307/// documentation for more details.
308pub trait MaybeFromWasmAbi: FromWasmAbi {
309 /// The ABI of `Option<Self>`.
310 type MaybeAbi: WasmAbi;
311
312 /// Recovers a value from the `Option<Self>` ABI, once
313 /// [`is_none`](Self::is_none) has ruled `None` out.
314 ///
315 /// # Safety
316 ///
317 /// As for [`FromWasmAbi::from_abi`].
318 unsafe fn from_maybe_abi(abi: Self::MaybeAbi) -> Self;
319
320 #[doc(hidden)]
321 #[inline]
322 unsafe fn try_from_maybe_abi(abi: Self::MaybeAbi) -> Result<Self, &'static str>
323 where
324 Self: Sized,
325 {
326 Ok(Self::from_maybe_abi(abi))
327 }
328
329 /// Tests the ABI value for `None`.
330 fn is_none(abi: &Self::MaybeAbi) -> bool;
331}
332
333/// The `Null` value of `Nullable<Self>`, which shares the ABI of
334/// `Option<Self>` with a second spare value beside
335/// [`none`](MaybeIntoWasmAbi::none).
336///
337/// `Nullable<T>` and `Option<Nullable<T>>` take their conversions from this
338/// trait, so every `T` implementing it can be wrapped, including under a
339/// generic bound such as `Nullable<impl JsStringLike>`.
340///
341/// # ⚠️ Unstable
342///
343/// This is part of the internal [`convert`](crate::convert) module, **no
344/// stability guarantees** are provided. Use at your own risk. See its
345/// documentation for more details.
346pub trait NullableIntoWasmAbi: MaybeIntoWasmAbi {
347 /// Returns the ABI value for `Nullable::Null`, which JS reads as `null`.
348 ///
349 /// It should be guaranteed that neither
350 /// [`into_maybe_abi`](MaybeIntoWasmAbi::into_maybe_abi) nor
351 /// [`none`](MaybeIntoWasmAbi::none) can produce this value.
352 fn null() -> Self::MaybeAbi;
353}
354
355/// The `Null` test of `Nullable<Self>` received from JS. See
356/// [`NullableIntoWasmAbi`].
357///
358/// # ⚠️ Unstable
359///
360/// This is part of the internal [`convert`](crate::convert) module, **no
361/// stability guarantees** are provided. Use at your own risk. See its
362/// documentation for more details.
363pub trait NullableFromWasmAbi: MaybeFromWasmAbi {
364 /// Tests the ABI value for `Nullable::Null`.
365 fn is_null(abi: &Self::MaybeAbi) -> bool;
366}
367
368/// A trait for any type which maps to a Wasm primitive type when used in FFI
369/// (`i32`, `i64`, `f32`, or `f64`).
370///
371/// This is with the exception of `()` (and other zero-sized types), which are
372/// also allowed because they're ignored: no arguments actually get added.
373///
374/// # Safety
375///
376/// This is an unsafe trait to implement as there's no guarantee the type
377/// actually maps to a primitive type.
378///
379/// # ⚠️ Unstable
380///
381/// This is part of the internal [`convert`](crate::convert) module, **no
382/// stability guarantees** are provided. Use at your own risk. See its
383/// documentation for more details.
384pub unsafe trait WasmPrimitive: Default {}
385
386unsafe impl WasmPrimitive for u32 {}
387unsafe impl WasmPrimitive for i32 {}
388unsafe impl WasmPrimitive for u64 {}
389unsafe impl WasmPrimitive for i64 {}
390unsafe impl WasmPrimitive for f32 {}
391unsafe impl WasmPrimitive for f64 {}
392unsafe impl WasmPrimitive for () {}
393
394/// A trait which represents types that can be passed across the Wasm ABI
395/// boundary, by being split into multiple Wasm primitive types.
396///
397/// Up to 4 primitives are supported; if you don't want to use all of them, you
398/// can set the rest to `()`, which will cause them to be ignored.
399///
400/// You need to be careful how many primitives you use, however:
401/// `Result<T, JsValue>` uses up 2 primitives to store the error, and so it
402/// doesn't work if `T` uses more than 2 primitives.
403///
404/// So, if you're adding support for a type that needs 3 or more primitives and
405/// is able to be returned, you have to add another primitive here.
406///
407/// There's already one type that uses 3 primitives: `&mut [T]`. However, it
408/// can't be returned anyway, so it doesn't matter that
409/// `Result<&mut [T], JsValue>` wouldn't work.
410///
411/// # ⚠️ Unstable
412///
413/// This is part of the internal [`convert`](crate::convert) module, **no
414/// stability guarantees** are provided. Use at your own risk. See its
415/// documentation for more details.
416pub trait WasmAbi {
417 type Prim1: WasmPrimitive;
418 type Prim2: WasmPrimitive;
419 type Prim3: WasmPrimitive;
420 type Prim4: WasmPrimitive;
421
422 /// Splits this type up into primitives to be sent over the ABI.
423 fn split(self) -> (Self::Prim1, Self::Prim2, Self::Prim3, Self::Prim4);
424 /// Reconstructs this type from primitives received over the ABI.
425 fn join(prim1: Self::Prim1, prim2: Self::Prim2, prim3: Self::Prim3, prim4: Self::Prim4)
426 -> Self;
427}
428
429/// A trait representing how to interpret the return value of a function for
430/// the Wasm ABI.
431///
432/// This is very similar to the `IntoWasmAbi` trait and in fact has a blanket
433/// implementation for all implementors of the `IntoWasmAbi`. The primary use
434/// case of this trait is to enable functions to return `Result`, interpreting
435/// an error as "rethrow this to JS"
436///
437/// # ⚠️ Unstable
438///
439/// This is part of the internal [`convert`](crate::convert) module, **no
440/// stability guarantees** are provided. Use at your own risk. See its
441/// documentation for more details.
442pub trait ReturnWasmAbi: WasmDescribe {
443 /// Same as `IntoWasmAbi::Abi`
444 type Abi: WasmAbi;
445
446 /// Same as `IntoWasmAbi::into_abi`, except that it may throw and never
447 /// return in the case of `Err`.
448 fn return_abi(self) -> Self::Abi;
449}
450
451impl<T: IntoWasmAbi> ReturnWasmAbi for T {
452 type Abi = T::Abi;
453
454 #[inline]
455 fn return_abi(self) -> Self::Abi {
456 self.into_abi()
457 }
458}
459
460use alloc::boxed::Box;
461use core::marker::Sized;
462
463/// Trait for element types to implement IntoWasmAbi for vectors of
464/// themselves.
465///
466/// # ⚠️ Unstable
467///
468/// This is part of the internal [`convert`](crate::convert) module, **no
469/// stability guarantees** are provided. Use at your own risk. See its
470/// documentation for more details.
471pub trait VectorIntoWasmAbi: WasmDescribeVector + Sized {
472 type Abi: WasmAbi;
473
474 fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi;
475}
476
477/// Trait for element types to implement FromWasmAbi for vectors of
478/// themselves.
479///
480/// # ⚠️ Unstable
481///
482/// This is part of the internal [`convert`](crate::convert) module, **no
483/// stability guarantees** are provided. Use at your own risk. See its
484/// documentation for more details.
485pub trait VectorFromWasmAbi: WasmDescribeVector + Sized {
486 type Abi: WasmAbi;
487
488 unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]>;
489
490 /// The fallible form of `vector_from_abi`, see
491 /// `FromWasmAbi::try_from_abi`.
492 #[doc(hidden)]
493 #[inline]
494 unsafe fn try_vector_from_abi(js: Self::Abi) -> Result<Box<[Self]>, &'static str> {
495 Ok(Self::vector_from_abi(js))
496 }
497}
498
499/// A repr(C) struct containing all of the primitives of a `WasmAbi` type, in
500/// order.
501///
502/// This is used as the return type of imported/exported functions. `WasmAbi`
503/// types aren't guaranteed to be FFI-safe, so we can't return them directly:
504/// instead we return this.
505///
506/// If all but one of the primitives is `()`, this corresponds to returning the
507/// remaining primitive directly, otherwise a return pointer is used.
508///
509/// # ⚠️ Unstable
510///
511/// This is part of the internal [`convert`](crate::convert) module, **no
512/// stability guarantees** are provided. Use at your own risk. See its
513/// documentation for more details.
514#[repr(C)]
515pub struct WasmRet<T: WasmAbi> {
516 prim1: T::Prim1,
517 prim2: T::Prim2,
518 prim3: T::Prim3,
519 prim4: T::Prim4,
520}
521
522impl<T: WasmAbi> From<T> for WasmRet<T> {
523 fn from(value: T) -> Self {
524 let (prim1, prim2, prim3, prim4) = value.split();
525 Self {
526 prim1,
527 prim2,
528 prim3,
529 prim4,
530 }
531 }
532}
533
534// Ideally this'd just be an `Into<T>` implementation, but unfortunately that
535// doesn't work because of the orphan rule.
536impl<T: WasmAbi> WasmRet<T> {
537 /// Joins the components of this `WasmRet` back into the type they represent.
538 pub fn join(self) -> T {
539 T::join(self.prim1, self.prim2, self.prim3, self.prim4)
540 }
541}
542
543/// [`TryFromJsValue`] is a trait for converting a JavaScript value ([`JsValue`])
544/// into a Rust type. It is used by the [`wasm_bindgen`](wasm_bindgen_macro::wasm_bindgen)
545/// proc-macro to allow conversion to user types.
546///
547/// The semantics of this trait for various types are designed to provide a runtime
548/// analog of the static semantics implemented by the IntoWasmAbi function bindgen,
549/// with the exception that conversions are constrained to not cast invalid types.
550///
551/// For example, where the Wasm static semantics will permit `foo(x: i32)` when passed
552/// from JS `foo("5")` to treat that as `foo(5)`, this trait will instead throw. Apart
553/// from these reduced type conversion cases, behaviours should otherwise match the
554/// static semantics.
555///
556/// Types implementing this trait must specify their conversion logic from
557/// [`JsValue`] to the Rust type, handling any potential errors that may occur
558/// during the conversion process.
559///
560/// # ⚠️ Unstable
561///
562/// This is part of the internal [`convert`](crate::convert) module, **no
563/// stability guarantees** are provided. Use at your own risk. See its
564/// documentation for more details.
565pub trait TryFromJsValue: Sized {
566 /// Whether `Self` accepts `null` as a distinct value space, as
567 /// `Nullable<T>` does. An enclosing `Option` then passes `null` through
568 /// instead of reading it as `None`, so `Option<T>` is itself nullable
569 /// exactly when `T` is not. `JsValue` does not set this: it accepts
570 /// `null` as one value among all of them, not as a distinct space, and
571 /// `Option<JsValue>` reads it as `None` like the ABI does. This is the
572 /// JS-value side of [`NullableFromWasmAbi`], which claims `null` at the
573 /// ABI.
574 const NULLABLE: bool = false;
575
576 /// Performs the conversion.
577 fn try_from_js_value(value: JsValue) -> Result<Self, JsValue> {
578 Self::try_from_js_value_ref(&value).ok_or(value)
579 }
580
581 /// Performs the conversion.
582 fn try_from_js_value_ref(value: &JsValue) -> Option<Self>;
583}
584
585impl<T: FromWasmAbi> FromWasmAbi for AssertUnwindSafe<T> {
586 type Abi = T::Abi;
587
588 unsafe fn from_abi(js: Self::Abi) -> Self {
589 AssertUnwindSafe(T::from_abi(js))
590 }
591
592 #[inline]
593 unsafe fn try_from_abi(js: Self::Abi) -> Result<Self, &'static str> {
594 T::try_from_abi(js).map(AssertUnwindSafe)
595 }
596}
597
598/// A trait for defining upcast relationships from a source type.
599///
600/// This is the inverse of [`Upcast<T>`] - instead of implementing
601/// `impl Upcast<Target> for Source`, you implement `impl UpcastFrom<Source> for Target`.
602///
603/// # Why UpcastFrom?
604///
605/// This resolves Rust's orphan rule issues: you can implement `UpcastFrom<MyType>`
606/// for external types when `MyType` is local to your crate, whereas implementing
607/// `Upcast<ExternalType>` would be prohibited by orphan rules.
608///
609/// # ⚠️ Unstable
610///
611/// This is part of the internal [`convert`](crate::convert) module, **no
612/// stability guarantees** are provided. Use at your own risk. See its
613/// documentation for more details.
614///
615/// # Relationship to Upcast
616///
617/// `UpcastFrom<S>` provides a blanket implementation of `Upcast<T>`:
618/// ```ignore
619/// impl<S, T> Upcast<T> for S where T: UpcastFrom<S> {}
620/// ```
621///
622/// This means implementing `UpcastFrom<Source> for Target` automatically gives you
623/// `Upcast<Target> for Source`, enabling `source.upcast()` to produce `Target`.
624pub trait UpcastFrom<S: ?Sized> {}
625
626/// A trait for type-safe generic upcasting.
627///
628/// # ⚠️ Unstable
629///
630/// This is part of the internal [`convert`](crate::convert) module, **no
631/// stability guarantees** are provided. Use at your own risk. See its
632/// documentation for more details.
633///
634/// # Note
635///
636/// `Upcast<T>` has a blanket implementation for all types where `T: UpcastFrom<Self>`.
637/// New upcast relationships should typically be defined by implementing `FromUpcast`
638/// rather than `Upcast` directly, to avoid orphan rule issues.
639pub trait Upcast<T: ?Sized> {
640 /// Perform a zero-cost type-safe upcast to a wider ref type within the Wasm
641 /// bindgen generics type system.
642 ///
643 /// This enables proper nested conversions that obey subtyping rules,
644 /// supporting strict API type checking.
645 ///
646 /// The common pattern when passing a narrow type is to call `upcast()`
647 /// or `upcast_into()` to obtain the correct type for the function usage,
648 /// while ensuring safe type checked usage.
649 ///
650 /// For example, if passing `Promise<Number>` as an argument to a function
651 /// where `Promise<JsValue>` is expected, or `Function<JsValue>` as an
652 /// argument where `Function<Number>` is expected.
653 ///
654 /// This is a compile time conversion only by the nature of the erasable
655 /// generics type system.
656 #[inline]
657 fn upcast(&self) -> &T
658 where
659 Self: ErasableGeneric,
660 T: Sized + ErasableGeneric<Repr = <Self as ErasableGeneric>::Repr>,
661 {
662 unsafe { &*(self as *const Self as *const T) }
663 }
664
665 /// Perform a zero-cost type-safe upcast to a wider type within the Wasm
666 /// bindgen generics type system.
667 ///
668 /// This enables proper nested conversions that obey subtyping rules,
669 /// supporting strict API type checking.
670 ///
671 /// The common pattern when passing a narrow type is to call `upcast()`
672 /// or `upcast_into()` to obtain the correct type for the function usage,
673 /// while ensuring safe type checked usage.
674 ///
675 /// For example, if passing `Promise<Number>` as an argument to a function
676 /// where `Promise<JsValue>` is expected, or `FunctionArgs<JsValue>` as an
677 /// argument where `FunctionArgs<Number>` is expected.
678 ///
679 /// This is a compile time conversion only by the nature of the erasable
680 /// generics type system.
681 #[inline]
682 fn upcast_into(self) -> T
683 where
684 Self: Sized + ErasableGeneric,
685 T: Sized + ErasableGeneric<Repr = <Self as ErasableGeneric>::Repr>,
686 {
687 unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(self)) }
688 }
689}
690
691// Blanket impl: UpcastFrom<S> for T implies Upcast<T> for S
692impl<S, T> Upcast<T> for S
693where
694 T: UpcastFrom<S> + ?Sized,
695 S: ?Sized,
696{
697}
698
699// Reference impls using UpcastFrom.
700//
701// &mut T references are invariant. If you accept &mut T, you cannot upcast it
702// and write back a different type the caller could see.
703// Eg. this is not valid:
704// ```ignore
705// let mut string = JsString::from("valid");
706// let string_ref: &mut JsString = &mut string;
707// // If &mut T was modeled as just covariant, we could upcast this to
708// // &mut JsValue.
709// let js_value_ref: &mut JsValue = string_ref.upcast_into();
710// *js_value_ref = Object::new().into();
711// // string is still typed as JsString, but it now wraps a plain object.
712// // Converting it to a Rust String throws because the value is not a string.
713// let _ = String::from(&string);
714// ```
715//
716// Requiring `UpcastFrom` in *both* directions means `T` and `Target` have to be
717// mutually upcastable -- i.e. equivalent, with the same set of valid values.
718// That is exactly what makes a `&mut` cast sound: anything written back through
719// the wider `&mut Target` view is still a valid `T`. So this rejects every
720// widening (the `JsString` -> `JsValue` case above, where `JsValue` does not
721// upcast back to `JsString`), while still allowing casts between genuinely
722// equivalent types in either direction. For example `()` and `Undefined` both
723// model "nothing" and upcast to each other, so a
724// `&mut Closure<dyn Fn(Undefined)>` can be upcast to a `&mut Closure<dyn Fn(())>`
725// and back.
726impl<'a, T: ?Sized, Target: ?Sized> UpcastFrom<&'a mut T> for &'a mut Target
727where
728 Target: UpcastFrom<T>,
729 T: UpcastFrom<Target>,
730{
731}
732// &T references are covariant, so we can allow from a specific type to a more general type
733impl<'a, T, Target> UpcastFrom<&'a T> for &'a Target where Target: UpcastFrom<T> {}
734
735// Tuple upcasts with structural covariance
736macro_rules! impl_tuple_upcast {
737 ([$($T:ident)+] [$($Target:ident)+]) => {
738 // Structural covariance: (T...) -> (Target...)
739 impl<$($T,)+ $($Target,)+> UpcastFrom<($($T,)+)> for ($($Target,)+)
740 where
741 $($Target: JsGeneric + UpcastFrom<$T>,)+
742 $($T: JsGeneric,)+
743 {
744 }
745 impl<$($T: JsGeneric,)+ $($Target: JsGeneric,)+> UpcastFrom<($($T,)+)> for JsOption<($($Target,)+)>
746 where
747 $($Target: JsGeneric + UpcastFrom<$T>,)+
748 $($T: JsGeneric,)+
749 {
750 }
751 impl<$($T: JsGeneric,)+ $($Target: JsGeneric,)+> UpcastFrom<($($T,)+)> for JsNullable<($($Target,)+)>
752 where
753 $($Target: JsGeneric + UpcastFrom<$T>,)+
754 $($T: JsGeneric,)+
755 {
756 }
757 };
758}
759impl_tuple_upcast!([T1][Target1]);
760impl_tuple_upcast!([T1 T2] [Target1 Target2]);
761impl_tuple_upcast!([T1 T2 T3] [Target1 Target2 Target3]);
762impl_tuple_upcast!([T1 T2 T3 T4] [Target1 Target2 Target3 Target4]);
763impl_tuple_upcast!([T1 T2 T3 T4 T5] [Target1 Target2 Target3 Target4 Target5]);
764impl_tuple_upcast!([T1 T2 T3 T4 T5 T6] [Target1 Target2 Target3 Target4 Target5 Target6]);
765impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7] [Target1 Target2 Target3 Target4 Target5 Target6 Target7]);
766impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7 T8] [Target1 Target2 Target3 Target4 Target5 Target6 Target7 Target8]);
767
768/// A convenience trait for types that erase to [`JsValue`].
769///
770/// This is a shorthand for `ErasableGeneric<Repr = JsValue>`, used as a bound
771/// on generic parameters that must be representable as JavaScript values.
772///
773/// # When to Use
774///
775/// Use `JsGeneric` as a trait bound when you need a generic type that:
776/// - Can be passed to/from JavaScript
777/// - Is type-erased to `JsValue` at the FFI boundary
778///
779/// # Examples
780///
781/// ```ignore
782/// use wasm_bindgen::JsGeneric;
783///
784/// fn process_js_values<T: JsGeneric>(items: &[T]) {
785/// // T can be any JS-compatible type
786/// }
787/// ```
788///
789/// # Implementors
790///
791/// This trait is automatically implemented for all types that implement
792/// `ErasableGeneric<Repr = JsValue>`, including:
793/// - All `js_sys` types (`Object`, `Array`, `Function`, etc.)
794/// - `JsValue` itself
795/// - Custom types imported via `#[wasm_bindgen]`
796pub trait JsGeneric:
797 ErasableGeneric<Repr = JsValue>
798 + UpcastFrom<Self>
799 + Upcast<Self>
800 + Upcast<JsValue>
801 + JsCast
802 + 'static
803{
804}
805
806impl<T: ErasableGeneric<Repr = JsValue> + UpcastFrom<T> + Upcast<JsValue> + JsCast + 'static>
807 JsGeneric for T
808{
809}
810
811/// Value conversion from a type into its canonical [`JsGeneric`] form.
812///
813/// This trait allows types to be converted into JsGeneric supported types, which
814/// are required to be erasably generic with JsValue.
815///
816/// The single associated type — rather than a free type parameter bounded by
817/// `AsRef<T>` — is what makes collection-style APIs infer annotation-free.
818/// Given an input `A`, there is exactly one `A::JsCanon`, so rustc never has
819/// to search across multiple `AsRef` impls to pick a target element type.
820///
821/// # Implementations
822///
823/// Provided impls:
824/// - [`JsValue`] in this crate.
825/// - Every `#[wasm_bindgen]`-imported type (identity — emitted by the macro).
826/// - Every generic `js_sys` container (`Array<T>`, `Promise<T>`, `Set<T>`, …)
827/// provides its own identity impl owned by `js_sys`.
828/// - References to cloneable implementors, so borrowed iteration can still
829/// produce owned JS-generic values.
830///
831/// This trait is deliberately *not* blanket-implemented over all [`JsGeneric`]
832/// types: each implementor explicitly opts in, which leaves room for future
833/// wrapper types to pick a non-identity [`Self::JsCanon`].
834///
835/// # Example
836///
837/// ```ignore
838/// use js_sys::{Array, Number};
839///
840/// let arr: Array<Number> = (0..10).map(Number::from).collect();
841/// ```
842pub trait IntoJsGeneric {
843 /// The canonical [`JsGeneric`] form of this type.
844 type JsCanon: JsGeneric;
845
846 /// Produce the canonical [`JsGeneric`] value for `self`.
847 fn to_js(self) -> Self::JsCanon;
848}
849
850impl IntoJsGeneric for JsValue {
851 type JsCanon = JsValue;
852 #[inline]
853 fn to_js(self) -> JsValue {
854 self
855 }
856}
857
858// Reference iteration clones the borrowed wrapper to produce an owned value,
859// then delegates to that type's canonical conversion.
860impl<T: IntoJsGeneric + Clone> IntoJsGeneric for &T {
861 type JsCanon = T::JsCanon;
862 #[inline]
863 fn to_js(self) -> T::JsCanon {
864 self.clone().to_js()
865 }
866}
867
868// Intentionally not a blanket `impl<T: JsGeneric> IntoJsGeneric for T`:
869// that would lock in identity for every current and future `JsGeneric` type
870// and prevent wrapper types from canonicalising to a different target.
871// Instead, implementations are provided explicitly by each owning crate
872// (macro-generated for user types; hand-written for `js_sys` containers).
873
874/// Marker for types that cross the ABI as a JavaScript string.
875///
876/// Use as a bound on an `experimental_generic_mono` import's type parameter to
877/// accept any Rust or JS string shape, each at its native wire format:
878/// `String` and `&str` cross as UTF-8 buffers, `js_sys::JsString` and
879/// `&js_sys::JsString` as handles — all arriving in JS as a string value.
880///
881/// `&String`, `&Box<str>` and `&Cow<str>` are also accepted and cross like
882/// `&str`. `&&str` is not; dereference it first.
883///
884/// This trait is sealed: it is implemented only for the string shapes above,
885/// each of which is guaranteed to produce a JS string on the other side.
886///
887/// `OptionIntoWasmAbi`, `NullableIntoWasmAbi` and `VectorRefIntoWasmAbi` are
888/// supertraits so that optional and nullable string positions (`Option<T>`,
889/// `Nullable<T>`) and string slices (`&[T]`) work under the same bound. A slice arrives in JS as an `Array` of strings.
890///
891/// This trait is experimental, like `experimental_generic_mono` itself, and
892/// may change or be removed as that feature stabilizes.
893pub trait JsStringLike:
894 IntoWasmAbi
895 + OptionIntoWasmAbi
896 + NullableIntoWasmAbi
897 + crate::convert::VectorRefIntoWasmAbi
898 + crate::__rt::marker::JsStringLikeSealed
899{
900}
901
902macro_rules! impl_js_string_like {
903 ($($t:ty),* $(,)?) => ($(
904 impl crate::__rt::marker::JsStringLikeSealed for $t {}
905 impl JsStringLike for $t {}
906 )*)
907}
908
909impl_js_string_like!(
910 alloc::string::String,
911 &str,
912 &alloc::string::String,
913 &alloc::boxed::Box<str>,
914 &alloc::borrow::Cow<'_, str>,
915);