use crate::convert::{FromWasmAbi, IntoWasmAbi, WasmAbi, WasmRet};
use crate::describe::inform;
use crate::JsValue;
#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
use core::any::Any;
use core::borrow::{Borrow, BorrowMut};
#[cfg(target_feature = "atomics")]
use core::cell::UnsafeCell;
use core::cell::{Cell, RefCell};
use core::convert::Infallible;
use core::ops::{Deref, DerefMut};
use core::panic::{RefUnwindSafe, UnwindSafe};
#[cfg(target_feature = "atomics")]
use core::sync::atomic::{AtomicU8, Ordering};
use wasm_bindgen_shared::tys::FUNCTION;
use alloc::alloc::{alloc, dealloc, realloc, Layout};
use alloc::rc::Rc;
use once_cell::unsync::Lazy;
pub extern crate alloc;
pub extern crate core;
#[cfg(feature = "std")]
pub extern crate std;
pub mod marker;
pub use wasm_bindgen_macro::BindgenedStruct;
pub fn js_panic(err: JsValue) {
#[cfg(all(feature = "std", not(target_feature = "atomics")))]
::std::panic::panic_any(err);
#[cfg(not(all(feature = "std", not(target_feature = "atomics"))))]
::core::panic!("{:?}", err);
}
pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
#[inline(never)]
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
unsafe extern "C" fn breaks_if_inlined<From: IntoWasmAbi, To: FromWasmAbi>(
prim1: <From::Abi as WasmAbi>::Prim1,
prim2: <From::Abi as WasmAbi>::Prim2,
prim3: <From::Abi as WasmAbi>::Prim3,
prim4: <From::Abi as WasmAbi>::Prim4,
) -> WasmRet<To::Abi> {
inform(FUNCTION);
inform(0);
inform(1);
From::describe();
To::describe();
To::describe();
core::ptr::read(super::__wbindgen_describe_cast(
breaks_if_inlined::<From, To> as _,
&(prim1, prim2, prim3, prim4) as *const _ as _,
) as _)
}
let (prim1, prim2, prim3, prim4) = value.into_abi().split();
unsafe { To::from_abi(breaks_if_inlined::<From, To>(prim1, prim2, prim3, prim4).join()) }
}
pub(crate) const JSIDX_OFFSET: u32 = 1024; pub(crate) const JSIDX_UNDEFINED: u32 = JSIDX_OFFSET;
pub(crate) const JSIDX_NULL: u32 = JSIDX_OFFSET + 1;
pub(crate) const JSIDX_TRUE: u32 = JSIDX_OFFSET + 2;
pub(crate) const JSIDX_FALSE: u32 = JSIDX_OFFSET + 3;
pub(crate) const JSIDX_RESERVED: u32 = JSIDX_OFFSET + 4;
pub(crate) struct ThreadLocalWrapper<T>(pub(crate) T);
#[cfg(not(target_feature = "atomics"))]
unsafe impl<T> Sync for ThreadLocalWrapper<T> {}
#[cfg(not(target_feature = "atomics"))]
unsafe impl<T> Send for ThreadLocalWrapper<T> {}
pub struct LazyCell<T, F = fn() -> T>(ThreadLocalWrapper<Lazy<T, F>>);
impl<T, F> LazyCell<T, F> {
pub const fn new(init: F) -> LazyCell<T, F> {
Self(ThreadLocalWrapper(Lazy::new(init)))
}
}
impl<T, F: FnOnce() -> T> LazyCell<T, F> {
pub fn force(this: &Self) -> &T {
&this.0 .0
}
}
impl<T> Deref for LazyCell<T> {
type Target = T;
fn deref(&self) -> &T {
::once_cell::unsync::Lazy::force(&self.0 .0)
}
}
#[cfg(not(target_feature = "atomics"))]
pub use LazyCell as LazyLock;
#[cfg(target_feature = "atomics")]
pub struct LazyLock<T, F = fn() -> T> {
state: AtomicU8,
data: UnsafeCell<Data<T, F>>,
}
#[cfg(target_feature = "atomics")]
enum Data<T, F> {
Value(T),
Init(F),
}
#[cfg(target_feature = "atomics")]
impl<T, F> LazyLock<T, F> {
const STATE_UNINIT: u8 = 0;
const STATE_INITIALIZING: u8 = 1;
const STATE_INIT: u8 = 2;
pub const fn new(init: F) -> LazyLock<T, F> {
Self {
state: AtomicU8::new(Self::STATE_UNINIT),
data: UnsafeCell::new(Data::Init(init)),
}
}
}
#[cfg(target_feature = "atomics")]
impl<T> Deref for LazyLock<T> {
type Target = T;
fn deref(&self) -> &T {
let mut state = self.state.load(Ordering::Acquire);
loop {
match state {
Self::STATE_INIT => {
let Data::Value(value) = (unsafe { &*self.data.get() }) else {
unreachable!()
};
return value;
}
Self::STATE_UNINIT => {
if let Err(new_state) = self.state.compare_exchange_weak(
Self::STATE_UNINIT,
Self::STATE_INITIALIZING,
Ordering::Acquire,
Ordering::Relaxed,
) {
state = new_state;
continue;
}
let data = unsafe { &mut *self.data.get() };
let Data::Init(init) = data else {
unreachable!()
};
*data = Data::Value(init());
self.state.store(Self::STATE_INIT, Ordering::Release);
state = Self::STATE_INIT;
}
Self::STATE_INITIALIZING => {
state = self.state.load(Ordering::Acquire);
}
_ => unreachable!(),
}
}
}
}
#[cfg(target_feature = "atomics")]
unsafe impl<T, F: Sync> Sync for LazyLock<T, F> {}
#[cfg(target_feature = "atomics")]
unsafe impl<T, F: Send> Send for LazyLock<T, F> {}
#[macro_export]
#[doc(hidden)]
#[cfg(not(target_feature = "atomics"))]
macro_rules! __wbindgen_thread_local {
($wasm_bindgen:tt, $actual_ty:ty) => {{
static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
$wasm_bindgen::__rt::LazyCell::new(init);
$wasm_bindgen::JsThreadLocal { __inner: &_VAL }
}};
}
#[macro_export]
#[doc(hidden)]
#[cfg(target_feature = "atomics")]
#[allow_internal_unstable(thread_local)]
macro_rules! __wbindgen_thread_local {
($wasm_bindgen:tt, $actual_ty:ty) => {{
#[thread_local]
static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
$wasm_bindgen::__rt::LazyCell::new(init);
$wasm_bindgen::JsThreadLocal {
__inner: || unsafe { $wasm_bindgen::__rt::LazyCell::force(&_VAL) as *const $actual_ty },
}
}};
}
#[macro_export]
#[doc(hidden)]
#[cfg(not(wasm_bindgen_unstable_test_coverage))]
macro_rules! __wbindgen_coverage {
($item:item) => {
$item
};
}
#[macro_export]
#[doc(hidden)]
#[cfg(wasm_bindgen_unstable_test_coverage)]
#[allow_internal_unstable(coverage_attribute)]
macro_rules! __wbindgen_coverage {
($item:item) => {
#[coverage(off)]
$item
};
}
#[inline]
pub fn assert_not_null<T>(s: *mut T) {
if s.is_null() {
throw_null();
}
}
#[cold]
#[inline(never)]
fn throw_null() -> ! {
super::throw_str("null pointer passed to rust");
}
pub struct WasmRefCell<T: ?Sized> {
inner: RefCell<T>,
}
impl<T: ?Sized> UnwindSafe for WasmRefCell<T> {}
impl<T: ?Sized> RefUnwindSafe for WasmRefCell<T> {}
impl<T: ?Sized> WasmRefCell<T> {
pub fn new(value: T) -> WasmRefCell<T>
where
T: Sized,
{
WasmRefCell {
inner: RefCell::new(value),
}
}
pub fn get_mut(&mut self) -> &mut T {
self.inner.get_mut()
}
pub fn borrow(&self) -> Ref<'_, T> {
match self.inner.try_borrow() {
Ok(inner) => Ref { inner },
Err(_) => borrow_fail(),
}
}
pub fn borrow_mut(&self) -> RefMut<'_, T> {
match self.inner.try_borrow_mut() {
Ok(inner) => RefMut { inner },
Err(_) => borrow_fail(),
}
}
pub fn into_inner(self) -> T
where
T: Sized,
{
self.inner.into_inner()
}
}
pub struct Ref<'b, T: ?Sized + 'b> {
inner: core::cell::Ref<'b, T>,
}
impl<T: ?Sized> Deref for Ref<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.inner
}
}
impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
#[inline]
fn borrow(&self) -> &T {
self
}
}
pub struct RefMut<'b, T: ?Sized + 'b> {
inner: core::cell::RefMut<'b, T>,
}
impl<T: ?Sized> Deref for RefMut<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.inner
}
}
impl<T: ?Sized> DerefMut for RefMut<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
&mut self.inner
}
}
impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
#[inline]
fn borrow(&self) -> &T {
self
}
}
impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self
}
}
#[cfg(panic = "unwind")]
fn borrow_fail() -> ! {
panic!(
"recursive use of an object detected which would lead to \
unsafe aliasing in rust",
)
}
#[cfg(not(panic = "unwind"))]
fn borrow_fail() -> ! {
super::throw_str(
"recursive use of an object detected which would lead to \
unsafe aliasing in rust",
);
}
pub struct RcRef<T: ?Sized + 'static> {
ref_: Ref<'static, T>,
_rc: Rc<WasmRefCell<T>>,
}
impl<T: ?Sized> UnwindSafe for RcRef<T> {}
impl<T: ?Sized> RcRef<T> {
pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow() };
Self { _rc: rc, ref_ }
}
}
impl<T: ?Sized> Deref for RcRef<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.ref_
}
}
impl<T: ?Sized> Borrow<T> for RcRef<T> {
#[inline]
fn borrow(&self) -> &T {
&self.ref_
}
}
pub struct RcRefMut<T: ?Sized + 'static> {
ref_: RefMut<'static, T>,
_rc: Rc<WasmRefCell<T>>,
}
impl<T: ?Sized> RcRefMut<T> {
pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow_mut() };
Self { _rc: rc, ref_ }
}
}
impl<T: ?Sized> Deref for RcRefMut<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.ref_
}
}
impl<T: ?Sized> DerefMut for RcRefMut<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
&mut self.ref_
}
}
impl<T: ?Sized> Borrow<T> for RcRefMut<T> {
#[inline]
fn borrow(&self) -> &T {
&self.ref_
}
}
impl<T: ?Sized> BorrowMut<T> for RcRefMut<T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
&mut self.ref_
}
}
#[no_mangle]
pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 {
if let Ok(layout) = Layout::from_size_align(size, align) {
unsafe {
if layout.size() > 0 {
let ptr = alloc(layout);
if !ptr.is_null() {
return ptr;
}
} else {
return align as *mut u8;
}
}
}
malloc_failure();
}
#[no_mangle]
pub unsafe extern "C" fn __wbindgen_realloc(
ptr: *mut u8,
old_size: usize,
new_size: usize,
align: usize,
) -> *mut u8 {
debug_assert!(old_size > 0);
debug_assert!(new_size > 0);
if let Ok(layout) = Layout::from_size_align(old_size, align) {
let ptr = realloc(ptr, layout, new_size);
if !ptr.is_null() {
return ptr;
}
}
malloc_failure();
}
#[cold]
fn malloc_failure() -> ! {
cfg_if::cfg_if! {
if #[cfg(debug_assertions)] {
super::throw_str("invalid malloc request")
} else if #[cfg(feature = "std")] {
std::process::abort();
} else if #[cfg(all(
target_arch = "wasm32",
any(target_os = "unknown", target_os = "none")
))] {
core::arch::wasm32::unreachable();
} else {
unreachable!()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) {
if size == 0 {
return;
}
let layout = Layout::from_size_align_unchecked(size, align);
dealloc(ptr, layout);
}
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
pub fn link_mem_intrinsics() {
crate::link::link_intrinsics();
}
#[cfg_attr(target_feature = "atomics", thread_local)]
static GLOBAL_EXNDATA: ThreadLocalWrapper<Cell<[u32; 2]>> = ThreadLocalWrapper(Cell::new([0; 2]));
#[cfg(panic = "unwind")]
#[no_mangle]
pub static mut __instance_terminated: u32 = 0;
#[cfg(panic = "unwind")]
#[no_mangle]
pub static mut __abort_handler: u32 = 0;
#[cfg(panic = "unwind")]
pub fn set_on_abort(f: fn()) -> Option<fn()> {
unsafe {
let prev = __abort_handler;
__abort_handler = f as usize as u32;
if prev != 0 {
Some(core::mem::transmute::<usize, fn()>(prev as usize))
} else {
None
}
}
}
#[cfg(not(panic = "unwind"))]
pub fn set_on_abort(_f: fn()) -> Option<fn()> {
None
}
pub fn schedule_reinit() {
crate::__wbindgen_reinit();
}
#[no_mangle]
pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
debug_assert_eq!(GLOBAL_EXNDATA.0.get()[0], 0);
GLOBAL_EXNDATA.0.set([1, idx]);
}
pub fn take_last_exception() -> Result<(), super::JsValue> {
let ret = if GLOBAL_EXNDATA.0.get()[0] == 1 {
Err(super::JsValue::_new(GLOBAL_EXNDATA.0.get()[1]))
} else {
Ok(())
};
GLOBAL_EXNDATA.0.set([0, 0]);
ret
}
pub trait IntoJsResult {
fn into_js_result(self) -> Result<JsValue, JsValue>;
}
impl IntoJsResult for () {
fn into_js_result(self) -> Result<JsValue, JsValue> {
Ok(JsValue::undefined())
}
}
impl<T: Into<JsValue>> IntoJsResult for T {
fn into_js_result(self) -> Result<JsValue, JsValue> {
Ok(self.into())
}
}
impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> {
fn into_js_result(self) -> Result<JsValue, JsValue> {
match self {
Ok(e) => Ok(e.into()),
Err(e) => Err(e.into()),
}
}
}
impl<E: Into<JsValue>> IntoJsResult for Result<(), E> {
fn into_js_result(self) -> Result<JsValue, JsValue> {
match self {
Ok(()) => Ok(JsValue::undefined()),
Err(e) => Err(e.into()),
}
}
}
pub trait Start {
fn start(self);
}
impl Start for () {
#[inline]
fn start(self) {}
}
impl<E: Into<JsValue>> Start for Result<(), E> {
#[inline]
fn start(self) {
if let Err(e) = self {
crate::throw_val(e.into());
}
}
}
pub struct MainWrapper<T>(pub Option<T>);
pub trait Main {
fn __wasm_bindgen_main(&mut self);
}
impl Main for &mut &mut MainWrapper<()> {
#[inline]
fn __wasm_bindgen_main(&mut self) {}
}
impl Main for &mut &mut MainWrapper<Infallible> {
#[inline]
fn __wasm_bindgen_main(&mut self) {}
}
impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> {
#[inline]
fn __wasm_bindgen_main(&mut self) {
if let Err(e) = self.0.take().unwrap() {
crate::throw_val(e.into());
}
}
}
impl<E: core::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
#[inline]
fn __wasm_bindgen_main(&mut self) {
if let Err(e) = self.0.take().unwrap() {
crate::throw_str(&alloc::format!("{e:?}"));
}
}
}
pub const fn flat_len<T, const SIZE: usize>(slices: [&[T]; SIZE]) -> usize {
let mut len = 0;
let mut i = 0;
while i < slices.len() {
len += slices[i].len();
i += 1;
}
len
}
pub const fn flat_byte_slices<const RESULT_LEN: usize, const SIZE: usize>(
slices: [&[u8]; SIZE],
) -> [u8; RESULT_LEN] {
let mut result = [0; RESULT_LEN];
let mut slice_index = 0;
let mut result_offset = 0;
while slice_index < slices.len() {
let mut i = 0;
let slice = slices[slice_index];
while i < slice.len() {
result[result_offset] = slice[i];
i += 1;
result_offset += 1;
}
slice_index += 1;
}
result
}
pub const fn encode_u32_to_fixed_len_bytes(value: u32) -> [u8; 5] {
let mut result: [u8; 5] = [0; 5];
let mut i = 0;
while i < 4 {
result[i] = ((value >> (7 * i)) | 0x80) as u8;
i += 1;
}
result[4] = (value >> (7 * 4)) as u8;
result
}
#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
#[wasm_bindgen_macro::wasm_bindgen(wasm_bindgen = crate, raw_module = "__wbindgen_placeholder__")]
extern "C" {
fn __wbindgen_panic_error(msg: &JsValue) -> JsValue;
}
#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
pub fn panic_to_panic_error(val: std::boxed::Box<dyn Any + Send>) -> JsValue {
#[cfg(not(target_feature = "atomics"))]
{
if let Some(s) = val.downcast_ref::<JsValue>() {
return __wbindgen_panic_error(&s);
}
}
let maybe_panic_msg: Option<&str> = if let Some(s) = val.downcast_ref::<&str>() {
Some(s)
} else if let Some(s) = val.downcast_ref::<std::string::String>() {
Some(s)
} else {
None
};
let err: JsValue = __wbindgen_panic_error(&JsValue::from_str(
maybe_panic_msg.unwrap_or("No panic message available"),
));
err
}
#[cfg(all(target_arch = "wasm32", feature = "std", panic = "unwind"))]
pub fn maybe_catch_unwind<F: FnOnce() -> R + std::panic::UnwindSafe, R>(f: F) -> R {
let result = std::panic::catch_unwind(f);
match result {
Ok(val) => val,
Err(e) => {
crate::throw_val(panic_to_panic_error(e));
}
}
}
#[cfg(not(all(target_arch = "wasm32", feature = "std", panic = "unwind")))]
pub fn maybe_catch_unwind<F: FnOnce() -> R, R>(f: F) -> R {
f()
}