Skip to main content

wry_bindgen/
value.rs

1//! JsValue - An opaque reference to a JavaScript value
2//!
3//! This type represents a reference to a JavaScript value on the JS heap.
4//! API compatible with wasm-bindgen's JsValue.
5
6use alloc::{boxed::Box, string::String, vec::Vec};
7use core::fmt;
8use core::ptr::NonNull;
9
10/// Top of the temporary borrow stack and start of special JS value indices.
11/// Values `1..JSIDX_OFFSET` are borrowed references that are only valid while
12/// the current JS borrow frame is alive.
13pub(crate) const JSIDX_OFFSET: u64 = 128;
14
15/// Index for the `undefined` JS value.
16pub(crate) const JSIDX_UNDEFINED: u64 = JSIDX_OFFSET;
17
18/// Index for the `null` JS value.
19pub(crate) const JSIDX_NULL: u64 = JSIDX_OFFSET + 1;
20
21/// Index for the `true` JS value.
22pub(crate) const JSIDX_TRUE: u64 = JSIDX_OFFSET + 2;
23
24/// Index for the `false` JS value.
25pub(crate) const JSIDX_FALSE: u64 = JSIDX_OFFSET + 3;
26
27/// First usable owned heap ID. IDs in `JSIDX_OFFSET..JSIDX_RESERVED` are
28/// reserved for special JS constants.
29pub(crate) const JSIDX_RESERVED: u64 = JSIDX_OFFSET + 4;
30
31#[inline]
32fn is_special_value_id(id: u64) -> bool {
33    (JSIDX_OFFSET..JSIDX_RESERVED).contains(&id)
34}
35
36/// An opaque reference to a JavaScript heap object.
37///
38/// This type is the wry-bindgen equivalent of wasm-bindgen's `JsValue`.
39/// It represents any JavaScript value and is used as the base type for
40/// all imported JS types.
41///
42/// JsValue is intentionally opaque - you cannot inspect or create values
43/// directly. All values come from JavaScript via the IPC protocol.
44///
45/// Unlike wasm-bindgen which runs in a single-threaded Wasm environment,
46/// this implementation uses the IPC protocol to communicate with JS.
47pub struct JsValue {
48    // The handle is just a `u64`, so the type is `Send`/`Sync`. A JsValue id is
49    // only meaningful inside the thread-local runtime that created it; using one
50    // elsewhere is a runtime error.
51    #[doc(hidden)]
52    pub idx: u64,
53}
54
55impl JsValue {
56    /// The `null` JS value constant.
57    pub const NULL: JsValue = JsValue::_new(JSIDX_NULL);
58
59    /// The `undefined` JS value constant.
60    pub const UNDEFINED: JsValue = JsValue::_new(JSIDX_UNDEFINED);
61
62    /// The `true` JS value constant.
63    pub const TRUE: JsValue = JsValue::_new(JSIDX_TRUE);
64
65    /// The `false` JS value constant.
66    pub const FALSE: JsValue = JsValue::_new(JSIDX_FALSE);
67
68    /// Create a new JsValue from an index (const fn for static values).
69    #[inline]
70    const fn _new(idx: u64) -> JsValue {
71        JsValue { idx }
72    }
73
74    /// Create a new JsValue from a heap ID.
75    ///
76    /// This is called internally when decoding a value from JS.
77    #[inline]
78    pub(crate) fn from_id(id: u64) -> Self {
79        Self::_new(id)
80    }
81
82    /// Get the heap ID for this value.
83    ///
84    /// This is used internally for encoding values to send to JS.
85    #[inline]
86    pub fn id(&self) -> u64 {
87        self.idx
88    }
89
90    /// Serializes a Rust value into a `JsValue` by serializing to JSON and
91    /// invoking `JSON.parse` on the JS side.
92    ///
93    /// **This function is deprecated**, mirroring upstream wasm-bindgen. Use
94    /// [`serde-wasm-bindgen`](https://docs.rs/serde-wasm-bindgen) instead.
95    ///
96    /// Usage requires activating the `serde-serialize` feature.
97    ///
98    /// # Errors
99    ///
100    /// Returns any error encountered when serializing `T` into JSON.
101    #[cfg(feature = "serde-serialize")]
102    #[deprecated = "causes dependency cycles, use `serde-wasm-bindgen` instead"]
103    pub fn from_serde<T>(t: &T) -> serde_json::Result<JsValue>
104    where
105        T: serde::ser::Serialize + ?Sized,
106    {
107        let json = serde_json::to_string(t)?;
108        Ok(crate::__wry_call_js_function!(
109            "(s) => JSON.parse(s)",
110            fn(&str) -> JsValue,
111            (json.as_str())
112        ))
113    }
114
115    /// Invokes `JSON.stringify` on this value and parses the resulting JSON into
116    /// an arbitrary Rust value.
117    ///
118    /// **This function is deprecated**, mirroring upstream wasm-bindgen. Use
119    /// [`serde-wasm-bindgen`](https://docs.rs/serde-wasm-bindgen) instead.
120    ///
121    /// Usage requires activating the `serde-serialize` feature.
122    ///
123    /// # Errors
124    ///
125    /// Returns any error encountered when parsing the JSON into a `T`.
126    #[cfg(feature = "serde-serialize")]
127    #[deprecated = "causes dependency cycles, use `serde-wasm-bindgen` instead"]
128    pub fn into_serde<T>(&self) -> serde_json::Result<T>
129    where
130        T: for<'a> serde::de::Deserialize<'a>,
131    {
132        // `JSON.stringify(undefined) === undefined`; reinterpret that as JSON
133        // `null` so it round-trips, matching upstream's behavior.
134        let json: String = crate::__wry_call_js_function!(
135            "(v) => JSON.stringify(v) ?? \"null\"",
136            fn(JsValue) -> String,
137            (self.clone())
138        );
139        serde_json::from_str(&json)
140    }
141
142    /// Returns the value as f64 without type checking.
143    /// Used by serde-wasm-bindgen for numeric conversions.
144    #[inline]
145    pub fn unchecked_into_f64(&self) -> f64 {
146        self.as_f64().unwrap_or(f64::NAN)
147    }
148
149    /// Check if this value is an instance of a specific JS type.
150    #[inline]
151    pub fn has_type<T: crate::JsCast>(&self) -> bool {
152        T::is_type_of(self)
153    }
154
155    /// Get the internal ABI representation (heap index), consuming self.
156    /// This is used by the convert module for low-level interop.
157    /// Returns u32 for wasm-bindgen compatibility.
158    #[inline]
159    pub fn into_abi(self) -> u32 {
160        let id = self.idx;
161        core::mem::forget(self);
162        id as u32
163    }
164
165    /// Creates a new JS value representing `undefined`.
166    #[inline]
167    pub const fn undefined() -> JsValue {
168        JsValue::UNDEFINED
169    }
170
171    /// Creates a new JS value representing `null`.
172    #[inline]
173    pub const fn null() -> JsValue {
174        JsValue::NULL
175    }
176
177    /// Creates a new JS value which is a boolean.
178    #[inline]
179    pub const fn from_bool(b: bool) -> JsValue {
180        if b { JsValue::TRUE } else { JsValue::FALSE }
181    }
182
183    /// Creates a JS string from a Rust string.
184    #[allow(clippy::should_implement_trait)]
185    pub fn from_str(s: &str) -> JsValue {
186        s.into()
187    }
188
189    /// Creates a JS number from an f64.
190    pub fn from_f64(n: f64) -> JsValue {
191        n.into()
192    }
193
194    /// Creates a JS value which is a bigint from a string representing a number.
195    pub fn bigint_from_str(s: &str) -> JsValue {
196        crate::js_helpers::js_bigint_from_str(s)
197    }
198
199    /// Creates a new JS symbol with the optional description specified.
200    pub fn symbol(description: Option<&str>) -> JsValue {
201        crate::js_helpers::js_symbol_new(description)
202    }
203}
204
205impl Clone for JsValue {
206    #[inline]
207    fn clone(&self) -> JsValue {
208        // Special constants don't need cloning. Borrow-stack IDs are below
209        // JSIDX_OFFSET and must be promoted to owned heap refs when cloned.
210        if is_special_value_id(self.idx) {
211            return JsValue::_new(self.idx);
212        }
213
214        // Clone the value on the JS heap
215        crate::js_helpers::js_clone_heap_ref(self.idx)
216    }
217}
218
219impl Drop for JsValue {
220    #[inline]
221    fn drop(&mut self) {
222        // Borrowed refs and special constants don't own JS heap slots.
223        if self.idx < JSIDX_RESERVED {
224            return;
225        }
226
227        // Drop the value on the JS heap
228        crate::batch::queue_js_drop(self.idx);
229    }
230}
231
232impl<'a> PartialEq<&'a str> for JsValue {
233    fn eq(&self, other: &&'a str) -> bool {
234        match self.as_string() {
235            Some(s) => &s == other,
236            None => false,
237        }
238    }
239}
240
241impl PartialEq<JsValue> for &str {
242    fn eq(&self, other: &JsValue) -> bool {
243        match other.as_string() {
244            Some(s) => self == &s,
245            None => false,
246        }
247    }
248}
249
250impl PartialEq<str> for JsValue {
251    fn eq(&self, other: &str) -> bool {
252        match self.as_string() {
253            Some(s) => s == other,
254            None => false,
255        }
256    }
257}
258
259impl PartialEq<String> for JsValue {
260    fn eq(&self, other: &String) -> bool {
261        match self.as_string() {
262            Some(s) => &s == other,
263            None => false,
264        }
265    }
266}
267
268impl PartialEq<JsValue> for String {
269    fn eq(&self, other: &JsValue) -> bool {
270        match other.as_string() {
271            Some(s) => self == &s,
272            None => false,
273        }
274    }
275}
276
277impl<'a> PartialEq<&'a String> for JsValue {
278    fn eq(&self, other: &&'a String) -> bool {
279        match self.as_string() {
280            Some(s) => &s == *other,
281            None => false,
282        }
283    }
284}
285
286impl PartialEq<JsValue> for &String {
287    fn eq(&self, other: &JsValue) -> bool {
288        match other.as_string() {
289            Some(s) => *self == &s,
290            None => false,
291        }
292    }
293}
294
295impl PartialEq<bool> for JsValue {
296    fn eq(&self, other: &bool) -> bool {
297        match self.as_bool() {
298            Some(b) => b == *other,
299            None => false,
300        }
301    }
302}
303
304impl PartialEq<JsValue> for bool {
305    fn eq(&self, other: &JsValue) -> bool {
306        match other.as_bool() {
307            Some(b) => *self == b,
308            None => false,
309        }
310    }
311}
312
313impl PartialEq<f32> for JsValue {
314    fn eq(&self, other: &f32) -> bool {
315        match self.as_f64() {
316            Some(n) => n == (*other as f64),
317            None => false,
318        }
319    }
320}
321
322impl PartialEq<JsValue> for f32 {
323    fn eq(&self, other: &JsValue) -> bool {
324        match other.as_f64() {
325            Some(n) => (*self as f64) == n,
326            None => false,
327        }
328    }
329}
330
331impl PartialEq<f64> for JsValue {
332    fn eq(&self, other: &f64) -> bool {
333        match self.as_f64() {
334            Some(n) => n == *other,
335            None => false,
336        }
337    }
338}
339
340impl PartialEq<JsValue> for f64 {
341    fn eq(&self, other: &JsValue) -> bool {
342        match other.as_f64() {
343            Some(n) => *self == n,
344            None => false,
345        }
346    }
347}
348
349// Macro for integer PartialEq implementations
350macro_rules! impl_partial_eq_int {
351    ($($t:ty),*) => {
352        $(
353            impl PartialEq<$t> for JsValue {
354                fn eq(&self, other: &$t) -> bool {
355                    match self.as_f64() {
356                        Some(n) => n == (*other as f64),
357                        None => false,
358                    }
359                }
360            }
361
362            impl PartialEq<JsValue> for $t {
363                fn eq(&self, other: &JsValue) -> bool {
364                    match other.as_f64() {
365                        Some(n) => (*self as f64) == n,
366                        None => false,
367                    }
368                }
369            }
370        )*
371    };
372}
373
374impl_partial_eq_int!(
375    i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
376);
377
378impl fmt::Debug for JsValue {
379    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380        f.write_str(&self.as_debug_string())
381    }
382}
383
384impl PartialEq for JsValue {
385    fn eq(&self, other: &Self) -> bool {
386        self.idx == other.idx
387    }
388}
389
390impl Eq for JsValue {}
391
392impl core::hash::Hash for JsValue {
393    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
394        self.idx.hash(state);
395    }
396}
397
398impl Default for JsValue {
399    fn default() -> Self {
400        Self::UNDEFINED
401    }
402}
403
404// Additional methods needed by js-sys for BigInt operations
405impl JsValue {
406    /// Checked division.
407    pub fn checked_div(&self, rhs: &Self) -> Self {
408        crate::js_helpers::js_checked_div(self, rhs)
409    }
410
411    /// Power operation.
412    pub fn pow(&self, rhs: &Self) -> Self {
413        crate::js_helpers::js_pow(self, rhs)
414    }
415
416    /// Bitwise AND.
417    pub fn bit_and(&self, rhs: &JsValue) -> JsValue {
418        crate::js_helpers::js_bit_and(self, rhs)
419    }
420
421    /// Bitwise OR.
422    pub fn bit_or(&self, rhs: &JsValue) -> JsValue {
423        crate::js_helpers::js_bit_or(self, rhs)
424    }
425
426    /// Bitwise XOR.
427    pub fn bit_xor(&self, rhs: &JsValue) -> JsValue {
428        crate::js_helpers::js_bit_xor(self, rhs)
429    }
430
431    /// Bitwise NOT.
432    pub fn bit_not(&self) -> JsValue {
433        crate::js_helpers::js_bit_not(self)
434    }
435
436    /// Left shift.
437    pub fn shl(&self, rhs: &JsValue) -> JsValue {
438        crate::js_helpers::js_shl(self, rhs)
439    }
440
441    /// Signed right shift.
442    pub fn shr(&self, rhs: &JsValue) -> JsValue {
443        crate::js_helpers::js_shr(self, rhs)
444    }
445
446    /// Unsigned right shift.
447    pub fn unsigned_shr(&self, rhs: &Self) -> u32 {
448        crate::js_helpers::js_unsigned_shr(self, rhs)
449    }
450
451    /// Add.
452    pub fn add(&self, rhs: &JsValue) -> JsValue {
453        crate::js_helpers::js_add(self, rhs)
454    }
455
456    /// Subtract.
457    pub fn sub(&self, rhs: &JsValue) -> JsValue {
458        crate::js_helpers::js_sub(self, rhs)
459    }
460
461    /// Multiply.
462    pub fn mul(&self, rhs: &JsValue) -> JsValue {
463        crate::js_helpers::js_mul(self, rhs)
464    }
465
466    /// Divide.
467    pub fn div(&self, rhs: &JsValue) -> JsValue {
468        crate::js_helpers::js_div(self, rhs)
469    }
470
471    /// Remainder.
472    pub fn rem(&self, rhs: &JsValue) -> JsValue {
473        crate::js_helpers::js_rem(self, rhs)
474    }
475
476    /// Negate.
477    pub fn neg(&self) -> JsValue {
478        crate::js_helpers::js_neg(self)
479    }
480
481    /// Less than comparison.
482    pub fn lt(&self, other: &Self) -> bool {
483        crate::js_helpers::js_lt(self, other)
484    }
485
486    /// Less than or equal comparison.
487    pub fn le(&self, other: &Self) -> bool {
488        crate::js_helpers::js_le(self, other)
489    }
490
491    /// Greater than comparison.
492    pub fn gt(&self, other: &Self) -> bool {
493        crate::js_helpers::js_gt(self, other)
494    }
495
496    /// Greater than or equal comparison.
497    pub fn ge(&self, other: &Self) -> bool {
498        crate::js_helpers::js_ge(self, other)
499    }
500
501    /// Loose equality (==).
502    pub fn loose_eq(&self, other: &Self) -> bool {
503        crate::js_helpers::js_loose_eq(self, other)
504    }
505
506    /// Check if this value is a falsy value in JavaScript.
507    pub fn is_falsy(&self) -> bool {
508        crate::js_helpers::js_is_falsy(self)
509    }
510
511    /// Check if this value is a truthy value in JavaScript.
512    pub fn is_truthy(&self) -> bool {
513        crate::js_helpers::js_is_truthy(self)
514    }
515
516    /// Check if this value is an object.
517    pub fn is_object(&self) -> bool {
518        crate::js_helpers::js_is_object(self)
519    }
520
521    /// Check if this value is a function.
522    pub fn is_function(&self) -> bool {
523        crate::js_helpers::js_is_function(self)
524    }
525
526    /// Check if this value is a string.
527    pub fn is_string(&self) -> bool {
528        crate::js_helpers::js_is_string(self)
529    }
530
531    /// Check if this value is a symbol.
532    pub fn is_symbol(&self) -> bool {
533        crate::js_helpers::js_is_symbol(self)
534    }
535
536    /// Check if this value is a bigint.
537    pub fn is_bigint(&self) -> bool {
538        crate::js_helpers::js_is_bigint(self)
539    }
540
541    /// Check if this value is an Array.
542    pub fn is_array(&self) -> bool {
543        crate::js_helpers::js_is_array(self)
544    }
545
546    /// Check if this value is undefined.
547    pub fn is_undefined(&self) -> bool {
548        if self.idx == JSIDX_UNDEFINED {
549            return true;
550        }
551        crate::js_helpers::js_is_undefined(self)
552    }
553
554    /// Check if this value is null.
555    pub fn is_null(&self) -> bool {
556        if self.idx == JSIDX_NULL {
557            return true;
558        }
559        crate::js_helpers::js_is_null(self)
560    }
561
562    /// Check if this value is null or undefined.
563    pub fn is_null_or_undefined(&self) -> bool {
564        if self.idx == JSIDX_NULL || self.idx == JSIDX_UNDEFINED {
565            return true;
566        }
567        crate::js_helpers::js_is_null_or_undefined(self)
568    }
569
570    /// Get the typeof this value as a string.
571    pub fn js_typeof(&self) -> JsValue {
572        crate::js_helpers::js_typeof(self)
573    }
574
575    /// Check if this value has a property with the given name.
576    pub fn js_in(&self, obj: &JsValue) -> bool {
577        crate::js_helpers::js_in(self, obj)
578    }
579
580    /// Get the value as a bool.
581    pub fn as_bool(&self) -> Option<bool> {
582        match self.idx {
583            JSIDX_TRUE => Some(true),
584            JSIDX_FALSE => Some(false),
585            JSIDX_UNDEFINED | JSIDX_NULL => None,
586            _ => {
587                // For heap values, check via JS
588                if crate::js_helpers::js_is_true(self) {
589                    Some(true)
590                } else if crate::js_helpers::js_is_false(self) {
591                    Some(false)
592                } else {
593                    None
594                }
595            }
596        }
597    }
598
599    /// Get the value as an f64.
600    pub fn as_f64(&self) -> Option<f64> {
601        crate::js_helpers::js_as_f64(self)
602    }
603
604    /// Get the value as a string.
605    pub fn as_string(&self) -> Option<String> {
606        crate::js_helpers::js_as_string(self)
607    }
608
609    /// Get a debug string representation of the value.
610    pub fn as_debug_string(&self) -> String {
611        crate::js_helpers::js_debug_string(self)
612    }
613}
614
615// Operator trait implementations for JsValue references
616use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub};
617
618impl Neg for &JsValue {
619    type Output = JsValue;
620    fn neg(self) -> Self::Output {
621        JsValue::neg(self)
622    }
623}
624
625impl Not for &JsValue {
626    type Output = bool;
627
628    fn not(self) -> Self::Output {
629        JsValue::is_falsy(self)
630    }
631}
632
633impl BitAnd for &JsValue {
634    type Output = JsValue;
635    fn bitand(self, rhs: Self) -> Self::Output {
636        JsValue::bit_and(self, rhs)
637    }
638}
639
640impl BitOr for &JsValue {
641    type Output = JsValue;
642    fn bitor(self, rhs: Self) -> Self::Output {
643        JsValue::bit_or(self, rhs)
644    }
645}
646
647impl BitXor for &JsValue {
648    type Output = JsValue;
649    fn bitxor(self, rhs: Self) -> Self::Output {
650        JsValue::bit_xor(self, rhs)
651    }
652}
653
654impl Shl for &JsValue {
655    type Output = JsValue;
656    fn shl(self, rhs: Self) -> Self::Output {
657        JsValue::shl(self, rhs)
658    }
659}
660
661impl Shr for &JsValue {
662    type Output = JsValue;
663    fn shr(self, rhs: Self) -> Self::Output {
664        JsValue::shr(self, rhs)
665    }
666}
667
668impl Add for &JsValue {
669    type Output = JsValue;
670    fn add(self, rhs: Self) -> Self::Output {
671        JsValue::add(self, rhs)
672    }
673}
674
675impl Sub for &JsValue {
676    type Output = JsValue;
677    fn sub(self, rhs: Self) -> Self::Output {
678        JsValue::sub(self, rhs)
679    }
680}
681
682impl Mul for &JsValue {
683    type Output = JsValue;
684    fn mul(self, rhs: Self) -> Self::Output {
685        JsValue::mul(self, rhs)
686    }
687}
688
689impl Div for &JsValue {
690    type Output = JsValue;
691    fn div(self, rhs: Self) -> Self::Output {
692        JsValue::div(self, rhs)
693    }
694}
695
696impl Rem for &JsValue {
697    type Output = JsValue;
698    fn rem(self, rhs: Self) -> Self::Output {
699        JsValue::rem(self, rhs)
700    }
701}
702
703impl Neg for JsValue {
704    type Output = JsValue;
705    fn neg(self) -> JsValue {
706        JsValue::neg(&self)
707    }
708}
709
710impl Not for JsValue {
711    type Output = bool;
712    fn not(self) -> Self::Output {
713        JsValue::is_falsy(&self)
714    }
715}
716
717// Macro for binary operators with all ownership combinations
718macro_rules! impl_binary_op {
719    ($trait:ident, $method:ident, $js_method:ident) => {
720        // JsValue op JsValue
721        impl $trait for JsValue {
722            type Output = JsValue;
723            fn $method(self, rhs: JsValue) -> JsValue {
724                JsValue::$js_method(&self, &rhs)
725            }
726        }
727
728        // JsValue op &JsValue
729        impl $trait<&JsValue> for JsValue {
730            type Output = JsValue;
731            fn $method(self, rhs: &JsValue) -> JsValue {
732                JsValue::$js_method(&self, rhs)
733            }
734        }
735
736        // &JsValue op JsValue
737        impl<'a> $trait<JsValue> for &'a JsValue {
738            type Output = JsValue;
739            fn $method(self, rhs: JsValue) -> JsValue {
740                JsValue::$js_method(self, &rhs)
741            }
742        }
743    };
744}
745
746impl_binary_op!(Add, add, add);
747impl_binary_op!(Sub, sub, sub);
748impl_binary_op!(Mul, mul, mul);
749impl_binary_op!(Div, div, div);
750impl_binary_op!(Rem, rem, rem);
751impl_binary_op!(BitAnd, bitand, bit_and);
752impl_binary_op!(BitOr, bitor, bit_or);
753impl_binary_op!(BitXor, bitxor, bit_xor);
754impl_binary_op!(Shl, shl, shl);
755impl_binary_op!(Shr, shr, shr);
756
757impl From<bool> for JsValue {
758    fn from(s: bool) -> JsValue {
759        JsValue::from_bool(s)
760    }
761}
762
763impl<T> From<*mut T> for JsValue {
764    fn from(s: *mut T) -> JsValue {
765        JsValue::from(s as usize)
766    }
767}
768
769impl<T> From<*const T> for JsValue {
770    fn from(s: *const T) -> JsValue {
771        JsValue::from(s as usize)
772    }
773}
774
775impl<T> From<NonNull<T>> for JsValue {
776    fn from(s: NonNull<T>) -> JsValue {
777        JsValue::from(s.as_ptr() as usize)
778    }
779}
780
781impl<T> From<Vec<T>> for JsValue
782where
783    Vec<T>: crate::BinaryEncode + crate::EncodeTypeDef,
784{
785    fn from(vector: Vec<T>) -> Self {
786        crate::__rt::wbg_cast(vector)
787    }
788}
789
790impl<T> From<Box<[T]>> for JsValue
791where
792    Box<[T]>: crate::BinaryEncode + crate::EncodeTypeDef,
793{
794    fn from(vector: Box<[T]>) -> Self {
795        crate::__rt::wbg_cast(vector)
796    }
797}
798
799impl<T> From<crate::Clamped<Vec<T>>> for JsValue
800where
801    crate::Clamped<Vec<T>>: crate::BinaryEncode + crate::EncodeTypeDef,
802{
803    fn from(vector: crate::Clamped<Vec<T>>) -> Self {
804        crate::__rt::wbg_cast(vector)
805    }
806}
807
808impl<T> From<crate::Clamped<Box<[T]>>> for JsValue
809where
810    crate::Clamped<Vec<T>>: crate::BinaryEncode + crate::EncodeTypeDef,
811{
812    fn from(vector: crate::Clamped<Box<[T]>>) -> Self {
813        crate::__rt::wbg_cast(crate::Clamped(vector.0.into_vec()))
814    }
815}