1use crate::convert::{FromWasmAbi, IntoWasmAbi, WasmAbi, WasmRet};
2use crate::describe::inform;
3use crate::JsValue;
4use core::borrow::{Borrow, BorrowMut};
5use core::cell::{Cell, UnsafeCell};
6use core::convert::Infallible;
7use core::ops::{Deref, DerefMut};
8#[cfg(target_feature = "atomics")]
9use core::sync::atomic::{AtomicU8, Ordering};
10use wasm_bindgen_shared::tys::FUNCTION;
11
12use alloc::alloc::{alloc, dealloc, realloc, Layout};
13use alloc::rc::Rc;
14use once_cell::unsync::Lazy;
15
16pub extern crate alloc;
17pub extern crate core;
18#[cfg(feature = "std")]
19pub extern crate std;
20
21pub mod marker;
22
23pub use wasm_bindgen_macro::BindgenedStruct;
24
25pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
31 #[inline(never)]
70 #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
71 unsafe extern "C" fn breaks_if_inlined<From: IntoWasmAbi, To: FromWasmAbi>(
72 prim1: <From::Abi as WasmAbi>::Prim1,
73 prim2: <From::Abi as WasmAbi>::Prim2,
74 prim3: <From::Abi as WasmAbi>::Prim3,
75 prim4: <From::Abi as WasmAbi>::Prim4,
76 ) -> WasmRet<To::Abi> {
77 inform(FUNCTION);
78 inform(0);
79 inform(1);
80 From::describe();
81 To::describe();
82 To::describe();
83 core::ptr::read(super::__wbindgen_describe_cast(
86 breaks_if_inlined::<From, To> as _,
87 &(prim1, prim2, prim3, prim4) as *const _ as _,
88 ) as _)
89 }
90
91 let (prim1, prim2, prim3, prim4) = value.into_abi().split();
92
93 unsafe { To::from_abi(breaks_if_inlined::<From, To>(prim1, prim2, prim3, prim4).join()) }
94}
95
96pub(crate) struct ThreadLocalWrapper<T>(pub(crate) T);
97
98#[cfg(not(target_feature = "atomics"))]
99unsafe impl<T> Sync for ThreadLocalWrapper<T> {}
100
101#[cfg(not(target_feature = "atomics"))]
102unsafe impl<T> Send for ThreadLocalWrapper<T> {}
103
104pub struct LazyCell<T, F = fn() -> T>(ThreadLocalWrapper<Lazy<T, F>>);
106
107impl<T, F> LazyCell<T, F> {
108 pub const fn new(init: F) -> LazyCell<T, F> {
109 Self(ThreadLocalWrapper(Lazy::new(init)))
110 }
111}
112
113impl<T, F: FnOnce() -> T> LazyCell<T, F> {
114 pub fn force(this: &Self) -> &T {
115 &this.0 .0
116 }
117}
118
119impl<T> Deref for LazyCell<T> {
120 type Target = T;
121
122 fn deref(&self) -> &T {
123 ::once_cell::unsync::Lazy::force(&self.0 .0)
124 }
125}
126
127#[cfg(not(target_feature = "atomics"))]
128pub use LazyCell as LazyLock;
129
130#[cfg(target_feature = "atomics")]
131pub struct LazyLock<T, F = fn() -> T> {
132 state: AtomicU8,
133 data: UnsafeCell<Data<T, F>>,
134}
135
136#[cfg(target_feature = "atomics")]
137enum Data<T, F> {
138 Value(T),
139 Init(F),
140}
141
142#[cfg(target_feature = "atomics")]
143impl<T, F> LazyLock<T, F> {
144 const STATE_UNINIT: u8 = 0;
145 const STATE_INITIALIZING: u8 = 1;
146 const STATE_INIT: u8 = 2;
147
148 pub const fn new(init: F) -> LazyLock<T, F> {
149 Self {
150 state: AtomicU8::new(Self::STATE_UNINIT),
151 data: UnsafeCell::new(Data::Init(init)),
152 }
153 }
154}
155
156#[cfg(target_feature = "atomics")]
157impl<T> Deref for LazyLock<T> {
158 type Target = T;
159
160 fn deref(&self) -> &T {
161 let mut state = self.state.load(Ordering::Acquire);
162
163 loop {
164 match state {
165 Self::STATE_INIT => {
166 let Data::Value(value) = (unsafe { &*self.data.get() }) else {
167 unreachable!()
168 };
169 return value;
170 }
171 Self::STATE_UNINIT => {
172 if let Err(new_state) = self.state.compare_exchange_weak(
173 Self::STATE_UNINIT,
174 Self::STATE_INITIALIZING,
175 Ordering::Acquire,
176 Ordering::Relaxed,
177 ) {
178 state = new_state;
179 continue;
180 }
181
182 let data = unsafe { &mut *self.data.get() };
183 let Data::Init(init) = data else {
184 unreachable!()
185 };
186 *data = Data::Value(init());
187 self.state.store(Self::STATE_INIT, Ordering::Release);
188 state = Self::STATE_INIT;
189 }
190 Self::STATE_INITIALIZING => {
191 state = self.state.load(Ordering::Acquire);
194 }
195 _ => unreachable!(),
196 }
197 }
198 }
199}
200
201#[cfg(target_feature = "atomics")]
202unsafe impl<T, F: Sync> Sync for LazyLock<T, F> {}
203
204#[cfg(target_feature = "atomics")]
205unsafe impl<T, F: Send> Send for LazyLock<T, F> {}
206
207#[macro_export]
208#[doc(hidden)]
209#[cfg(not(target_feature = "atomics"))]
210macro_rules! __wbindgen_thread_local {
211 ($wasm_bindgen:tt, $actual_ty:ty) => {{
212 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
213 $wasm_bindgen::__rt::LazyCell::new(init);
214 $wasm_bindgen::JsThreadLocal { __inner: &_VAL }
215 }};
216}
217
218#[macro_export]
219#[doc(hidden)]
220#[cfg(target_feature = "atomics")]
221#[allow_internal_unstable(thread_local)]
222macro_rules! __wbindgen_thread_local {
223 ($wasm_bindgen:tt, $actual_ty:ty) => {{
224 #[thread_local]
225 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
226 $wasm_bindgen::__rt::LazyCell::new(init);
227 $wasm_bindgen::JsThreadLocal {
228 __inner: || unsafe { $wasm_bindgen::__rt::LazyCell::force(&_VAL) as *const $actual_ty },
229 }
230 }};
231}
232
233#[macro_export]
234#[doc(hidden)]
235#[cfg(not(wasm_bindgen_unstable_test_coverage))]
236macro_rules! __wbindgen_coverage {
237 ($item:item) => {
238 $item
239 };
240}
241
242#[macro_export]
243#[doc(hidden)]
244#[cfg(wasm_bindgen_unstable_test_coverage)]
245#[allow_internal_unstable(coverage_attribute)]
246macro_rules! __wbindgen_coverage {
247 ($item:item) => {
248 #[coverage(off)]
249 $item
250 };
251}
252
253#[inline]
254pub fn assert_not_null<T>(s: *mut T) {
255 if s.is_null() {
256 throw_null();
257 }
258}
259
260#[cold]
261#[inline(never)]
262fn throw_null() -> ! {
263 super::throw_str("null pointer passed to rust");
264}
265
266pub struct WasmRefCell<T: ?Sized> {
284 borrow: Cell<usize>,
285 value: UnsafeCell<T>,
286}
287
288impl<T: ?Sized> WasmRefCell<T> {
289 pub fn new(value: T) -> WasmRefCell<T>
290 where
291 T: Sized,
292 {
293 WasmRefCell {
294 value: UnsafeCell::new(value),
295 borrow: Cell::new(0),
296 }
297 }
298
299 pub fn get_mut(&mut self) -> &mut T {
300 unsafe { &mut *self.value.get() }
301 }
302
303 pub fn borrow(&self) -> Ref<'_, T> {
304 unsafe {
305 if self.borrow.get() == usize::MAX {
306 borrow_fail();
307 }
308 self.borrow.set(self.borrow.get() + 1);
309 Ref {
310 value: &*self.value.get(),
311 borrow: &self.borrow,
312 }
313 }
314 }
315
316 pub fn borrow_mut(&self) -> RefMut<'_, T> {
317 unsafe {
318 if self.borrow.get() != 0 {
319 borrow_fail();
320 }
321 self.borrow.set(usize::MAX);
322 RefMut {
323 value: &mut *self.value.get(),
324 borrow: &self.borrow,
325 }
326 }
327 }
328
329 pub fn into_inner(self) -> T
330 where
331 T: Sized,
332 {
333 self.value.into_inner()
334 }
335}
336
337pub struct Ref<'b, T: ?Sized + 'b> {
338 value: &'b T,
339 borrow: &'b Cell<usize>,
340}
341
342impl<T: ?Sized> Deref for Ref<'_, T> {
343 type Target = T;
344
345 #[inline]
346 fn deref(&self) -> &T {
347 self.value
348 }
349}
350
351impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
352 #[inline]
353 fn borrow(&self) -> &T {
354 self.value
355 }
356}
357
358impl<T: ?Sized> Drop for Ref<'_, T> {
359 fn drop(&mut self) {
360 self.borrow.set(self.borrow.get() - 1);
361 }
362}
363
364pub struct RefMut<'b, T: ?Sized + 'b> {
365 value: &'b mut T,
366 borrow: &'b Cell<usize>,
367}
368
369impl<T: ?Sized> Deref for RefMut<'_, T> {
370 type Target = T;
371
372 #[inline]
373 fn deref(&self) -> &T {
374 self.value
375 }
376}
377
378impl<T: ?Sized> DerefMut for RefMut<'_, T> {
379 #[inline]
380 fn deref_mut(&mut self) -> &mut T {
381 self.value
382 }
383}
384
385impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
386 #[inline]
387 fn borrow(&self) -> &T {
388 self.value
389 }
390}
391
392impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
393 #[inline]
394 fn borrow_mut(&mut self) -> &mut T {
395 self.value
396 }
397}
398
399impl<T: ?Sized> Drop for RefMut<'_, T> {
400 fn drop(&mut self) {
401 self.borrow.set(0);
402 }
403}
404
405fn borrow_fail() -> ! {
406 super::throw_str(
407 "recursive use of an object detected which would lead to \
408 unsafe aliasing in rust",
409 );
410}
411
412pub struct RcRef<T: ?Sized + 'static> {
418 ref_: Ref<'static, T>,
427 _rc: Rc<WasmRefCell<T>>,
428}
429
430impl<T: ?Sized> RcRef<T> {
431 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
432 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow() };
433 Self { _rc: rc, ref_ }
434 }
435}
436
437impl<T: ?Sized> Deref for RcRef<T> {
438 type Target = T;
439
440 #[inline]
441 fn deref(&self) -> &T {
442 &self.ref_
443 }
444}
445
446impl<T: ?Sized> Borrow<T> for RcRef<T> {
447 #[inline]
448 fn borrow(&self) -> &T {
449 &self.ref_
450 }
451}
452
453pub struct RcRefMut<T: ?Sized + 'static> {
459 ref_: RefMut<'static, T>,
460 _rc: Rc<WasmRefCell<T>>,
461}
462
463impl<T: ?Sized> RcRefMut<T> {
464 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
465 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow_mut() };
466 Self { _rc: rc, ref_ }
467 }
468}
469
470impl<T: ?Sized> Deref for RcRefMut<T> {
471 type Target = T;
472
473 #[inline]
474 fn deref(&self) -> &T {
475 &self.ref_
476 }
477}
478
479impl<T: ?Sized> DerefMut for RcRefMut<T> {
480 #[inline]
481 fn deref_mut(&mut self) -> &mut T {
482 &mut self.ref_
483 }
484}
485
486impl<T: ?Sized> Borrow<T> for RcRefMut<T> {
487 #[inline]
488 fn borrow(&self) -> &T {
489 &self.ref_
490 }
491}
492
493impl<T: ?Sized> BorrowMut<T> for RcRefMut<T> {
494 #[inline]
495 fn borrow_mut(&mut self) -> &mut T {
496 &mut self.ref_
497 }
498}
499
500#[no_mangle]
501pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 {
502 if let Ok(layout) = Layout::from_size_align(size, align) {
503 unsafe {
504 if layout.size() > 0 {
505 let ptr = alloc(layout);
506 if !ptr.is_null() {
507 return ptr;
508 }
509 } else {
510 return align as *mut u8;
511 }
512 }
513 }
514
515 malloc_failure();
516}
517
518#[no_mangle]
519pub unsafe extern "C" fn __wbindgen_realloc(
520 ptr: *mut u8,
521 old_size: usize,
522 new_size: usize,
523 align: usize,
524) -> *mut u8 {
525 debug_assert!(old_size > 0);
526 debug_assert!(new_size > 0);
527 if let Ok(layout) = Layout::from_size_align(old_size, align) {
528 let ptr = realloc(ptr, layout, new_size);
529 if !ptr.is_null() {
530 return ptr;
531 }
532 }
533 malloc_failure();
534}
535
536#[cold]
537fn malloc_failure() -> ! {
538 cfg_if::cfg_if! {
539 if #[cfg(debug_assertions)] {
540 super::throw_str("invalid malloc request")
541 } else if #[cfg(feature = "std")] {
542 std::process::abort();
543 } else if #[cfg(all(
544 target_arch = "wasm32",
545 any(target_os = "unknown", target_os = "none")
546 ))] {
547 core::arch::wasm32::unreachable();
548 } else {
549 unreachable!()
550 }
551 }
552}
553
554#[no_mangle]
555pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) {
556 if size == 0 {
559 return;
560 }
561 let layout = Layout::from_size_align_unchecked(size, align);
562 dealloc(ptr, layout);
563}
564
565#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
599pub fn link_mem_intrinsics() {
600 crate::link::link_intrinsics();
601}
602
603#[cfg_attr(target_feature = "atomics", thread_local)]
604static GLOBAL_EXNDATA: ThreadLocalWrapper<Cell<[u32; 2]>> = ThreadLocalWrapper(Cell::new([0; 2]));
605
606#[no_mangle]
607pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
608 debug_assert_eq!(GLOBAL_EXNDATA.0.get()[0], 0);
609 GLOBAL_EXNDATA.0.set([1, idx]);
610}
611
612pub fn take_last_exception() -> Result<(), super::JsValue> {
613 let ret = if GLOBAL_EXNDATA.0.get()[0] == 1 {
614 Err(super::JsValue::_new(GLOBAL_EXNDATA.0.get()[1]))
615 } else {
616 Ok(())
617 };
618 GLOBAL_EXNDATA.0.set([0, 0]);
619 ret
620}
621
622pub trait IntoJsResult {
627 fn into_js_result(self) -> Result<JsValue, JsValue>;
628}
629
630impl IntoJsResult for () {
631 fn into_js_result(self) -> Result<JsValue, JsValue> {
632 Ok(JsValue::undefined())
633 }
634}
635
636impl<T: Into<JsValue>> IntoJsResult for T {
637 fn into_js_result(self) -> Result<JsValue, JsValue> {
638 Ok(self.into())
639 }
640}
641
642impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> {
643 fn into_js_result(self) -> Result<JsValue, JsValue> {
644 match self {
645 Ok(e) => Ok(e.into()),
646 Err(e) => Err(e.into()),
647 }
648 }
649}
650
651impl<E: Into<JsValue>> IntoJsResult for Result<(), E> {
652 fn into_js_result(self) -> Result<JsValue, JsValue> {
653 match self {
654 Ok(()) => Ok(JsValue::undefined()),
655 Err(e) => Err(e.into()),
656 }
657 }
658}
659
660pub trait Start {
663 fn start(self);
664}
665
666impl Start for () {
667 #[inline]
668 fn start(self) {}
669}
670
671impl<E: Into<JsValue>> Start for Result<(), E> {
672 #[inline]
673 fn start(self) {
674 if let Err(e) = self {
675 crate::throw_val(e.into());
676 }
677 }
678}
679
680pub struct MainWrapper<T>(pub Option<T>);
683
684pub trait Main {
685 fn __wasm_bindgen_main(&mut self);
686}
687
688impl Main for &mut &mut MainWrapper<()> {
689 #[inline]
690 fn __wasm_bindgen_main(&mut self) {}
691}
692
693impl Main for &mut &mut MainWrapper<Infallible> {
694 #[inline]
695 fn __wasm_bindgen_main(&mut self) {}
696}
697
698impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> {
699 #[inline]
700 fn __wasm_bindgen_main(&mut self) {
701 if let Err(e) = self.0.take().unwrap() {
702 crate::throw_val(e.into());
703 }
704 }
705}
706
707impl<E: core::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
708 #[inline]
709 fn __wasm_bindgen_main(&mut self) {
710 if let Err(e) = self.0.take().unwrap() {
711 crate::throw_str(&alloc::format!("{:?}", e));
712 }
713 }
714}
715
716pub const fn flat_len<T, const SIZE: usize>(slices: [&[T]; SIZE]) -> usize {
717 let mut len = 0;
718 let mut i = 0;
719 while i < slices.len() {
720 len += slices[i].len();
721 i += 1;
722 }
723 len
724}
725
726pub const fn flat_byte_slices<const RESULT_LEN: usize, const SIZE: usize>(
727 slices: [&[u8]; SIZE],
728) -> [u8; RESULT_LEN] {
729 let mut result = [0; RESULT_LEN];
730
731 let mut slice_index = 0;
732 let mut result_offset = 0;
733
734 while slice_index < slices.len() {
735 let mut i = 0;
736 let slice = slices[slice_index];
737 while i < slice.len() {
738 result[result_offset] = slice[i];
739 i += 1;
740 result_offset += 1;
741 }
742 slice_index += 1;
743 }
744
745 result
746}
747
748pub const fn encode_u32_to_fixed_len_bytes(value: u32) -> [u8; 5] {
752 let mut result: [u8; 5] = [0; 5];
753 let mut i = 0;
754 while i < 4 {
755 result[i] = ((value >> (7 * i)) | 0x80) as u8;
756 i += 1;
757 }
758 result[4] = (value >> (7 * 4)) as u8;
759 result
760}