Skip to main content

wasm_bindgen/rt/
mod.rs

1use crate::convert::{FromWasmAbi, IntoWasmAbi, WasmAbi, WasmRet};
2use crate::describe::inform;
3use crate::JsValue;
4#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
5use core::any::Any;
6use core::borrow::{Borrow, BorrowMut};
7#[cfg(target_feature = "atomics")]
8use core::cell::UnsafeCell;
9use core::cell::{Cell, RefCell};
10use core::convert::Infallible;
11use core::ops::{Deref, DerefMut};
12use core::panic::{RefUnwindSafe, UnwindSafe};
13#[cfg(target_feature = "atomics")]
14use core::sync::atomic::{AtomicU8, Ordering};
15use wasm_bindgen_shared::tys::FUNCTION;
16
17use alloc::alloc::{alloc, dealloc, realloc, Layout};
18use alloc::rc::Rc;
19use once_cell::unsync::Lazy;
20
21pub extern crate alloc;
22pub extern crate core;
23#[cfg(feature = "std")]
24pub extern crate std;
25
26pub mod marker;
27
28pub use wasm_bindgen_macro::BindgenedStruct;
29
30/// Wrapper implementation for JsValue errors, with atomics and std handling
31pub fn js_panic(err: JsValue) {
32    #[cfg(all(feature = "std", not(target_feature = "atomics")))]
33    ::std::panic::panic_any(err);
34    #[cfg(not(all(feature = "std", not(target_feature = "atomics"))))]
35    ::core::panic!("{:?}", err);
36}
37
38// Cast between arbitrary types supported by wasm-bindgen by going via JS.
39//
40// The implementation generates a no-op JS adapter that simply takes an argument
41// in one type, decodes it from the ABI, and then returns the same value back
42// encoded with a different type.
43pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
44    // Here we need to create a conversion function between arbitrary types
45    // supported by the wasm-bindgen's ABI.
46    // To do that we... take a few unconventional turns.
47    // In essence what happens here is this:
48    //
49    // 1. First up, below we call a function, `breaks_if_inlined`. This
50    //    function, as the name implies, does not work if it's inlined.
51    //    More on that in a moment.
52    // 2. This is actually a descriptor function, similar to ones we
53    //    generate for imports and exports, except we can't name it here
54    //    because it's generated by monomorphisation for specific types.
55    // 2. Since we can't name it to associate with a specific import or
56    //    export, we use a different approach. After describing the input
57    //    type, this function internally calls a special import recognized
58    //    by the `wasm-bindgen` CLI tool, `__wbindgen_describe_cast`. This
59    //    imported symbol is similar to `__wbindgen_describe` in that it's
60    //    not intended to show up in the final binary but it's merely a
61    //    signal for `wasm-bindgen` that marks the parent function
62    //    (`breaks_if_inlined`) as a cast descriptor.
63    //
64    // Most of this doesn't actually make sense to happen at runtime! The
65    // real magic happens when `wasm-bindgen` comes along and updates our
66    // generated code. When `wasm-bindgen` runs it performs a few tasks:
67    //
68    // * First, it finds all functions that call
69    //   `__wbindgen_describe_cast`. These are all `breaks_if_inlined`
70    //   defined below as the symbol isn't called anywhere else.
71    // * Next, `wasm-bindgen` executes the `breaks_if_inlined`
72    //   monomorphized functions, passing it dummy arguments. This will
73    //   execute the function until it reaches the call to
74    //   `__wbindgen_describe_cast`, at which point the interpreter stops.
75    // * Finally, and probably most heinously, the call to
76    //   `breaks_if_inlined` is rewritten to call an otherwise globally
77    //   imported function. This globally imported function will simply
78    //   return the passed in argument, but because it's adapter for our
79    //   descriptors, what we get is actually a general JS cast going via
80    //   Rust input type -> ABI -> JS value -> Rust output type chain.
81
82    #[inline(never)]
83    #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
84    unsafe extern "C" fn breaks_if_inlined<From: IntoWasmAbi, To: FromWasmAbi>(
85        prim1: <From::Abi as WasmAbi>::Prim1,
86        prim2: <From::Abi as WasmAbi>::Prim2,
87        prim3: <From::Abi as WasmAbi>::Prim3,
88        prim4: <From::Abi as WasmAbi>::Prim4,
89    ) -> WasmRet<To::Abi> {
90        inform(FUNCTION);
91        inform(0);
92        inform(1);
93        From::describe();
94        To::describe();
95        To::describe();
96        // Pass all inputs and outputs across the opaque FFI boundary to prevent
97        // compiler from removing them as dead code.
98        core::ptr::read(super::__wbindgen_describe_cast(
99            breaks_if_inlined::<From, To> as _,
100            &(prim1, prim2, prim3, prim4) as *const _ as _,
101        ) as _)
102    }
103
104    let (prim1, prim2, prim3, prim4) = value.into_abi().split();
105
106    unsafe { To::from_abi(breaks_if_inlined::<From, To>(prim1, prim2, prim3, prim4).join()) }
107}
108
109pub(crate) const JSIDX_OFFSET: u32 = 1024; // keep in sync with js/mod.rs
110pub(crate) const JSIDX_UNDEFINED: u32 = JSIDX_OFFSET;
111pub(crate) const JSIDX_NULL: u32 = JSIDX_OFFSET + 1;
112pub(crate) const JSIDX_TRUE: u32 = JSIDX_OFFSET + 2;
113pub(crate) const JSIDX_FALSE: u32 = JSIDX_OFFSET + 3;
114pub(crate) const JSIDX_RESERVED: u32 = JSIDX_OFFSET + 4;
115
116pub(crate) struct ThreadLocalWrapper<T>(pub(crate) T);
117
118#[cfg(not(target_feature = "atomics"))]
119unsafe impl<T> Sync for ThreadLocalWrapper<T> {}
120
121#[cfg(not(target_feature = "atomics"))]
122unsafe impl<T> Send for ThreadLocalWrapper<T> {}
123
124/// Wrapper around [`Lazy`] adding `Send + Sync` when `atomics` is not enabled.
125pub struct LazyCell<T, F = fn() -> T>(ThreadLocalWrapper<Lazy<T, F>>);
126
127impl<T, F> LazyCell<T, F> {
128    pub const fn new(init: F) -> LazyCell<T, F> {
129        Self(ThreadLocalWrapper(Lazy::new(init)))
130    }
131}
132
133impl<T, F: FnOnce() -> T> LazyCell<T, F> {
134    pub fn force(this: &Self) -> &T {
135        &this.0 .0
136    }
137}
138
139impl<T> Deref for LazyCell<T> {
140    type Target = T;
141
142    fn deref(&self) -> &T {
143        ::once_cell::unsync::Lazy::force(&self.0 .0)
144    }
145}
146
147#[cfg(not(target_feature = "atomics"))]
148pub use LazyCell as LazyLock;
149
150#[cfg(target_feature = "atomics")]
151pub struct LazyLock<T, F = fn() -> T> {
152    state: AtomicU8,
153    data: UnsafeCell<Data<T, F>>,
154}
155
156#[cfg(target_feature = "atomics")]
157enum Data<T, F> {
158    Value(T),
159    Init(F),
160}
161
162#[cfg(target_feature = "atomics")]
163impl<T, F> LazyLock<T, F> {
164    const STATE_UNINIT: u8 = 0;
165    const STATE_INITIALIZING: u8 = 1;
166    const STATE_INIT: u8 = 2;
167
168    pub const fn new(init: F) -> LazyLock<T, F> {
169        Self {
170            state: AtomicU8::new(Self::STATE_UNINIT),
171            data: UnsafeCell::new(Data::Init(init)),
172        }
173    }
174}
175
176#[cfg(target_feature = "atomics")]
177impl<T> Deref for LazyLock<T> {
178    type Target = T;
179
180    fn deref(&self) -> &T {
181        let mut state = self.state.load(Ordering::Acquire);
182
183        loop {
184            match state {
185                Self::STATE_INIT => {
186                    let Data::Value(value) = (unsafe { &*self.data.get() }) else {
187                        unreachable!()
188                    };
189                    return value;
190                }
191                Self::STATE_UNINIT => {
192                    if let Err(new_state) = self.state.compare_exchange_weak(
193                        Self::STATE_UNINIT,
194                        Self::STATE_INITIALIZING,
195                        Ordering::Acquire,
196                        Ordering::Relaxed,
197                    ) {
198                        state = new_state;
199                        continue;
200                    }
201
202                    let data = unsafe { &mut *self.data.get() };
203                    let Data::Init(init) = data else {
204                        unreachable!()
205                    };
206                    *data = Data::Value(init());
207                    self.state.store(Self::STATE_INIT, Ordering::Release);
208                    state = Self::STATE_INIT;
209                }
210                Self::STATE_INITIALIZING => {
211                    // TODO: Block here if possible. This would require
212                    // detecting if we can in the first place.
213                    state = self.state.load(Ordering::Acquire);
214                }
215                _ => unreachable!(),
216            }
217        }
218    }
219}
220
221#[cfg(target_feature = "atomics")]
222unsafe impl<T, F: Sync> Sync for LazyLock<T, F> {}
223
224#[cfg(target_feature = "atomics")]
225unsafe impl<T, F: Send> Send for LazyLock<T, F> {}
226
227#[macro_export]
228#[doc(hidden)]
229#[cfg(not(target_feature = "atomics"))]
230macro_rules! __wbindgen_thread_local {
231    ($wasm_bindgen:tt, $actual_ty:ty) => {{
232        static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
233            $wasm_bindgen::__rt::LazyCell::new(init);
234        $wasm_bindgen::JsThreadLocal { __inner: &_VAL }
235    }};
236}
237
238#[macro_export]
239#[doc(hidden)]
240#[cfg(target_feature = "atomics")]
241#[allow_internal_unstable(thread_local)]
242macro_rules! __wbindgen_thread_local {
243    ($wasm_bindgen:tt, $actual_ty:ty) => {{
244        #[thread_local]
245        static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
246            $wasm_bindgen::__rt::LazyCell::new(init);
247        $wasm_bindgen::JsThreadLocal {
248            __inner: || unsafe { $wasm_bindgen::__rt::LazyCell::force(&_VAL) as *const $actual_ty },
249        }
250    }};
251}
252
253#[macro_export]
254#[doc(hidden)]
255#[cfg(not(wasm_bindgen_unstable_test_coverage))]
256macro_rules! __wbindgen_coverage {
257    ($item:item) => {
258        $item
259    };
260}
261
262#[macro_export]
263#[doc(hidden)]
264#[cfg(wasm_bindgen_unstable_test_coverage)]
265#[allow_internal_unstable(coverage_attribute)]
266macro_rules! __wbindgen_coverage {
267    ($item:item) => {
268        #[coverage(off)]
269        $item
270    };
271}
272
273#[inline]
274pub fn assert_not_null<T>(s: *mut T) {
275    if s.is_null() {
276        throw_null();
277    }
278}
279
280#[cold]
281#[inline(never)]
282fn throw_null() -> ! {
283    super::throw_str("null pointer passed to rust");
284}
285
286/// A wrapper around the `RefCell` from the standard library.
287///
288/// Now why, you may ask, would we do that? Surely `RefCell` in libstd is
289/// quite good. And you're right, it is indeed quite good! Functionally
290/// nothing more is needed from `RefCell` in the standard library but for
291/// now this crate is also sort of optimizing for compiled code size.
292///
293/// One major factor to larger binaries in Rust is when a panic happens.
294/// Panicking in the standard library involves a fair bit of machinery
295/// (formatting, panic hooks, synchronization, etc). It's all worthwhile if
296/// you need it but for something like `WasmRefCell` here we don't actually
297/// need all that!
298///
299/// This is just a wrapper around all Rust objects passed to JS intended to
300/// guard accidental reentrancy, so this vendored version is intended solely
301/// to not panic in libstd. Instead when it "panics" it calls our `throw`
302/// function in this crate which raises an error in JS.
303pub struct WasmRefCell<T: ?Sized> {
304    inner: RefCell<T>,
305}
306
307impl<T: ?Sized> UnwindSafe for WasmRefCell<T> {}
308impl<T: ?Sized> RefUnwindSafe for WasmRefCell<T> {}
309
310impl<T: ?Sized> WasmRefCell<T> {
311    pub fn new(value: T) -> WasmRefCell<T>
312    where
313        T: Sized,
314    {
315        WasmRefCell {
316            inner: RefCell::new(value),
317        }
318    }
319
320    pub fn get_mut(&mut self) -> &mut T {
321        self.inner.get_mut()
322    }
323
324    pub fn borrow(&self) -> Ref<'_, T> {
325        match self.inner.try_borrow() {
326            Ok(inner) => Ref { inner },
327            Err(_) => borrow_fail(),
328        }
329    }
330
331    pub fn borrow_mut(&self) -> RefMut<'_, T> {
332        match self.inner.try_borrow_mut() {
333            Ok(inner) => RefMut { inner },
334            Err(_) => borrow_fail(),
335        }
336    }
337
338    pub fn into_inner(self) -> T
339    where
340        T: Sized,
341    {
342        self.inner.into_inner()
343    }
344}
345
346pub struct Ref<'b, T: ?Sized + 'b> {
347    inner: core::cell::Ref<'b, T>,
348}
349
350impl<T: ?Sized> Deref for Ref<'_, T> {
351    type Target = T;
352
353    #[inline]
354    fn deref(&self) -> &T {
355        &self.inner
356    }
357}
358
359impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
360    #[inline]
361    fn borrow(&self) -> &T {
362        self
363    }
364}
365
366pub struct RefMut<'b, T: ?Sized + 'b> {
367    inner: core::cell::RefMut<'b, T>,
368}
369
370impl<T: ?Sized> Deref for RefMut<'_, T> {
371    type Target = T;
372
373    #[inline]
374    fn deref(&self) -> &T {
375        &self.inner
376    }
377}
378
379impl<T: ?Sized> DerefMut for RefMut<'_, T> {
380    #[inline]
381    fn deref_mut(&mut self) -> &mut T {
382        &mut self.inner
383    }
384}
385
386impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
387    #[inline]
388    fn borrow(&self) -> &T {
389        self
390    }
391}
392
393impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
394    #[inline]
395    fn borrow_mut(&mut self) -> &mut T {
396        self
397    }
398}
399
400#[cfg(panic = "unwind")]
401fn borrow_fail() -> ! {
402    panic!(
403        "recursive use of an object detected which would lead to \
404		 unsafe aliasing in rust",
405    )
406}
407
408#[cfg(not(panic = "unwind"))]
409fn borrow_fail() -> ! {
410    super::throw_str(
411        "recursive use of an object detected which would lead to \
412		 unsafe aliasing in rust",
413    );
414}
415
416/// A type that encapsulates an `Rc<WasmRefCell<T>>` as well as a `Ref`
417/// to the contents of that `WasmRefCell`.
418///
419/// The `'static` requirement is an unfortunate consequence of how this
420/// is implemented.
421pub struct RcRef<T: ?Sized + 'static> {
422    // The 'static is a lie.
423    //
424    // We could get away without storing this, since we're in the same module as
425    // `WasmRefCell` and can directly manipulate its `borrow`, but I'm considering
426    // turning it into a wrapper around `std`'s `RefCell` to reduce `unsafe` in
427    // which case that would stop working. This also requires less `unsafe` as is.
428    //
429    // It's important that this goes before `Rc` so that it gets dropped first.
430    ref_: Ref<'static, T>,
431    _rc: Rc<WasmRefCell<T>>,
432}
433
434impl<T: ?Sized> UnwindSafe for RcRef<T> {}
435
436impl<T: ?Sized> RcRef<T> {
437    pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
438        let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow() };
439        Self { _rc: rc, ref_ }
440    }
441}
442
443impl<T: ?Sized> Deref for RcRef<T> {
444    type Target = T;
445
446    #[inline]
447    fn deref(&self) -> &T {
448        &self.ref_
449    }
450}
451
452impl<T: ?Sized> Borrow<T> for RcRef<T> {
453    #[inline]
454    fn borrow(&self) -> &T {
455        &self.ref_
456    }
457}
458
459/// A type that encapsulates an `Rc<WasmRefCell<T>>` as well as a
460/// `RefMut` to the contents of that `WasmRefCell`.
461///
462/// The `'static` requirement is an unfortunate consequence of how this
463/// is implemented.
464pub struct RcRefMut<T: ?Sized + 'static> {
465    ref_: RefMut<'static, T>,
466    _rc: Rc<WasmRefCell<T>>,
467}
468
469impl<T: ?Sized> RcRefMut<T> {
470    pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
471        let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow_mut() };
472        Self { _rc: rc, ref_ }
473    }
474}
475
476impl<T: ?Sized> Deref for RcRefMut<T> {
477    type Target = T;
478
479    #[inline]
480    fn deref(&self) -> &T {
481        &self.ref_
482    }
483}
484
485impl<T: ?Sized> DerefMut for RcRefMut<T> {
486    #[inline]
487    fn deref_mut(&mut self) -> &mut T {
488        &mut self.ref_
489    }
490}
491
492impl<T: ?Sized> Borrow<T> for RcRefMut<T> {
493    #[inline]
494    fn borrow(&self) -> &T {
495        &self.ref_
496    }
497}
498
499impl<T: ?Sized> BorrowMut<T> for RcRefMut<T> {
500    #[inline]
501    fn borrow_mut(&mut self) -> &mut T {
502        &mut self.ref_
503    }
504}
505
506#[no_mangle]
507pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 {
508    if let Ok(layout) = Layout::from_size_align(size, align) {
509        unsafe {
510            if layout.size() > 0 {
511                let ptr = alloc(layout);
512                if !ptr.is_null() {
513                    return ptr;
514                }
515            } else {
516                return align as *mut u8;
517            }
518        }
519    }
520
521    malloc_failure();
522}
523
524#[no_mangle]
525pub unsafe extern "C" fn __wbindgen_realloc(
526    ptr: *mut u8,
527    old_size: usize,
528    new_size: usize,
529    align: usize,
530) -> *mut u8 {
531    debug_assert!(old_size > 0);
532    debug_assert!(new_size > 0);
533    if let Ok(layout) = Layout::from_size_align(old_size, align) {
534        let ptr = realloc(ptr, layout, new_size);
535        if !ptr.is_null() {
536            return ptr;
537        }
538    }
539    malloc_failure();
540}
541
542#[cold]
543fn malloc_failure() -> ! {
544    cfg_if::cfg_if! {
545        if #[cfg(debug_assertions)] {
546            super::throw_str("invalid malloc request")
547        } else if #[cfg(feature = "std")] {
548            std::process::abort();
549        } else if #[cfg(all(
550            target_arch = "wasm32",
551            any(target_os = "unknown", target_os = "none")
552        ))] {
553            core::arch::wasm32::unreachable();
554        } else {
555            unreachable!()
556        }
557    }
558}
559
560#[no_mangle]
561pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) {
562    // This happens for zero-length slices, and in that case `ptr` is
563    // likely bogus so don't actually send this to the system allocator
564    if size == 0 {
565        return;
566    }
567    let layout = Layout::from_size_align_unchecked(size, align);
568    dealloc(ptr, layout);
569}
570
571/// This is a curious function necessary to get wasm-bindgen working today,
572/// and it's a bit of an unfortunate hack.
573///
574/// The general problem is that somehow we need the above two symbols to
575/// exist in the final output binary (__wbindgen_malloc and
576/// __wbindgen_free). These symbols may be called by JS for various
577/// bindings, so we for sure need to make sure they're exported.
578///
579/// The problem arises, though, when what if no Rust code uses the symbols?
580/// For all intents and purposes it looks to LLVM and the linker like the
581/// above two symbols are dead code, so they're completely discarded!
582///
583/// Specifically what happens is this:
584///
585/// * The above two symbols are generated into some object file inside of
586///   libwasm_bindgen.rlib
587/// * The linker, LLD, will not load this object file unless *some* symbol
588///   is loaded from the object. In this case, if the Rust code never calls
589///   __wbindgen_malloc or __wbindgen_free then the symbols never get linked
590///   in.
591/// * Later when `wasm-bindgen` attempts to use the symbols they don't
592///   exist, causing an error.
593///
594/// This function is a weird hack for this problem. We inject a call to this
595/// function in all generated code. Usage of this function should then
596/// ensure that the above two intrinsics are translated.
597///
598/// Due to how rustc creates object files this function (and anything inside
599/// it) will be placed into the same object file as the two intrinsics
600/// above. That means if this function is called and referenced we'll pull
601/// in the object file and link the intrinsics.
602///
603/// Ideas for how to improve this are most welcome!
604#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
605pub fn link_mem_intrinsics() {
606    crate::link::link_intrinsics();
607}
608
609#[cfg_attr(target_feature = "atomics", thread_local)]
610static GLOBAL_EXNDATA: ThreadLocalWrapper<Cell<[u32; 2]>> = ThreadLocalWrapper(Cell::new([0; 2]));
611
612#[cfg(panic = "unwind")]
613#[no_mangle]
614pub static mut __instance_terminated: u32 = 0;
615
616#[no_mangle]
617pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
618    debug_assert_eq!(GLOBAL_EXNDATA.0.get()[0], 0);
619    GLOBAL_EXNDATA.0.set([1, idx]);
620}
621
622pub fn take_last_exception() -> Result<(), super::JsValue> {
623    let ret = if GLOBAL_EXNDATA.0.get()[0] == 1 {
624        Err(super::JsValue::_new(GLOBAL_EXNDATA.0.get()[1]))
625    } else {
626        Ok(())
627    };
628    GLOBAL_EXNDATA.0.set([0, 0]);
629    ret
630}
631
632/// An internal helper trait for usage in `#[wasm_bindgen]` on `async`
633/// functions to convert the return value of the function to
634/// `Result<JsValue, JsValue>` which is what we'll return to JS (where an
635/// error is a failed future).
636pub trait IntoJsResult {
637    fn into_js_result(self) -> Result<JsValue, JsValue>;
638}
639
640impl IntoJsResult for () {
641    fn into_js_result(self) -> Result<JsValue, JsValue> {
642        Ok(JsValue::undefined())
643    }
644}
645
646impl<T: Into<JsValue>> IntoJsResult for T {
647    fn into_js_result(self) -> Result<JsValue, JsValue> {
648        Ok(self.into())
649    }
650}
651
652impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> {
653    fn into_js_result(self) -> Result<JsValue, JsValue> {
654        match self {
655            Ok(e) => Ok(e.into()),
656            Err(e) => Err(e.into()),
657        }
658    }
659}
660
661impl<E: Into<JsValue>> IntoJsResult for Result<(), E> {
662    fn into_js_result(self) -> Result<JsValue, JsValue> {
663        match self {
664            Ok(()) => Ok(JsValue::undefined()),
665            Err(e) => Err(e.into()),
666        }
667    }
668}
669
670/// An internal helper trait for usage in `#[wasm_bindgen(start)]`
671/// functions to throw the error (if it is `Err`).
672pub trait Start {
673    fn start(self);
674}
675
676impl Start for () {
677    #[inline]
678    fn start(self) {}
679}
680
681impl<E: Into<JsValue>> Start for Result<(), E> {
682    #[inline]
683    fn start(self) {
684        if let Err(e) = self {
685            crate::throw_val(e.into());
686        }
687    }
688}
689
690/// An internal helper struct for usage in `#[wasm_bindgen(main)]`
691/// functions to throw the error (if it is `Err`).
692pub struct MainWrapper<T>(pub Option<T>);
693
694pub trait Main {
695    fn __wasm_bindgen_main(&mut self);
696}
697
698impl Main for &mut &mut MainWrapper<()> {
699    #[inline]
700    fn __wasm_bindgen_main(&mut self) {}
701}
702
703impl Main for &mut &mut MainWrapper<Infallible> {
704    #[inline]
705    fn __wasm_bindgen_main(&mut self) {}
706}
707
708impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> {
709    #[inline]
710    fn __wasm_bindgen_main(&mut self) {
711        if let Err(e) = self.0.take().unwrap() {
712            crate::throw_val(e.into());
713        }
714    }
715}
716
717impl<E: core::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
718    #[inline]
719    fn __wasm_bindgen_main(&mut self) {
720        if let Err(e) = self.0.take().unwrap() {
721            crate::throw_str(&alloc::format!("{e:?}"));
722        }
723    }
724}
725
726pub const fn flat_len<T, const SIZE: usize>(slices: [&[T]; SIZE]) -> usize {
727    let mut len = 0;
728    let mut i = 0;
729    while i < slices.len() {
730        len += slices[i].len();
731        i += 1;
732    }
733    len
734}
735
736pub const fn flat_byte_slices<const RESULT_LEN: usize, const SIZE: usize>(
737    slices: [&[u8]; SIZE],
738) -> [u8; RESULT_LEN] {
739    let mut result = [0; RESULT_LEN];
740
741    let mut slice_index = 0;
742    let mut result_offset = 0;
743
744    while slice_index < slices.len() {
745        let mut i = 0;
746        let slice = slices[slice_index];
747        while i < slice.len() {
748            result[result_offset] = slice[i];
749            i += 1;
750            result_offset += 1;
751        }
752        slice_index += 1;
753    }
754
755    result
756}
757
758// NOTE: This method is used to encode u32 into a variable-length-integer during the compile-time .
759// Generally speaking, the length of the encoded variable-length-integer depends on the size of the integer
760// but the maximum capacity can be used here to simplify the amount of code during the compile-time .
761pub const fn encode_u32_to_fixed_len_bytes(value: u32) -> [u8; 5] {
762    let mut result: [u8; 5] = [0; 5];
763    let mut i = 0;
764    while i < 4 {
765        result[i] = ((value >> (7 * i)) | 0x80) as u8;
766        i += 1;
767    }
768    result[4] = (value >> (7 * 4)) as u8;
769    result
770}
771
772#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
773#[wasm_bindgen_macro::wasm_bindgen(wasm_bindgen = crate, raw_module = "__wbindgen_placeholder__")]
774extern "C" {
775    fn __wbindgen_panic_error(msg: &JsValue) -> JsValue;
776}
777
778#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
779pub fn panic_to_panic_error(val: std::boxed::Box<dyn Any + Send>) -> JsValue {
780    #[cfg(not(target_feature = "atomics"))]
781    {
782        if let Some(s) = val.downcast_ref::<JsValue>() {
783            return __wbindgen_panic_error(&s);
784        }
785    }
786    let maybe_panic_msg: Option<&str> = if let Some(s) = val.downcast_ref::<&str>() {
787        Some(s)
788    } else if let Some(s) = val.downcast_ref::<std::string::String>() {
789        Some(s)
790    } else {
791        None
792    };
793    let err: JsValue = __wbindgen_panic_error(&JsValue::from_str(
794        maybe_panic_msg.unwrap_or("No panic message available"),
795    ));
796    err
797}
798
799#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
800pub fn maybe_catch_unwind<F: FnOnce() -> R + std::panic::UnwindSafe, R>(f: F) -> R {
801    let result = std::panic::catch_unwind(f);
802    match result {
803        Ok(val) => val,
804        Err(e) => {
805            crate::throw_val(panic_to_panic_error(e));
806        }
807    }
808}
809
810#[cfg(not(all(target_arch = "wasm32", feature = "std", panic = "unwind")))]
811pub fn maybe_catch_unwind<F: FnOnce() -> R, R>(f: F) -> R {
812    f()
813}