Skip to main content

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);