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