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