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
28pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
34 #[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 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; pub(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
114pub 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 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
276pub 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
425pub struct RcRef<T: ?Sized + 'static> {
431 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
468pub 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 if size == 0 {
574 return;
575 }
576 let layout = Layout::from_size_align_unchecked(size, align);
577 dealloc(ptr, layout);
578}
579
580#[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
637pub 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
675pub 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
695pub 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
763pub 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}