1use crate::convert::{FromWasmAbi, IntoWasmAbi, WasmAbi, WasmRet};
2use crate::describe::inform;
3use crate::JsValue;
4#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
5use core::any::Any;
6use core::borrow::{Borrow, BorrowMut};
7#[cfg(target_feature = "atomics")]
8use core::cell::UnsafeCell;
9use core::cell::{Cell, RefCell};
10use core::convert::Infallible;
11use core::ops::{Deref, DerefMut};
12use core::panic::{RefUnwindSafe, UnwindSafe};
13#[cfg(target_feature = "atomics")]
14use core::sync::atomic::{AtomicU8, Ordering};
15use wasm_bindgen_shared::tys::FUNCTION;
16
17use alloc::alloc::{alloc, dealloc, realloc, Layout};
18use alloc::rc::Rc;
19use once_cell::unsync::Lazy;
20
21pub extern crate alloc;
22pub extern crate core;
23#[cfg(feature = "std")]
24pub extern crate std;
25
26pub mod marker;
27
28pub use wasm_bindgen_macro::BindgenedStruct;
29
30pub fn js_panic(err: JsValue) {
32 #[cfg(all(feature = "std", not(target_feature = "atomics")))]
33 ::std::panic::panic_any(err);
34 #[cfg(not(all(feature = "std", not(target_feature = "atomics"))))]
35 ::core::panic!("{:?}", err);
36}
37
38pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
44 #[inline(never)]
83 #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
84 unsafe extern "C" fn breaks_if_inlined<From: IntoWasmAbi, To: FromWasmAbi>(
85 prim1: <From::Abi as WasmAbi>::Prim1,
86 prim2: <From::Abi as WasmAbi>::Prim2,
87 prim3: <From::Abi as WasmAbi>::Prim3,
88 prim4: <From::Abi as WasmAbi>::Prim4,
89 ) -> WasmRet<To::Abi> {
90 inform(FUNCTION);
91 inform(0);
92 inform(1);
93 From::describe();
94 To::describe();
95 To::describe();
96 core::ptr::read(super::__wbindgen_describe_cast(
99 breaks_if_inlined::<From, To> as _,
100 &(prim1, prim2, prim3, prim4) as *const _ as _,
101 ) as _)
102 }
103
104 let (prim1, prim2, prim3, prim4) = value.into_abi().split();
105
106 unsafe { To::from_abi(breaks_if_inlined::<From, To>(prim1, prim2, prim3, prim4).join()) }
107}
108
109pub(crate) const JSIDX_OFFSET: u32 = 1024; pub(crate) const JSIDX_UNDEFINED: u32 = JSIDX_OFFSET;
111pub(crate) const JSIDX_NULL: u32 = JSIDX_OFFSET + 1;
112pub(crate) const JSIDX_TRUE: u32 = JSIDX_OFFSET + 2;
113pub(crate) const JSIDX_FALSE: u32 = JSIDX_OFFSET + 3;
114pub(crate) const JSIDX_RESERVED: u32 = JSIDX_OFFSET + 4;
115
116pub(crate) struct ThreadLocalWrapper<T>(pub(crate) T);
117
118#[cfg(not(target_feature = "atomics"))]
119unsafe impl<T> Sync for ThreadLocalWrapper<T> {}
120
121#[cfg(not(target_feature = "atomics"))]
122unsafe impl<T> Send for ThreadLocalWrapper<T> {}
123
124pub struct LazyCell<T, F = fn() -> T>(ThreadLocalWrapper<Lazy<T, F>>);
126
127impl<T, F> LazyCell<T, F> {
128 pub const fn new(init: F) -> LazyCell<T, F> {
129 Self(ThreadLocalWrapper(Lazy::new(init)))
130 }
131}
132
133impl<T, F: FnOnce() -> T> LazyCell<T, F> {
134 pub fn force(this: &Self) -> &T {
135 &this.0 .0
136 }
137}
138
139impl<T> Deref for LazyCell<T> {
140 type Target = T;
141
142 fn deref(&self) -> &T {
143 ::once_cell::unsync::Lazy::force(&self.0 .0)
144 }
145}
146
147#[cfg(not(target_feature = "atomics"))]
148pub use LazyCell as LazyLock;
149
150#[cfg(target_feature = "atomics")]
151pub struct LazyLock<T, F = fn() -> T> {
152 state: AtomicU8,
153 data: UnsafeCell<Data<T, F>>,
154}
155
156#[cfg(target_feature = "atomics")]
157enum Data<T, F> {
158 Value(T),
159 Init(F),
160}
161
162#[cfg(target_feature = "atomics")]
163impl<T, F> LazyLock<T, F> {
164 const STATE_UNINIT: u8 = 0;
165 const STATE_INITIALIZING: u8 = 1;
166 const STATE_INIT: u8 = 2;
167
168 pub const fn new(init: F) -> LazyLock<T, F> {
169 Self {
170 state: AtomicU8::new(Self::STATE_UNINIT),
171 data: UnsafeCell::new(Data::Init(init)),
172 }
173 }
174}
175
176#[cfg(target_feature = "atomics")]
177impl<T> Deref for LazyLock<T> {
178 type Target = T;
179
180 fn deref(&self) -> &T {
181 let mut state = self.state.load(Ordering::Acquire);
182
183 loop {
184 match state {
185 Self::STATE_INIT => {
186 let Data::Value(value) = (unsafe { &*self.data.get() }) else {
187 unreachable!()
188 };
189 return value;
190 }
191 Self::STATE_UNINIT => {
192 if let Err(new_state) = self.state.compare_exchange_weak(
193 Self::STATE_UNINIT,
194 Self::STATE_INITIALIZING,
195 Ordering::Acquire,
196 Ordering::Relaxed,
197 ) {
198 state = new_state;
199 continue;
200 }
201
202 let data = unsafe { &mut *self.data.get() };
203 let Data::Init(init) = data else {
204 unreachable!()
205 };
206 *data = Data::Value(init());
207 self.state.store(Self::STATE_INIT, Ordering::Release);
208 state = Self::STATE_INIT;
209 }
210 Self::STATE_INITIALIZING => {
211 state = self.state.load(Ordering::Acquire);
214 }
215 _ => unreachable!(),
216 }
217 }
218 }
219}
220
221#[cfg(target_feature = "atomics")]
222unsafe impl<T, F: Sync> Sync for LazyLock<T, F> {}
223
224#[cfg(target_feature = "atomics")]
225unsafe impl<T, F: Send> Send for LazyLock<T, F> {}
226
227#[macro_export]
228#[doc(hidden)]
229#[cfg(not(target_feature = "atomics"))]
230macro_rules! __wbindgen_thread_local {
231 ($wasm_bindgen:tt, $actual_ty:ty) => {{
232 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
233 $wasm_bindgen::__rt::LazyCell::new(init);
234 $wasm_bindgen::JsThreadLocal { __inner: &_VAL }
235 }};
236}
237
238#[macro_export]
239#[doc(hidden)]
240#[cfg(target_feature = "atomics")]
241#[allow_internal_unstable(thread_local)]
242macro_rules! __wbindgen_thread_local {
243 ($wasm_bindgen:tt, $actual_ty:ty) => {{
244 #[thread_local]
245 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
246 $wasm_bindgen::__rt::LazyCell::new(init);
247 $wasm_bindgen::JsThreadLocal {
248 __inner: || unsafe { $wasm_bindgen::__rt::LazyCell::force(&_VAL) as *const $actual_ty },
249 }
250 }};
251}
252
253#[macro_export]
254#[doc(hidden)]
255#[cfg(not(wasm_bindgen_unstable_test_coverage))]
256macro_rules! __wbindgen_coverage {
257 ($item:item) => {
258 $item
259 };
260}
261
262#[macro_export]
263#[doc(hidden)]
264#[cfg(wasm_bindgen_unstable_test_coverage)]
265#[allow_internal_unstable(coverage_attribute)]
266macro_rules! __wbindgen_coverage {
267 ($item:item) => {
268 #[coverage(off)]
269 $item
270 };
271}
272
273#[inline]
274pub fn assert_not_null<T>(s: *mut T) {
275 if s.is_null() {
276 throw_null();
277 }
278}
279
280#[cold]
281#[inline(never)]
282fn throw_null() -> ! {
283 super::throw_str("null pointer passed to rust");
284}
285
286pub struct WasmRefCell<T: ?Sized> {
304 inner: RefCell<T>,
305}
306
307impl<T: ?Sized> UnwindSafe for WasmRefCell<T> {}
308impl<T: ?Sized> RefUnwindSafe for WasmRefCell<T> {}
309
310impl<T: ?Sized> WasmRefCell<T> {
311 pub fn new(value: T) -> WasmRefCell<T>
312 where
313 T: Sized,
314 {
315 WasmRefCell {
316 inner: RefCell::new(value),
317 }
318 }
319
320 pub fn get_mut(&mut self) -> &mut T {
321 self.inner.get_mut()
322 }
323
324 pub fn borrow(&self) -> Ref<'_, T> {
325 match self.inner.try_borrow() {
326 Ok(inner) => Ref { inner },
327 Err(_) => borrow_fail(),
328 }
329 }
330
331 pub fn borrow_mut(&self) -> RefMut<'_, T> {
332 match self.inner.try_borrow_mut() {
333 Ok(inner) => RefMut { inner },
334 Err(_) => borrow_fail(),
335 }
336 }
337
338 pub fn into_inner(self) -> T
339 where
340 T: Sized,
341 {
342 self.inner.into_inner()
343 }
344}
345
346pub struct Ref<'b, T: ?Sized + 'b> {
347 inner: core::cell::Ref<'b, T>,
348}
349
350impl<T: ?Sized> Deref for Ref<'_, T> {
351 type Target = T;
352
353 #[inline]
354 fn deref(&self) -> &T {
355 &self.inner
356 }
357}
358
359impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
360 #[inline]
361 fn borrow(&self) -> &T {
362 self
363 }
364}
365
366pub struct RefMut<'b, T: ?Sized + 'b> {
367 inner: core::cell::RefMut<'b, T>,
368}
369
370impl<T: ?Sized> Deref for RefMut<'_, T> {
371 type Target = T;
372
373 #[inline]
374 fn deref(&self) -> &T {
375 &self.inner
376 }
377}
378
379impl<T: ?Sized> DerefMut for RefMut<'_, T> {
380 #[inline]
381 fn deref_mut(&mut self) -> &mut T {
382 &mut self.inner
383 }
384}
385
386impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
387 #[inline]
388 fn borrow(&self) -> &T {
389 self
390 }
391}
392
393impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
394 #[inline]
395 fn borrow_mut(&mut self) -> &mut T {
396 self
397 }
398}
399
400#[cfg(panic = "unwind")]
401fn borrow_fail() -> ! {
402 panic!(
403 "recursive use of an object detected which would lead to \
404 unsafe aliasing in rust",
405 )
406}
407
408#[cfg(not(panic = "unwind"))]
409fn borrow_fail() -> ! {
410 super::throw_str(
411 "recursive use of an object detected which would lead to \
412 unsafe aliasing in rust",
413 );
414}
415
416pub struct RcRef<T: ?Sized + 'static> {
422 ref_: Ref<'static, T>,
431 _rc: Rc<WasmRefCell<T>>,
432}
433
434impl<T: ?Sized> UnwindSafe for RcRef<T> {}
435
436impl<T: ?Sized> RcRef<T> {
437 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
438 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow() };
439 Self { _rc: rc, ref_ }
440 }
441}
442
443impl<T: ?Sized> Deref for RcRef<T> {
444 type Target = T;
445
446 #[inline]
447 fn deref(&self) -> &T {
448 &self.ref_
449 }
450}
451
452impl<T: ?Sized> Borrow<T> for RcRef<T> {
453 #[inline]
454 fn borrow(&self) -> &T {
455 &self.ref_
456 }
457}
458
459pub struct RcRefMut<T: ?Sized + 'static> {
465 ref_: RefMut<'static, T>,
466 _rc: Rc<WasmRefCell<T>>,
467}
468
469impl<T: ?Sized> RcRefMut<T> {
470 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
471 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow_mut() };
472 Self { _rc: rc, ref_ }
473 }
474}
475
476impl<T: ?Sized> Deref for RcRefMut<T> {
477 type Target = T;
478
479 #[inline]
480 fn deref(&self) -> &T {
481 &self.ref_
482 }
483}
484
485impl<T: ?Sized> DerefMut for RcRefMut<T> {
486 #[inline]
487 fn deref_mut(&mut self) -> &mut T {
488 &mut self.ref_
489 }
490}
491
492impl<T: ?Sized> Borrow<T> for RcRefMut<T> {
493 #[inline]
494 fn borrow(&self) -> &T {
495 &self.ref_
496 }
497}
498
499impl<T: ?Sized> BorrowMut<T> for RcRefMut<T> {
500 #[inline]
501 fn borrow_mut(&mut self) -> &mut T {
502 &mut self.ref_
503 }
504}
505
506#[no_mangle]
507pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 {
508 if let Ok(layout) = Layout::from_size_align(size, align) {
509 unsafe {
510 if layout.size() > 0 {
511 let ptr = alloc(layout);
512 if !ptr.is_null() {
513 return ptr;
514 }
515 } else {
516 return align as *mut u8;
517 }
518 }
519 }
520
521 malloc_failure();
522}
523
524#[no_mangle]
525pub unsafe extern "C" fn __wbindgen_realloc(
526 ptr: *mut u8,
527 old_size: usize,
528 new_size: usize,
529 align: usize,
530) -> *mut u8 {
531 debug_assert!(old_size > 0);
532 debug_assert!(new_size > 0);
533 if let Ok(layout) = Layout::from_size_align(old_size, align) {
534 let ptr = realloc(ptr, layout, new_size);
535 if !ptr.is_null() {
536 return ptr;
537 }
538 }
539 malloc_failure();
540}
541
542#[cold]
543fn malloc_failure() -> ! {
544 cfg_if::cfg_if! {
545 if #[cfg(debug_assertions)] {
546 super::throw_str("invalid malloc request")
547 } else if #[cfg(feature = "std")] {
548 std::process::abort();
549 } else if #[cfg(all(
550 target_arch = "wasm32",
551 any(target_os = "unknown", target_os = "none")
552 ))] {
553 core::arch::wasm32::unreachable();
554 } else {
555 unreachable!()
556 }
557 }
558}
559
560#[no_mangle]
561pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) {
562 if size == 0 {
565 return;
566 }
567 let layout = Layout::from_size_align_unchecked(size, align);
568 dealloc(ptr, layout);
569}
570
571#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
605pub fn link_mem_intrinsics() {
606 crate::link::link_intrinsics();
607}
608
609#[cfg_attr(target_feature = "atomics", thread_local)]
610static GLOBAL_EXNDATA: ThreadLocalWrapper<Cell<[u32; 2]>> = ThreadLocalWrapper(Cell::new([0; 2]));
611
612#[cfg(panic = "unwind")]
613#[no_mangle]
614pub static mut __instance_terminated: u32 = 0;
615
616#[no_mangle]
617pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
618 debug_assert_eq!(GLOBAL_EXNDATA.0.get()[0], 0);
619 GLOBAL_EXNDATA.0.set([1, idx]);
620}
621
622pub fn take_last_exception() -> Result<(), super::JsValue> {
623 let ret = if GLOBAL_EXNDATA.0.get()[0] == 1 {
624 Err(super::JsValue::_new(GLOBAL_EXNDATA.0.get()[1]))
625 } else {
626 Ok(())
627 };
628 GLOBAL_EXNDATA.0.set([0, 0]);
629 ret
630}
631
632pub trait IntoJsResult {
637 fn into_js_result(self) -> Result<JsValue, JsValue>;
638}
639
640impl IntoJsResult for () {
641 fn into_js_result(self) -> Result<JsValue, JsValue> {
642 Ok(JsValue::undefined())
643 }
644}
645
646impl<T: Into<JsValue>> IntoJsResult for T {
647 fn into_js_result(self) -> Result<JsValue, JsValue> {
648 Ok(self.into())
649 }
650}
651
652impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> {
653 fn into_js_result(self) -> Result<JsValue, JsValue> {
654 match self {
655 Ok(e) => Ok(e.into()),
656 Err(e) => Err(e.into()),
657 }
658 }
659}
660
661impl<E: Into<JsValue>> IntoJsResult for Result<(), E> {
662 fn into_js_result(self) -> Result<JsValue, JsValue> {
663 match self {
664 Ok(()) => Ok(JsValue::undefined()),
665 Err(e) => Err(e.into()),
666 }
667 }
668}
669
670pub trait Start {
673 fn start(self);
674}
675
676impl Start for () {
677 #[inline]
678 fn start(self) {}
679}
680
681impl<E: Into<JsValue>> Start for Result<(), E> {
682 #[inline]
683 fn start(self) {
684 if let Err(e) = self {
685 crate::throw_val(e.into());
686 }
687 }
688}
689
690pub struct MainWrapper<T>(pub Option<T>);
693
694pub trait Main {
695 fn __wasm_bindgen_main(&mut self);
696}
697
698impl Main for &mut &mut MainWrapper<()> {
699 #[inline]
700 fn __wasm_bindgen_main(&mut self) {}
701}
702
703impl Main for &mut &mut MainWrapper<Infallible> {
704 #[inline]
705 fn __wasm_bindgen_main(&mut self) {}
706}
707
708impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> {
709 #[inline]
710 fn __wasm_bindgen_main(&mut self) {
711 if let Err(e) = self.0.take().unwrap() {
712 crate::throw_val(e.into());
713 }
714 }
715}
716
717impl<E: core::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
718 #[inline]
719 fn __wasm_bindgen_main(&mut self) {
720 if let Err(e) = self.0.take().unwrap() {
721 crate::throw_str(&alloc::format!("{e:?}"));
722 }
723 }
724}
725
726pub const fn flat_len<T, const SIZE: usize>(slices: [&[T]; SIZE]) -> usize {
727 let mut len = 0;
728 let mut i = 0;
729 while i < slices.len() {
730 len += slices[i].len();
731 i += 1;
732 }
733 len
734}
735
736pub const fn flat_byte_slices<const RESULT_LEN: usize, const SIZE: usize>(
737 slices: [&[u8]; SIZE],
738) -> [u8; RESULT_LEN] {
739 let mut result = [0; RESULT_LEN];
740
741 let mut slice_index = 0;
742 let mut result_offset = 0;
743
744 while slice_index < slices.len() {
745 let mut i = 0;
746 let slice = slices[slice_index];
747 while i < slice.len() {
748 result[result_offset] = slice[i];
749 i += 1;
750 result_offset += 1;
751 }
752 slice_index += 1;
753 }
754
755 result
756}
757
758pub const fn encode_u32_to_fixed_len_bytes(value: u32) -> [u8; 5] {
762 let mut result: [u8; 5] = [0; 5];
763 let mut i = 0;
764 while i < 4 {
765 result[i] = ((value >> (7 * i)) | 0x80) as u8;
766 i += 1;
767 }
768 result[4] = (value >> (7 * 4)) as u8;
769 result
770}
771
772#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
773#[wasm_bindgen_macro::wasm_bindgen(wasm_bindgen = crate, raw_module = "__wbindgen_placeholder__")]
774extern "C" {
775 fn __wbindgen_panic_error(msg: &JsValue) -> JsValue;
776}
777
778#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
779pub fn panic_to_panic_error(val: std::boxed::Box<dyn Any + Send>) -> JsValue {
780 #[cfg(not(target_feature = "atomics"))]
781 {
782 if let Some(s) = val.downcast_ref::<JsValue>() {
783 return __wbindgen_panic_error(&s);
784 }
785 }
786 let maybe_panic_msg: Option<&str> = if let Some(s) = val.downcast_ref::<&str>() {
787 Some(s)
788 } else if let Some(s) = val.downcast_ref::<std::string::String>() {
789 Some(s)
790 } else {
791 None
792 };
793 let err: JsValue = __wbindgen_panic_error(&JsValue::from_str(
794 maybe_panic_msg.unwrap_or("No panic message available"),
795 ));
796 err
797}
798
799#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
800pub fn maybe_catch_unwind<F: FnOnce() -> R + std::panic::UnwindSafe, R>(f: F) -> R {
801 let result = std::panic::catch_unwind(f);
802 match result {
803 Ok(val) => val,
804 Err(e) => {
805 crate::throw_val(panic_to_panic_error(e));
806 }
807 }
808}
809
810#[cfg(not(all(target_arch = "wasm32", feature = "std", panic = "unwind")))]
811pub fn maybe_catch_unwind<F: FnOnce() -> R, R>(f: F) -> R {
812 f()
813}