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