Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

103
vendor/wasm-bindgen/src/cache/intern.rs vendored Normal file
View File

@@ -0,0 +1,103 @@
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "enable-interning")] {
use std::thread_local;
use std::string::String;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::collections::HashMap;
use crate::JsValue;
struct Cache {
entries: RefCell<HashMap<String, JsValue>>,
}
thread_local! {
static CACHE: Cache = Cache {
entries: RefCell::new(HashMap::new()),
};
}
/// This returns the raw index of the cached JsValue, so you must take care
/// so that you don't use it after it is freed.
pub(crate) fn unsafe_get_str(s: &str) -> Option<u32> {
CACHE.with(|cache| {
let cache = cache.entries.borrow();
cache.get(s).map(|x| x.idx)
})
}
fn intern_str(key: &str) {
CACHE.with(|cache| {
let entries = &cache.entries;
// Can't use `entry` because `entry` requires a `String`
if !entries.borrow().contains_key(key) {
// Note: we must not hold the borrow while we create the `JsValue`,
// because it will try to look up the value in the cache first.
let value = JsValue::from(key);
entries.borrow_mut().insert(key.to_owned(), value);
}
})
}
fn unintern_str(key: &str) {
CACHE.with(|cache| {
let mut cache = cache.entries.borrow_mut();
cache.remove(key);
})
}
}
}
/// Interns Rust strings so that it's much faster to send them to JS.
///
/// Sending strings from Rust to JS is slow, because it has to do a full `O(n)`
/// copy and *also* encode from UTF-8 to UTF-16. This must be done every single
/// time a string is sent to JS.
///
/// If you are sending the same string multiple times, you can call this `intern`
/// function, which simply returns its argument unchanged:
///
/// ```rust
/// # use wasm_bindgen::intern;
/// intern("foo") // returns "foo"
/// # ;
/// ```
///
/// However, if you enable the `"enable-interning"` feature for wasm-bindgen,
/// then it will add the string into an internal cache.
///
/// When you send that cached string to JS, it will look it up in the cache,
/// which completely avoids the `O(n)` copy and encoding. This has a significant
/// speed boost (as high as 783%)!
///
/// However, there is a small cost to this caching, so you shouldn't cache every
/// string. Only cache strings which have a high likelihood of being sent
/// to JS multiple times.
///
/// Also, keep in mind that this function is a *performance hint*: it's not
/// *guaranteed* that the string will be cached, and the caching strategy
/// might change at any time, so don't rely upon it.
#[inline]
pub fn intern(s: &str) -> &str {
#[cfg(feature = "enable-interning")]
intern_str(s);
s
}
/// Removes a Rust string from the intern cache.
///
/// This does the opposite of the [`intern`](fn.intern.html) function.
///
/// If the [`intern`](fn.intern.html) function is called again then it will re-intern the string.
#[allow(unused_variables)]
#[inline]
pub fn unintern(s: &str) {
#[cfg(feature = "enable-interning")]
unintern_str(s);
}

1
vendor/wasm-bindgen/src/cache/mod.rs vendored Normal file
View File

@@ -0,0 +1 @@
pub mod intern;

156
vendor/wasm-bindgen/src/cast.rs vendored Normal file
View File

@@ -0,0 +1,156 @@
use crate::JsValue;
/// A trait for checked and unchecked casting between JS types.
///
/// Specified [in an RFC][rfc] this trait is intended to provide support for
/// casting JS values between different types of one another. In JS there aren't
/// many static types but we've ascribed JS values with static types in Rust,
/// yet they often need to be switched to other types temporarily! This trait
/// provides both checked and unchecked casting into various kinds of values.
///
/// This trait is automatically implemented for any type imported in a
/// `#[wasm_bindgen]` `extern` block.
///
/// [rfc]: https://github.com/rustwasm/rfcs/blob/master/text/002-wasm-bindgen-inheritance-casting.md
pub trait JsCast
where
Self: AsRef<JsValue> + Into<JsValue>,
{
/// Test whether this JS value has a type `T`.
///
/// This method will dynamically check to see if this JS object can be
/// casted to the JS object of type `T`. Usually this uses the `instanceof`
/// operator. This also works with primitive types like
/// booleans/strings/numbers as well as cross-realm object like `Array`
/// which can originate from other iframes.
///
/// In general this is intended to be a more robust version of
/// `is_instance_of`, but if you want strictly the `instanceof` operator
/// it's recommended to use that instead.
fn has_type<T>(&self) -> bool
where
T: JsCast,
{
T::is_type_of(self.as_ref())
}
/// Performs a dynamic cast (checked at runtime) of this value into the
/// target type `T`.
///
/// This method will return `Err(self)` if `self.has_type::<T>()`
/// returns `false`, and otherwise it will return `Ok(T)` manufactured with
/// an unchecked cast (verified correct via the `has_type` operation).
fn dyn_into<T>(self) -> Result<T, Self>
where
T: JsCast,
{
if self.has_type::<T>() {
Ok(self.unchecked_into())
} else {
Err(self)
}
}
/// Performs a dynamic cast (checked at runtime) of this value into the
/// target type `T`.
///
/// This method will return `None` if `self.has_type::<T>()`
/// returns `false`, and otherwise it will return `Some(&T)` manufactured
/// with an unchecked cast (verified correct via the `has_type` operation).
fn dyn_ref<T>(&self) -> Option<&T>
where
T: JsCast,
{
if self.has_type::<T>() {
Some(self.unchecked_ref())
} else {
None
}
}
/// Performs a zero-cost unchecked cast into the specified type.
///
/// This method will convert the `self` value to the type `T`, where both
/// `self` and `T` are simple wrappers around `JsValue`. This method **does
/// not check whether `self` is an instance of `T`**. If used incorrectly
/// then this method may cause runtime exceptions in both Rust and JS, this
/// should be used with caution.
fn unchecked_into<T>(self) -> T
where
T: JsCast,
{
T::unchecked_from_js(self.into())
}
/// Performs a zero-cost unchecked cast into a reference to the specified
/// type.
///
/// This method will convert the `self` value to the type `T`, where both
/// `self` and `T` are simple wrappers around `JsValue`. This method **does
/// not check whether `self` is an instance of `T`**. If used incorrectly
/// then this method may cause runtime exceptions in both Rust and JS, this
/// should be used with caution.
///
/// This method, unlike `unchecked_into`, does not consume ownership of
/// `self` and instead works over a shared reference.
fn unchecked_ref<T>(&self) -> &T
where
T: JsCast,
{
T::unchecked_from_js_ref(self.as_ref())
}
/// Test whether this JS value is an instance of the type `T`.
///
/// This method performs a dynamic check (at runtime) using the JS
/// `instanceof` operator. This method returns `self instanceof T`.
///
/// Note that `instanceof` does not always work with primitive values or
/// across different realms (e.g. iframes). If you're not sure whether you
/// specifically need only `instanceof` it's recommended to use `has_type`
/// instead.
fn is_instance_of<T>(&self) -> bool
where
T: JsCast,
{
T::instanceof(self.as_ref())
}
/// Performs a dynamic `instanceof` check to see whether the `JsValue`
/// provided is an instance of this type.
///
/// This is intended to be an internal implementation detail, you likely
/// won't need to call this. It's generally called through the
/// `is_instance_of` method instead.
fn instanceof(val: &JsValue) -> bool;
/// Performs a dynamic check to see whether the `JsValue` provided
/// is a value of this type.
///
/// Unlike `instanceof`, this can be specialised to use a custom check by
/// adding a `#[wasm_bindgen(is_type_of = callback)]` attribute to the
/// type import declaration.
///
/// Other than that, this is intended to be an internal implementation
/// detail of `has_type` and you likely won't need to call this.
fn is_type_of(val: &JsValue) -> bool {
Self::instanceof(val)
}
/// Performs a zero-cost unchecked conversion from a `JsValue` into an
/// instance of `Self`
///
/// This is intended to be an internal implementation detail, you likely
/// won't need to call this.
fn unchecked_from_js(val: JsValue) -> Self;
/// Performs a zero-cost unchecked conversion from a `&JsValue` into an
/// instance of `&Self`.
///
/// Note the safety of this method, which basically means that `Self` must
/// be a newtype wrapper around `JsValue`.
///
/// This is intended to be an internal implementation detail, you likely
/// won't need to call this.
fn unchecked_from_js_ref(val: &JsValue) -> &Self;
}

521
vendor/wasm-bindgen/src/closure.rs vendored Normal file
View File

@@ -0,0 +1,521 @@
//! Support for long-lived closures in `wasm-bindgen`
//!
//! This module defines the `Closure` type which is used to pass "owned
//! closures" from Rust to JS. Some more details can be found on the `Closure`
//! type itself.
#![allow(clippy::fn_to_numeric_cast)]
use alloc::boxed::Box;
use alloc::string::String;
use core::fmt;
use core::mem::{self, ManuallyDrop};
use crate::convert::*;
use crate::describe::*;
use crate::JsValue;
/// A handle to both a closure in Rust as well as JS closure which will invoke
/// the Rust closure.
///
/// A `Closure` is the primary way that a `'static` lifetime closure is
/// transferred from Rust to JS. `Closure` currently requires that the closures
/// it's created with have the `'static` lifetime in Rust for soundness reasons.
///
/// This type is a "handle" in the sense that whenever it is dropped it will
/// invalidate the JS closure that it refers to. Any usage of the closure in JS
/// after the `Closure` has been dropped will raise an exception. It's then up
/// to you to arrange for `Closure` to be properly deallocate at an appropriate
/// location in your program.
///
/// The type parameter on `Closure` is the type of closure that this represents.
/// Currently this can only be the `Fn` and `FnMut` traits with up to 7
/// arguments (and an optional return value).
///
/// # Examples
///
/// Here are a number of examples of using `Closure`.
///
/// ## Using the `setInterval` API
///
/// Sample usage of `Closure` to invoke the `setInterval` API.
///
/// ```rust,no_run
/// use wasm_bindgen::prelude::*;
///
/// #[wasm_bindgen]
/// extern "C" {
/// fn setInterval(closure: &Closure<dyn FnMut()>, time: u32) -> i32;
/// fn clearInterval(id: i32);
///
/// #[wasm_bindgen(js_namespace = console)]
/// fn log(s: &str);
/// }
///
/// #[wasm_bindgen]
/// pub struct IntervalHandle {
/// interval_id: i32,
/// _closure: Closure<dyn FnMut()>,
/// }
///
/// impl Drop for IntervalHandle {
/// fn drop(&mut self) {
/// clearInterval(self.interval_id);
/// }
/// }
///
/// #[wasm_bindgen]
/// pub fn run() -> IntervalHandle {
/// // First up we use `Closure::new` to wrap up a Rust closure and create
/// // a JS closure.
/// let cb = Closure::new(|| {
/// log("interval elapsed!");
/// });
///
/// // Next we pass this via reference to the `setInterval` function, and
/// // `setInterval` gets a handle to the corresponding JS closure.
/// let interval_id = setInterval(&cb, 1_000);
///
/// // If we were to drop `cb` here it would cause an exception to be raised
/// // whenever the interval elapses. Instead we *return* our handle back to JS
/// // so JS can decide when to cancel the interval and deallocate the closure.
/// IntervalHandle {
/// interval_id,
/// _closure: cb,
/// }
/// }
/// ```
///
/// ## Casting a `Closure` to a `js_sys::Function`
///
/// This is the same `setInterval` example as above, except it is using
/// `web_sys` (which uses `js_sys::Function` for callbacks) instead of manually
/// writing bindings to `setInterval` and other Web APIs.
///
/// ```rust,ignore
/// use wasm_bindgen::JsCast;
///
/// #[wasm_bindgen]
/// pub struct IntervalHandle {
/// interval_id: i32,
/// _closure: Closure<dyn FnMut()>,
/// }
///
/// impl Drop for IntervalHandle {
/// fn drop(&mut self) {
/// let window = web_sys::window().unwrap();
/// window.clear_interval_with_handle(self.interval_id);
/// }
/// }
///
/// #[wasm_bindgen]
/// pub fn run() -> Result<IntervalHandle, JsValue> {
/// let cb = Closure::new(|| {
/// web_sys::console::log_1(&"interval elapsed!".into());
/// });
///
/// let window = web_sys::window().unwrap();
/// let interval_id = window.set_interval_with_callback_and_timeout_and_arguments_0(
/// // Note this method call, which uses `as_ref()` to get a `JsValue`
/// // from our `Closure` which is then converted to a `&Function`
/// // using the `JsCast::unchecked_ref` function.
/// cb.as_ref().unchecked_ref(),
/// 1_000,
/// )?;
///
/// // Same as above.
/// Ok(IntervalHandle {
/// interval_id,
/// _closure: cb,
/// })
/// }
/// ```
///
/// ## Using `FnOnce` and `Closure::once` with `requestAnimationFrame`
///
/// Because `requestAnimationFrame` only calls its callback once, we can use
/// `FnOnce` and `Closure::once` with it.
///
/// ```rust,no_run
/// use wasm_bindgen::prelude::*;
///
/// #[wasm_bindgen]
/// extern "C" {
/// fn requestAnimationFrame(closure: &Closure<dyn FnMut()>) -> u32;
/// fn cancelAnimationFrame(id: u32);
///
/// #[wasm_bindgen(js_namespace = console)]
/// fn log(s: &str);
/// }
///
/// #[wasm_bindgen]
/// pub struct AnimationFrameHandle {
/// animation_id: u32,
/// _closure: Closure<dyn FnMut()>,
/// }
///
/// impl Drop for AnimationFrameHandle {
/// fn drop(&mut self) {
/// cancelAnimationFrame(self.animation_id);
/// }
/// }
///
/// // A type that will log a message when it is dropped.
/// struct LogOnDrop(&'static str);
/// impl Drop for LogOnDrop {
/// fn drop(&mut self) {
/// log(self.0);
/// }
/// }
///
/// #[wasm_bindgen]
/// pub fn run() -> AnimationFrameHandle {
/// // We are using `Closure::once` which takes a `FnOnce`, so the function
/// // can drop and/or move things that it closes over.
/// let fired = LogOnDrop("animation frame fired or canceled");
/// let cb = Closure::once(move || drop(fired));
///
/// // Schedule the animation frame!
/// let animation_id = requestAnimationFrame(&cb);
///
/// // Again, return a handle to JS, so that the closure is not dropped
/// // immediately and JS can decide whether to cancel the animation frame.
/// AnimationFrameHandle {
/// animation_id,
/// _closure: cb,
/// }
/// }
/// ```
///
/// ## Converting `FnOnce`s directly into JavaScript Functions with `Closure::once_into_js`
///
/// If we don't want to allow a `FnOnce` to be eagerly dropped (maybe because we
/// just want it to drop after it is called and don't care about cancellation)
/// then we can use the `Closure::once_into_js` function.
///
/// This is the same `requestAnimationFrame` example as above, but without
/// supporting early cancellation.
///
/// ```
/// use wasm_bindgen::prelude::*;
///
/// #[wasm_bindgen]
/// extern "C" {
/// // We modify the binding to take an untyped `JsValue` since that is what
/// // is returned by `Closure::once_into_js`.
/// //
/// // If we were using the `web_sys` binding for `requestAnimationFrame`,
/// // then the call sites would cast the `JsValue` into a `&js_sys::Function`
/// // using `f.unchecked_ref::<js_sys::Function>()`. See the `web_sys`
/// // example above for details.
/// fn requestAnimationFrame(callback: JsValue);
///
/// #[wasm_bindgen(js_namespace = console)]
/// fn log(s: &str);
/// }
///
/// // A type that will log a message when it is dropped.
/// struct LogOnDrop(&'static str);
/// impl Drop for LogOnDrop {
/// fn drop(&mut self) {
/// log(self.0);
/// }
/// }
///
/// #[wasm_bindgen]
/// pub fn run() {
/// // We are using `Closure::once_into_js` which takes a `FnOnce` and
/// // converts it into a JavaScript function, which is returned as a
/// // `JsValue`.
/// let fired = LogOnDrop("animation frame fired");
/// let cb = Closure::once_into_js(move || drop(fired));
///
/// // Schedule the animation frame!
/// requestAnimationFrame(cb);
///
/// // No need to worry about whether or not we drop a `Closure`
/// // here or return some sort of handle to JS!
/// }
/// ```
pub struct Closure<T: ?Sized> {
js: ManuallyDrop<JsValue>,
data: OwnedClosure<T>,
}
impl<T> Closure<T>
where
T: ?Sized + WasmClosure,
{
/// Creates a new instance of `Closure` from the provided Rust function.
///
/// Note that the closure provided here, `F`, has a few requirements
/// associated with it:
///
/// * It must implement `Fn` or `FnMut` (for `FnOnce` functions see
/// `Closure::once` and `Closure::once_into_js`).
///
/// * It must be `'static`, aka no stack references (use the `move`
/// keyword).
///
/// * It can have at most 7 arguments.
///
/// * Its arguments and return values are all types that can be shared with
/// JS (i.e. have `#[wasm_bindgen]` annotations or are simple numbers,
/// etc.)
pub fn new<F>(t: F) -> Closure<T>
where
F: IntoWasmClosure<T> + 'static,
{
Closure::wrap(Box::new(t).unsize())
}
/// A more direct version of `Closure::new` which creates a `Closure` from
/// a `Box<dyn Fn>`/`Box<dyn FnMut>`, which is how it's kept internally.
pub fn wrap(data: Box<T>) -> Closure<T> {
let data = OwnedClosure {
inner: ManuallyDrop::new(data),
};
Self {
js: ManuallyDrop::new(crate::__rt::wbg_cast(&data)),
data,
}
}
/// Release memory management of this closure from Rust to the JS GC.
///
/// When a `Closure` is dropped it will release the Rust memory and
/// invalidate the associated JS closure, but this isn't always desired.
/// Some callbacks are alive for the entire duration of the program or for a
/// lifetime dynamically managed by the JS GC. This function can be used
/// to drop this `Closure` while keeping the associated JS function still
/// valid.
///
/// If the platform supports weak references, the Rust memory will be
/// reclaimed when the JS closure is GC'd. If weak references is not
/// supported, this can be dangerous if this function is called many times
/// in an application because the memory leak will overwhelm the page
/// quickly and crash the wasm.
pub fn into_js_value(self) -> JsValue {
let idx = self.js.idx;
mem::forget(self);
JsValue::_new(idx)
}
/// Same as `into_js_value`, but doesn't return a value.
pub fn forget(self) {
drop(self.into_js_value());
}
/// Create a `Closure` from a function that can only be called once.
///
/// Since we have no way of enforcing that JS cannot attempt to call this
/// `FnOne(A...) -> R` more than once, this produces a `Closure<dyn FnMut(A...)
/// -> R>` that will dynamically throw a JavaScript error if called more
/// than once.
///
/// # Example
///
/// ```rust,no_run
/// use wasm_bindgen::prelude::*;
///
/// // Create an non-`Copy`, owned `String`.
/// let mut s = String::from("Hello");
///
/// // Close over `s`. Since `f` returns `s`, it is `FnOnce` and can only be
/// // called once. If it was called a second time, it wouldn't have any `s`
/// // to work with anymore!
/// let f = move || {
/// s += ", World!";
/// s
/// };
///
/// // Create a `Closure` from `f`. Note that the `Closure`'s type parameter
/// // is `FnMut`, even though `f` is `FnOnce`.
/// let closure: Closure<dyn FnMut() -> String> = Closure::once(f);
/// ```
///
/// Note: the `A` and `R` type parameters are here just for backward compat
/// and will be removed in the future.
pub fn once<F, A, R>(fn_once: F) -> Self
where
F: WasmClosureFnOnce<T, A, R>,
{
Closure::wrap(fn_once.into_fn_mut())
}
/// Convert a `FnOnce(A...) -> R` into a JavaScript `Function` object.
///
/// If the JavaScript function is invoked more than once, it will throw an
/// exception.
///
/// Unlike `Closure::once`, this does *not* return a `Closure` that can be
/// dropped before the function is invoked to deallocate the closure. The
/// only way the `FnOnce` is deallocated is by calling the JavaScript
/// function. If the JavaScript function is never called then the `FnOnce`
/// and everything it closes over will leak.
///
/// ```rust,ignore
/// use wasm_bindgen::{prelude::*, JsCast};
///
/// let f = Closure::once_into_js(move || {
/// // ...
/// });
///
/// assert!(f.is_instance_of::<js_sys::Function>());
/// ```
///
/// Note: the `A` and `R` type parameters are here just for backward compat
/// and will be removed in the future.
pub fn once_into_js<F, A, R>(fn_once: F) -> JsValue
where
F: WasmClosureFnOnce<T, A, R>,
{
fn_once.into_js_function()
}
}
/// A trait for converting an `FnOnce(A...) -> R` into a `FnMut(A...) -> R` that
/// will throw if ever called more than once.
#[doc(hidden)]
pub trait WasmClosureFnOnce<FnMut: ?Sized, A, R>: 'static {
fn into_fn_mut(self) -> Box<FnMut>;
fn into_js_function(self) -> JsValue;
}
impl<T: ?Sized> AsRef<JsValue> for Closure<T> {
fn as_ref(&self) -> &JsValue {
&self.js
}
}
/// Internal representation of the actual owned closure which we send to the JS
/// in the constructor to convert it into a JavaScript value.
#[repr(transparent)]
struct OwnedClosure<T: ?Sized> {
inner: ManuallyDrop<Box<T>>,
}
impl<T> WasmDescribe for &OwnedClosure<T>
where
T: WasmClosure + ?Sized,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(CLOSURE);
unsafe extern "C" fn destroy<T: ?Sized>(a: usize, b: usize) {
// This can be called by the JS glue in erroneous situations
// such as when the closure has already been destroyed. If
// that's the case let's not make things worse by
// segfaulting and/or asserting, so just ignore null
// pointers.
if a == 0 {
return;
}
drop(mem::transmute_copy::<_, Box<T>>(&(a, b)));
}
inform(destroy::<T> as usize as u32);
inform(T::IS_MUT as u32);
T::describe();
}
}
impl<T> IntoWasmAbi for &OwnedClosure<T>
where
T: WasmClosure + ?Sized,
{
type Abi = WasmSlice;
fn into_abi(self) -> WasmSlice {
let (a, b): (usize, usize) = unsafe { mem::transmute_copy(self) };
WasmSlice {
ptr: a as u32,
len: b as u32,
}
}
}
impl<T> WasmDescribe for Closure<T>
where
T: WasmClosure + ?Sized,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(EXTERNREF);
}
}
// `Closure` can only be passed by reference to imports.
impl<T> IntoWasmAbi for &Closure<T>
where
T: WasmClosure + ?Sized,
{
type Abi = u32;
fn into_abi(self) -> u32 {
(&*self.js).into_abi()
}
}
impl<T> OptionIntoWasmAbi for &Closure<T>
where
T: WasmClosure + ?Sized,
{
fn none() -> Self::Abi {
0
}
}
fn _check() {
fn _assert<T: IntoWasmAbi>() {}
_assert::<&Closure<dyn Fn()>>();
_assert::<&Closure<dyn Fn(String)>>();
_assert::<&Closure<dyn Fn() -> String>>();
_assert::<&Closure<dyn FnMut()>>();
_assert::<&Closure<dyn FnMut(String)>>();
_assert::<&Closure<dyn FnMut() -> String>>();
}
impl<T> fmt::Debug for Closure<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Closure {{ ... }}")
}
}
impl<T> Drop for Closure<T>
where
T: ?Sized,
{
fn drop(&mut self) {
// this will implicitly drop our strong reference in addition to
// invalidating all future invocations of the closure
if super::__wbindgen_cb_drop(&self.js) {
unsafe {
ManuallyDrop::drop(&mut self.data.inner);
}
}
}
}
/// An internal trait for the `Closure` type.
///
/// This trait is not stable and it's not recommended to use this in bounds or
/// implement yourself.
#[doc(hidden)]
pub unsafe trait WasmClosure: WasmDescribe {
const IS_MUT: bool;
}
/// An internal trait for the `Closure` type.
///
/// This trait is not stable and it's not recommended to use this in bounds or
/// implement yourself.
#[doc(hidden)]
pub trait IntoWasmClosure<T: ?Sized> {
fn unsize(self: Box<Self>) -> Box<T>;
}

View File

@@ -0,0 +1,193 @@
use alloc::boxed::Box;
use core::mem;
use crate::closure::{Closure, IntoWasmClosure, WasmClosure, WasmClosureFnOnce};
use crate::convert::slices::WasmSlice;
use crate::convert::RefFromWasmAbi;
use crate::convert::{FromWasmAbi, IntoWasmAbi, ReturnWasmAbi, WasmAbi, WasmRet};
use crate::describe::{inform, WasmDescribe, FUNCTION};
use crate::throw_str;
use crate::JsValue;
use crate::UnwrapThrowExt;
macro_rules! closures {
// A counter helper to count number of arguments.
(@count_one $ty:ty) => (1);
(@describe ( $($ty:ty),* )) => {
// Needs to be a constant so that interpreter doesn't crash on
// unsupported operations in debug mode.
const ARG_COUNT: u32 = 0 $(+ closures!(@count_one $ty))*;
inform(ARG_COUNT);
$(<$ty>::describe();)*
};
// This silly helper is because by default Rust infers `|var_with_ref_type| ...` closure
// as `impl Fn(&'outer_lifetime A)` instead of `impl for<'temp_lifetime> Fn(&'temp_lifetime A)`
// while `|var_with_ref_type: &A|` makes it use the higher-order generic as expected.
(@closure ($($ty:ty),*) $($var:ident)* $body:block) => (move |$($var: $ty),*| $body);
(@impl_for_fn $is_mut:literal [$($mut:ident)?] $Fn:ident $FnArgs:tt $FromWasmAbi:ident $($var_expr:expr => $var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) => (const _: () = {
impl<$($var,)* R> IntoWasmAbi for &'_ $($mut)? (dyn $Fn $FnArgs -> R + '_)
where
Self: WasmDescribe,
{
type Abi = WasmSlice;
fn into_abi(self) -> WasmSlice {
unsafe {
let (a, b): (usize, usize) = mem::transmute(self);
WasmSlice { ptr: a as u32, len: b as u32 }
}
}
}
#[allow(non_snake_case)]
unsafe extern "C" fn invoke<$($var: $FromWasmAbi,)* R: ReturnWasmAbi>(
a: usize,
b: usize,
$(
$arg1: <$var::Abi as WasmAbi>::Prim1,
$arg2: <$var::Abi as WasmAbi>::Prim2,
$arg3: <$var::Abi as WasmAbi>::Prim3,
$arg4: <$var::Abi as WasmAbi>::Prim4,
)*
) -> WasmRet<R::Abi> {
if a == 0 {
throw_str("closure invoked recursively or after being dropped");
}
// Scope all local variables before we call `return_abi` to
// ensure they're all destroyed as `return_abi` may throw
let ret = {
let f: & $($mut)? dyn $Fn $FnArgs -> R = mem::transmute((a, b));
$(
let $var = $var::Abi::join($arg1, $arg2, $arg3, $arg4);
)*
f($($var_expr),*)
};
ret.return_abi().into()
}
#[allow(clippy::fn_to_numeric_cast)]
impl<$($var,)* R> WasmDescribe for dyn $Fn $FnArgs -> R + '_
where
$($var: $FromWasmAbi,)*
R: ReturnWasmAbi,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(FUNCTION);
inform(invoke::<$($var,)* R> as usize as u32);
closures!(@describe $FnArgs);
R::describe();
R::describe();
}
}
unsafe impl<$($var,)* R> WasmClosure for dyn $Fn $FnArgs -> R + '_
where
Self: WasmDescribe,
{
const IS_MUT: bool = $is_mut;
}
impl<T, $($var,)* R> IntoWasmClosure<dyn $Fn $FnArgs -> R> for T
where
T: 'static + $Fn $FnArgs -> R,
{
fn unsize(self: Box<Self>) -> Box<dyn $Fn $FnArgs -> R> { self }
}
};);
(@impl_for_args $FnArgs:tt $FromWasmAbi:ident $($var_expr:expr => $var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) => {
closures!(@impl_for_fn false [] Fn $FnArgs $FromWasmAbi $($var_expr => $var $arg1 $arg2 $arg3 $arg4)*);
closures!(@impl_for_fn true [mut] FnMut $FnArgs $FromWasmAbi $($var_expr => $var $arg1 $arg2 $arg3 $arg4)*);
// The memory safety here in these implementations below is a bit tricky. We
// want to be able to drop the `Closure` object from within the invocation of a
// `Closure` for cases like promises. That means that while it's running we
// might drop the `Closure`, but that shouldn't invalidate the environment yet.
//
// Instead what we do is to wrap closures in `Rc` variables. The main `Closure`
// has a strong reference count which keeps the trait object alive. Each
// invocation of a closure then *also* clones this and gets a new reference
// count. When the closure returns it will release the reference count.
//
// This means that if the main `Closure` is dropped while it's being invoked
// then destruction is deferred until execution returns. Otherwise it'll
// deallocate data immediately.
#[allow(non_snake_case, unused_parens)]
impl<T, $($var,)* R> WasmClosureFnOnce<dyn FnMut $FnArgs -> R, $FnArgs, R> for T
where
T: 'static + FnOnce $FnArgs -> R,
$($var: $FromWasmAbi + 'static,)*
R: ReturnWasmAbi + 'static,
{
fn into_fn_mut(self) -> Box<dyn FnMut $FnArgs -> R> {
let mut me = Some(self);
Box::new(move |$($var),*| {
let me = me.take().expect_throw("FnOnce called more than once");
me($($var),*)
})
}
fn into_js_function(self) -> JsValue {
use alloc::rc::Rc;
use crate::__rt::WasmRefCell;
let rc1 = Rc::new(WasmRefCell::new(None));
let rc2 = rc1.clone();
let closure = Closure::once(closures!(@closure $FnArgs $($var)* {
let result = self($($var),*);
// And then drop the `Rc` holding this function's `Closure`
// alive.
debug_assert_eq!(Rc::strong_count(&rc2), 1);
let option_closure = rc2.borrow_mut().take();
debug_assert!(option_closure.is_some());
drop(option_closure);
result
}));
let js_val = closure.as_ref().clone();
*rc1.borrow_mut() = Some(closure);
debug_assert_eq!(Rc::strong_count(&rc1), 2);
drop(rc1);
js_val
}
}
};
($( ($($var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) )*) => ($(
closures!(@impl_for_args ($($var),*) FromWasmAbi $($var::from_abi($var) => $var $arg1 $arg2 $arg3 $arg4)*);
)*);
}
closures! {
()
(A a1 a2 a3 a4)
(A a1 a2 a3 a4 B b1 b2 b3 b4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4 H h1 h2 h3 h4)
}
// Copy the above impls down here for where there's only one argument and it's a
// reference. We could add more impls for more kinds of references, but it
// becomes a combinatorial explosion quickly. Let's see how far we can get with
// just this one! Maybe someone else can figure out voodoo so we don't have to
// duplicate.
// We need to allow coherence leak check just for these traits because we're providing separate implementation for `Fn(&A)` variants when `Fn(A)` one already exists.
#[allow(coherence_leak_check)]
const _: () = {
closures!(@impl_for_args (&A) RefFromWasmAbi &*A::ref_from_abi(A) => A a1 a2 a3 a4);
};

626
vendor/wasm-bindgen/src/convert/impls.rs vendored Normal file
View File

@@ -0,0 +1,626 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::char;
use core::fmt::Debug;
use core::mem::{self, ManuallyDrop};
use core::ptr::NonNull;
use crate::convert::traits::{WasmAbi, WasmPrimitive};
use crate::convert::TryFromJsValue;
use crate::convert::{FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, RefFromWasmAbi};
use crate::convert::{OptionFromWasmAbi, OptionIntoWasmAbi, ReturnWasmAbi};
use crate::{Clamped, JsError, JsValue, UnwrapThrowExt};
// Primitive types can always be passed over the ABI.
impl<T: WasmPrimitive> WasmAbi for T {
type Prim1 = Self;
type Prim2 = ();
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (Self, (), (), ()) {
(self, (), (), ())
}
#[inline]
fn join(prim: Self, _: (), _: (), _: ()) -> Self {
prim
}
}
impl WasmAbi for i128 {
type Prim1 = u64;
type Prim2 = u64;
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (u64, u64, (), ()) {
let low = self as u64;
let high = (self >> 64) as u64;
(low, high, (), ())
}
#[inline]
fn join(low: u64, high: u64, _: (), _: ()) -> Self {
((high as u128) << 64 | low as u128) as i128
}
}
impl WasmAbi for u128 {
type Prim1 = u64;
type Prim2 = u64;
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (u64, u64, (), ()) {
let low = self as u64;
let high = (self >> 64) as u64;
(low, high, (), ())
}
#[inline]
fn join(low: u64, high: u64, _: (), _: ()) -> Self {
(high as u128) << 64 | low as u128
}
}
impl<T: WasmAbi<Prim4 = ()>> WasmAbi for Option<T> {
/// Whether this `Option` is a `Some` value.
type Prim1 = u32;
type Prim2 = T::Prim1;
type Prim3 = T::Prim2;
type Prim4 = T::Prim3;
#[inline]
fn split(self) -> (u32, T::Prim1, T::Prim2, T::Prim3) {
match self {
None => (
0,
Default::default(),
Default::default(),
Default::default(),
),
Some(value) => {
let (prim1, prim2, prim3, ()) = value.split();
(1, prim1, prim2, prim3)
}
}
}
#[inline]
fn join(is_some: u32, prim1: T::Prim1, prim2: T::Prim2, prim3: T::Prim3) -> Self {
if is_some == 0 {
None
} else {
Some(T::join(prim1, prim2, prim3, ()))
}
}
}
macro_rules! type_wasm_native {
($($t:tt as $c:tt)*) => ($(
impl IntoWasmAbi for $t {
type Abi = $c;
#[inline]
fn into_abi(self) -> $c { self as $c }
}
impl FromWasmAbi for $t {
type Abi = $c;
#[inline]
unsafe fn from_abi(js: $c) -> Self { js as $t }
}
impl IntoWasmAbi for Option<$t> {
type Abi = Option<$c>;
#[inline]
fn into_abi(self) -> Self::Abi {
self.map(|v| v as $c)
}
}
impl FromWasmAbi for Option<$t> {
type Abi = Option<$c>;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
js.map(|v: $c| v as $t)
}
}
)*)
}
type_wasm_native!(
i64 as i64
u64 as u64
i128 as i128
u128 as u128
f64 as f64
);
/// The sentinel value is 2^32 + 1 for 32-bit primitive types.
///
/// 2^32 + 1 is used, because it's the smallest positive integer that cannot be
/// represented by any 32-bit primitive. While any value >= 2^32 works as a
/// sentinel value for 32-bit integers, it's a bit more tricky for `f32`. `f32`
/// can represent all powers of 2 up to 2^127 exactly. And between 2^32 and 2^33,
/// `f32` can represent all integers 2^32+512*k exactly.
const F64_ABI_OPTION_SENTINEL: f64 = 4294967297_f64;
macro_rules! type_wasm_native_f64_option {
($($t:tt as $c:tt)*) => ($(
impl IntoWasmAbi for $t {
type Abi = $c;
#[inline]
fn into_abi(self) -> $c { self as $c }
}
impl FromWasmAbi for $t {
type Abi = $c;
#[inline]
unsafe fn from_abi(js: $c) -> Self { js as $t }
}
impl IntoWasmAbi for Option<$t> {
type Abi = f64;
#[inline]
fn into_abi(self) -> Self::Abi {
self.map(|v| v as $c as f64).unwrap_or(F64_ABI_OPTION_SENTINEL)
}
}
impl FromWasmAbi for Option<$t> {
type Abi = f64;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
if js == F64_ABI_OPTION_SENTINEL {
None
} else {
Some(js as $c as $t)
}
}
}
)*)
}
type_wasm_native_f64_option!(
i32 as i32
isize as i32
u32 as u32
usize as u32
f32 as f32
);
/// The sentinel value is 0xFF_FFFF for primitives with less than 32 bits.
///
/// This value is used, so all small primitive types (`bool`, `i8`, `u8`,
/// `i16`, `u16`, `char`) can use the same JS glue code. `char::MAX` is
/// 0x10_FFFF btw.
const U32_ABI_OPTION_SENTINEL: u32 = 0x00FF_FFFFu32;
macro_rules! type_abi_as_u32 {
($($t:tt)*) => ($(
impl IntoWasmAbi for $t {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 { self as u32 }
}
impl FromWasmAbi for $t {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: u32) -> Self { js as $t }
}
impl OptionIntoWasmAbi for $t {
#[inline]
fn none() -> u32 { U32_ABI_OPTION_SENTINEL }
}
impl OptionFromWasmAbi for $t {
#[inline]
fn is_none(js: &u32) -> bool { *js == U32_ABI_OPTION_SENTINEL }
}
)*)
}
type_abi_as_u32!(i8 u8 i16 u16);
impl IntoWasmAbi for bool {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
self as u32
}
}
impl FromWasmAbi for bool {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: u32) -> bool {
js != 0
}
}
impl OptionIntoWasmAbi for bool {
#[inline]
fn none() -> u32 {
U32_ABI_OPTION_SENTINEL
}
}
impl OptionFromWasmAbi for bool {
#[inline]
fn is_none(js: &u32) -> bool {
*js == U32_ABI_OPTION_SENTINEL
}
}
impl IntoWasmAbi for char {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
self as u32
}
}
impl FromWasmAbi for char {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: u32) -> char {
// SAFETY: Checked in bindings.
char::from_u32_unchecked(js)
}
}
impl OptionIntoWasmAbi for char {
#[inline]
fn none() -> u32 {
U32_ABI_OPTION_SENTINEL
}
}
impl OptionFromWasmAbi for char {
#[inline]
fn is_none(js: &u32) -> bool {
*js == U32_ABI_OPTION_SENTINEL
}
}
impl<T> IntoWasmAbi for *const T {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
self as u32
}
}
impl<T> FromWasmAbi for *const T {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: u32) -> *const T {
js as *const T
}
}
impl<T> IntoWasmAbi for Option<*const T> {
type Abi = f64;
#[inline]
fn into_abi(self) -> f64 {
self.map(|ptr| ptr as u32 as f64)
.unwrap_or(F64_ABI_OPTION_SENTINEL)
}
}
impl<T> FromWasmAbi for Option<*const T> {
type Abi = f64;
#[inline]
unsafe fn from_abi(js: f64) -> Option<*const T> {
if js == F64_ABI_OPTION_SENTINEL {
None
} else {
Some(js as u32 as *const T)
}
}
}
impl<T> IntoWasmAbi for *mut T {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
self as u32
}
}
impl<T> FromWasmAbi for *mut T {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: u32) -> *mut T {
js as *mut T
}
}
impl<T> IntoWasmAbi for Option<*mut T> {
type Abi = f64;
#[inline]
fn into_abi(self) -> f64 {
self.map(|ptr| ptr as u32 as f64)
.unwrap_or(F64_ABI_OPTION_SENTINEL)
}
}
impl<T> FromWasmAbi for Option<*mut T> {
type Abi = f64;
#[inline]
unsafe fn from_abi(js: f64) -> Option<*mut T> {
if js == F64_ABI_OPTION_SENTINEL {
None
} else {
Some(js as u32 as *mut T)
}
}
}
impl<T> IntoWasmAbi for NonNull<T> {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
self.as_ptr() as u32
}
}
impl<T> OptionIntoWasmAbi for NonNull<T> {
#[inline]
fn none() -> u32 {
0
}
}
impl<T> FromWasmAbi for NonNull<T> {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
// SAFETY: Checked in bindings.
NonNull::new_unchecked(js as *mut T)
}
}
impl<T> OptionFromWasmAbi for NonNull<T> {
#[inline]
fn is_none(js: &u32) -> bool {
*js == 0
}
}
impl IntoWasmAbi for JsValue {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
let ret = self.idx;
mem::forget(self);
ret
}
}
impl FromWasmAbi for JsValue {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: u32) -> JsValue {
JsValue::_new(js)
}
}
impl IntoWasmAbi for &JsValue {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
self.idx
}
}
impl RefFromWasmAbi for JsValue {
type Abi = u32;
type Anchor = ManuallyDrop<JsValue>;
#[inline]
unsafe fn ref_from_abi(js: u32) -> Self::Anchor {
ManuallyDrop::new(JsValue::_new(js))
}
}
impl LongRefFromWasmAbi for JsValue {
type Abi = u32;
type Anchor = JsValue;
#[inline]
unsafe fn long_ref_from_abi(js: u32) -> Self::Anchor {
Self::from_abi(js)
}
}
impl<T: OptionIntoWasmAbi> IntoWasmAbi for Option<T> {
type Abi = T::Abi;
#[inline]
fn into_abi(self) -> T::Abi {
match self {
None => T::none(),
Some(me) => me.into_abi(),
}
}
}
impl<T: OptionFromWasmAbi> FromWasmAbi for Option<T> {
type Abi = T::Abi;
#[inline]
unsafe fn from_abi(js: T::Abi) -> Self {
if T::is_none(&js) {
None
} else {
Some(T::from_abi(js))
}
}
}
impl<T: IntoWasmAbi> IntoWasmAbi for Clamped<T> {
type Abi = T::Abi;
#[inline]
fn into_abi(self) -> Self::Abi {
self.0.into_abi()
}
}
impl<T: FromWasmAbi> FromWasmAbi for Clamped<T> {
type Abi = T::Abi;
#[inline]
unsafe fn from_abi(js: T::Abi) -> Self {
Clamped(T::from_abi(js))
}
}
impl IntoWasmAbi for () {
type Abi = ();
#[inline]
fn into_abi(self) {
self
}
}
impl<T: WasmAbi<Prim3 = (), Prim4 = ()>> WasmAbi for Result<T, u32> {
type Prim1 = T::Prim1;
type Prim2 = T::Prim2;
// The order of primitives here is such that we can pop() the possible error
// first, deal with it and move on. Later primitives are popped off the
// stack first.
/// If this `Result` is an `Err`, the error value.
type Prim3 = u32;
/// Whether this `Result` is an `Err`.
type Prim4 = u32;
#[inline]
fn split(self) -> (T::Prim1, T::Prim2, u32, u32) {
match self {
Ok(value) => {
let (prim1, prim2, (), ()) = value.split();
(prim1, prim2, 0, 0)
}
Err(err) => (Default::default(), Default::default(), err, 1),
}
}
#[inline]
fn join(prim1: T::Prim1, prim2: T::Prim2, err: u32, is_err: u32) -> Self {
if is_err == 0 {
Ok(T::join(prim1, prim2, (), ()))
} else {
Err(err)
}
}
}
impl<T, E> ReturnWasmAbi for Result<T, E>
where
T: IntoWasmAbi,
E: Into<JsValue>,
T::Abi: WasmAbi<Prim3 = (), Prim4 = ()>,
{
type Abi = Result<T::Abi, u32>;
#[inline]
fn return_abi(self) -> Self::Abi {
match self {
Ok(v) => Ok(v.into_abi()),
Err(e) => {
let jsval = e.into();
Err(jsval.into_abi())
}
}
}
}
impl IntoWasmAbi for JsError {
type Abi = <JsValue as IntoWasmAbi>::Abi;
fn into_abi(self) -> Self::Abi {
self.value.into_abi()
}
}
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
// Note: this can't take `&[T]` because the `Into<JsValue>` impl needs
// ownership of `T`.
pub fn js_value_vector_into_abi<T: Into<JsValue>>(
vector: Box<[T]>,
) -> <Box<[JsValue]> as IntoWasmAbi>::Abi {
let js_vals: Box<[JsValue]> = vector.into_vec().into_iter().map(|x| x.into()).collect();
js_vals.into_abi()
}
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub unsafe fn js_value_vector_from_abi<T: TryFromJsValue>(
js: <Box<[JsValue]> as FromWasmAbi>::Abi,
) -> Box<[T]>
where
T::Error: Debug,
{
let js_vals = <Vec<JsValue> as FromWasmAbi>::from_abi(js);
let mut result = Vec::with_capacity(js_vals.len());
for value in js_vals {
// We push elements one-by-one instead of using `collect` in order to improve
// error messages. When using `collect`, this `expect_throw` is buried in a
// giant chain of internal iterator functions, which results in the actual
// function that takes this `Vec` falling off the end of the call stack.
// So instead, make sure to call it directly within this function.
//
// This is only a problem in debug mode. Since this is the browser's error stack
// we're talking about, it can only see functions that actually make it to the
// final Wasm binary (i.e., not inlined functions). All of those internal
// iterator functions get inlined in release mode, and so they don't show up.
result.push(
T::try_from_js_value(value).expect_throw("array contains a value of the wrong type"),
);
}
result.into_boxed_slice()
}

15
vendor/wasm-bindgen/src/convert/mod.rs vendored Normal file
View File

@@ -0,0 +1,15 @@
//! # ⚠️ Unstable
//!
//! This is an internal module, no stability guarantees are provided. Use at
//! your own risk.
#![allow(clippy::missing_safety_doc)]
mod closures;
mod impls;
mod slices;
mod traits;
pub use self::impls::*;
pub use self::slices::WasmSlice;
pub use self::traits::*;

View File

@@ -0,0 +1,457 @@
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::str;
use crate::convert::{js_value_vector_from_abi, js_value_vector_into_abi};
use crate::convert::{
FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, OptionFromWasmAbi, OptionIntoWasmAbi,
RefFromWasmAbi, RefMutFromWasmAbi, VectorFromWasmAbi, VectorIntoWasmAbi, WasmAbi,
};
use crate::describe::*;
use crate::JsValue;
use crate::{JsCast, __wbindgen_copy_to_typed_array};
use cfg_if::cfg_if;
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
// note: `WasmAbi` types do not need to be FFI-safe themselves, it's just more
// convenient to directly write `WasmSlice` in some of the manually-written FFI
// functions in `lib.rs` rather than `WasmRet<WasmSlice>`.
#[repr(C)]
pub struct WasmSlice {
pub ptr: u32,
pub len: u32,
}
impl WasmAbi for WasmSlice {
/// `self.ptr`
type Prim1 = u32;
/// `self.len`
type Prim2 = u32;
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (u32, u32, (), ()) {
(self.ptr, self.len, (), ())
}
#[inline]
fn join(ptr: u32, len: u32, _: (), _: ()) -> Self {
Self { ptr, len }
}
}
#[inline]
fn null_slice() -> WasmSlice {
WasmSlice { ptr: 0, len: 0 }
}
pub struct WasmMutSlice {
pub slice: WasmSlice,
pub idx: u32,
}
impl WasmAbi for WasmMutSlice {
/// `self.slice.ptr`
type Prim1 = u32;
/// `self.slice.len`
type Prim2 = u32;
/// `self.idx`
type Prim3 = u32;
type Prim4 = ();
#[inline]
fn split(self) -> (u32, u32, u32, ()) {
(self.slice.ptr, self.slice.len, self.idx, ())
}
#[inline]
fn join(ptr: u32, len: u32, idx: u32, _: ()) -> Self {
Self {
slice: WasmSlice { ptr, len },
idx,
}
}
}
/// The representation of a mutable slice passed from JS to Rust.
pub struct MutSlice<T> {
/// A copy of the data in the JS typed array.
contents: Box<[T]>,
/// A reference to the original JS typed array.
js: JsValue,
}
impl<T> Drop for MutSlice<T> {
fn drop(&mut self) {
let byte_slice = unsafe {
core::slice::from_raw_parts(
self.contents.as_ptr() as *const u8,
self.contents.len() * mem::size_of::<T>(),
)
};
__wbindgen_copy_to_typed_array(byte_slice, &self.js);
}
}
impl<T> Deref for MutSlice<T> {
type Target = [T];
fn deref(&self) -> &[T] {
&self.contents
}
}
impl<T> DerefMut for MutSlice<T> {
fn deref_mut(&mut self) -> &mut [T] {
&mut self.contents
}
}
macro_rules! vectors {
($($t:ty)*) => ($(
vectors_internal!($t);
vectors_internal!(MaybeUninit<$t>);
)*)
}
macro_rules! vectors_internal {
($t:ty) => {
impl WasmDescribeVector for $t {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe_vector() {
inform(VECTOR);
<$t>::describe();
}
}
impl VectorIntoWasmAbi for $t {
type Abi = WasmSlice;
#[inline]
fn vector_into_abi(vector: Box<[$t]>) -> WasmSlice {
let ptr = vector.as_ptr();
let len = vector.len();
mem::forget(vector);
WasmSlice {
ptr: ptr.into_abi(),
len: len as u32,
}
}
}
impl VectorFromWasmAbi for $t {
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[$t]> {
let ptr = <*mut $t>::from_abi(js.ptr);
let len = js.len as usize;
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
}
}
impl<'a> IntoWasmAbi for &'a [$t] {
type Abi = WasmSlice;
#[inline]
fn into_abi(self) -> WasmSlice {
WasmSlice {
ptr: self.as_ptr().into_abi(),
len: self.len() as u32,
}
}
}
impl<'a> OptionIntoWasmAbi for &'a [$t] {
#[inline]
fn none() -> WasmSlice {
null_slice()
}
}
impl<'a> IntoWasmAbi for &'a mut [$t] {
type Abi = WasmSlice;
#[inline]
fn into_abi(self) -> WasmSlice {
(&*self).into_abi()
}
}
impl<'a> OptionIntoWasmAbi for &'a mut [$t] {
#[inline]
fn none() -> WasmSlice {
null_slice()
}
}
impl RefFromWasmAbi for [$t] {
type Abi = WasmSlice;
type Anchor = Box<[$t]>;
#[inline]
unsafe fn ref_from_abi(js: WasmSlice) -> Box<[$t]> {
<Box<[$t]>>::from_abi(js)
}
}
impl RefMutFromWasmAbi for [$t] {
type Abi = WasmMutSlice;
type Anchor = MutSlice<$t>;
#[inline]
unsafe fn ref_mut_from_abi(js: WasmMutSlice) -> MutSlice<$t> {
let contents = <Box<[$t]>>::from_abi(js.slice);
let js = JsValue::from_abi(js.idx);
MutSlice { contents, js }
}
}
impl LongRefFromWasmAbi for [$t] {
type Abi = WasmSlice;
type Anchor = Box<[$t]>;
#[inline]
unsafe fn long_ref_from_abi(js: WasmSlice) -> Box<[$t]> {
Self::ref_from_abi(js)
}
}
};
}
vectors! {
u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64
}
impl WasmDescribeVector for String {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe_vector() {
inform(VECTOR);
inform(NAMED_EXTERNREF);
// Trying to use an actual loop for this breaks the Wasm interpreter.
inform(6);
inform('s' as u32);
inform('t' as u32);
inform('r' as u32);
inform('i' as u32);
inform('n' as u32);
inform('g' as u32);
}
}
impl VectorIntoWasmAbi for String {
type Abi = <Box<[JsValue]> as IntoWasmAbi>::Abi;
fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi {
js_value_vector_into_abi(vector)
}
}
impl VectorFromWasmAbi for String {
type Abi = <Box<[JsValue]> as FromWasmAbi>::Abi;
unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]> {
js_value_vector_from_abi(js)
}
}
cfg_if! {
if #[cfg(feature = "enable-interning")] {
#[inline]
fn unsafe_get_cached_str(x: &str) -> Option<WasmSlice> {
// This uses 0 for the ptr as an indication that it is a JsValue and not a str.
crate::cache::intern::unsafe_get_str(x).map(|x| WasmSlice { ptr: 0, len: x })
}
} else {
#[inline]
fn unsafe_get_cached_str(_x: &str) -> Option<WasmSlice> {
None
}
}
}
impl<T> IntoWasmAbi for Vec<T>
where
Box<[T]>: IntoWasmAbi<Abi = WasmSlice>,
{
type Abi = <Box<[T]> as IntoWasmAbi>::Abi;
#[inline]
fn into_abi(self) -> Self::Abi {
self.into_boxed_slice().into_abi()
}
}
impl<T> OptionIntoWasmAbi for Vec<T>
where
Box<[T]>: IntoWasmAbi<Abi = WasmSlice>,
{
#[inline]
fn none() -> WasmSlice {
null_slice()
}
}
impl<T> FromWasmAbi for Vec<T>
where
Box<[T]>: FromWasmAbi<Abi = WasmSlice>,
{
type Abi = <Box<[T]> as FromWasmAbi>::Abi;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
<Box<[T]>>::from_abi(js).into()
}
}
impl<T> OptionFromWasmAbi for Vec<T>
where
Box<[T]>: FromWasmAbi<Abi = WasmSlice>,
{
#[inline]
fn is_none(abi: &WasmSlice) -> bool {
abi.ptr == 0
}
}
impl IntoWasmAbi for String {
type Abi = <Vec<u8> as IntoWasmAbi>::Abi;
#[inline]
fn into_abi(self) -> Self::Abi {
// This is safe because the JsValue is immediately looked up in the heap and
// then returned, so use-after-free cannot occur.
unsafe_get_cached_str(&self).unwrap_or_else(|| self.into_bytes().into_abi())
}
}
impl OptionIntoWasmAbi for String {
#[inline]
fn none() -> Self::Abi {
null_slice()
}
}
impl FromWasmAbi for String {
type Abi = <Vec<u8> as FromWasmAbi>::Abi;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
String::from_utf8_unchecked(<Vec<u8>>::from_abi(js))
}
}
impl OptionFromWasmAbi for String {
#[inline]
fn is_none(slice: &WasmSlice) -> bool {
slice.ptr == 0
}
}
impl<'a> IntoWasmAbi for &'a str {
type Abi = <&'a [u8] as IntoWasmAbi>::Abi;
#[inline]
fn into_abi(self) -> Self::Abi {
// This is safe because the JsValue is immediately looked up in the heap and
// then returned, so use-after-free cannot occur.
unsafe_get_cached_str(self).unwrap_or_else(|| self.as_bytes().into_abi())
}
}
impl OptionIntoWasmAbi for &str {
#[inline]
fn none() -> Self::Abi {
null_slice()
}
}
impl RefFromWasmAbi for str {
type Abi = <[u8] as RefFromWasmAbi>::Abi;
type Anchor = Box<str>;
#[inline]
unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor {
mem::transmute::<Box<[u8]>, Box<str>>(<Box<[u8]>>::from_abi(js))
}
}
impl LongRefFromWasmAbi for str {
type Abi = <[u8] as RefFromWasmAbi>::Abi;
type Anchor = Box<str>;
#[inline]
unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor {
Self::ref_from_abi(js)
}
}
impl<T: VectorIntoWasmAbi> IntoWasmAbi for Box<[T]> {
type Abi = <T as VectorIntoWasmAbi>::Abi;
fn into_abi(self) -> Self::Abi {
T::vector_into_abi(self)
}
}
impl<T> OptionIntoWasmAbi for Box<[T]>
where
Self: IntoWasmAbi<Abi = WasmSlice>,
{
fn none() -> WasmSlice {
null_slice()
}
}
impl<T: VectorFromWasmAbi> FromWasmAbi for Box<[T]> {
type Abi = <T as VectorFromWasmAbi>::Abi;
unsafe fn from_abi(js: Self::Abi) -> Self {
T::vector_from_abi(js)
}
}
impl<T> OptionFromWasmAbi for Box<[T]>
where
Self: FromWasmAbi<Abi = WasmSlice>,
{
fn is_none(slice: &WasmSlice) -> bool {
slice.ptr == 0
}
}
impl<T: JsCast + WasmDescribe> VectorFromWasmAbi for T {
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[Self]> {
let ptr = <*mut T>::from_abi(js.ptr);
let len = js.len as usize;
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
}
}
impl<T: JsCast + WasmDescribe> VectorIntoWasmAbi for T {
type Abi = WasmSlice;
#[inline]
fn vector_into_abi(vector: Box<[T]>) -> WasmSlice {
let ptr = vector.as_ptr();
let len = vector.len();
mem::forget(vector);
WasmSlice {
ptr: ptr.into_abi(),
len: len as u32,
}
}
}

View File

@@ -0,0 +1,349 @@
use core::borrow::Borrow;
use core::ops::{Deref, DerefMut};
use crate::describe::*;
use crate::JsValue;
/// A trait for anything that can be converted into a type that can cross the
/// Wasm ABI directly, eg `u32` or `f64`.
///
/// This is the opposite operation as `FromWasmAbi` and `Ref[Mut]FromWasmAbi`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait IntoWasmAbi: WasmDescribe {
/// The Wasm ABI type that this converts into when crossing the ABI
/// boundary.
type Abi: WasmAbi;
/// Convert `self` into `Self::Abi` so that it can be sent across the wasm
/// ABI boundary.
fn into_abi(self) -> Self::Abi;
}
/// A trait for anything that can be recovered by-value from the Wasm ABI
/// boundary, eg a Rust `u8` can be recovered from the Wasm ABI `u32` type.
///
/// This is the by-value variant of the opposite operation as `IntoWasmAbi`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait FromWasmAbi: WasmDescribe {
/// The Wasm ABI type that this converts from when coming back out from the
/// ABI boundary.
type Abi: WasmAbi;
/// Recover a `Self` from `Self::Abi`.
///
/// # Safety
///
/// This is only safe to call when -- and implementations may assume that --
/// the supplied `Self::Abi` was previously generated by a call to `<Self as
/// IntoWasmAbi>::into_abi()` or the moral equivalent in JS.
unsafe fn from_abi(js: Self::Abi) -> Self;
}
/// A trait for anything that can be recovered as some sort of shared reference
/// from the Wasm ABI boundary.
///
/// This is the shared reference variant of the opposite operation as
/// `IntoWasmAbi`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait RefFromWasmAbi: WasmDescribe {
/// The Wasm ABI type references to `Self` are recovered from.
type Abi: WasmAbi;
/// The type that holds the reference to `Self` for the duration of the
/// invocation of the function that has an `&Self` parameter. This is
/// required to ensure that the lifetimes don't persist beyond one function
/// call, and so that they remain anonymous.
type Anchor: Deref<Target = Self>;
/// Recover a `Self::Anchor` from `Self::Abi`.
///
/// # Safety
///
/// Same as `FromWasmAbi::from_abi`.
unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor;
}
/// A version of the `RefFromWasmAbi` trait with the additional requirement
/// that the reference must remain valid as long as the anchor isn't dropped.
///
/// This isn't the case for `JsValue`'s `RefFromWasmAbi` implementation. To
/// avoid having to allocate a spot for the `JsValue` on the `JsValue` heap,
/// the `JsValue` is instead pushed onto the `JsValue` stack, and popped off
/// again after the function that the reference was passed to returns. So,
/// `JsValue` has a different `LongRefFromWasmAbi` implementation that behaves
/// the same as `FromWasmAbi`, putting the value on the heap.
///
/// This is needed for async functions, where the reference needs to be valid
/// for the whole length of the `Future`, rather than the initial synchronous
/// call.
///
/// 'long ref' is short for 'long-lived reference'.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait LongRefFromWasmAbi: WasmDescribe {
/// Same as `RefFromWasmAbi::Abi`
type Abi: WasmAbi;
/// Same as `RefFromWasmAbi::Anchor`
type Anchor: Borrow<Self>;
/// Same as `RefFromWasmAbi::ref_from_abi`
unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor;
}
/// Dual of the `RefFromWasmAbi` trait, except for mutable references.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait RefMutFromWasmAbi: WasmDescribe {
/// Same as `RefFromWasmAbi::Abi`
type Abi: WasmAbi;
/// Same as `RefFromWasmAbi::Anchor`
type Anchor: DerefMut<Target = Self>;
/// Same as `RefFromWasmAbi::ref_from_abi`
unsafe fn ref_mut_from_abi(js: Self::Abi) -> Self::Anchor;
}
/// Indicates that this type can be passed to JS as `Option<Self>`.
///
/// This trait is used when implementing `IntoWasmAbi for Option<T>`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait OptionIntoWasmAbi: IntoWasmAbi {
/// Returns an ABI instance indicating "none", which JS will interpret as
/// the `None` branch of this option.
///
/// It should be guaranteed that the `IntoWasmAbi` can never produce the ABI
/// value returned here.
fn none() -> Self::Abi;
}
/// Indicates that this type can be received from JS as `Option<Self>`.
///
/// This trait is used when implementing `FromWasmAbi for Option<T>`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait OptionFromWasmAbi: FromWasmAbi {
/// Tests whether the argument is a "none" instance. If so it will be
/// deserialized as `None`, and otherwise it will be passed to
/// `FromWasmAbi`.
fn is_none(abi: &Self::Abi) -> bool;
}
/// A trait for any type which maps to a Wasm primitive type when used in FFI
/// (`i32`, `i64`, `f32`, or `f64`).
///
/// This is with the exception of `()` (and other zero-sized types), which are
/// also allowed because they're ignored: no arguments actually get added.
///
/// # Safety
///
/// This is an unsafe trait to implement as there's no guarantee the type
/// actually maps to a primitive type.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub unsafe trait WasmPrimitive: Default {}
unsafe impl WasmPrimitive for u32 {}
unsafe impl WasmPrimitive for i32 {}
unsafe impl WasmPrimitive for u64 {}
unsafe impl WasmPrimitive for i64 {}
unsafe impl WasmPrimitive for f32 {}
unsafe impl WasmPrimitive for f64 {}
unsafe impl WasmPrimitive for () {}
/// A trait which represents types that can be passed across the Wasm ABI
/// boundary, by being split into multiple Wasm primitive types.
///
/// Up to 4 primitives are supported; if you don't want to use all of them, you
/// can set the rest to `()`, which will cause them to be ignored.
///
/// You need to be careful how many primitives you use, however:
/// `Result<T, JsValue>` uses up 2 primitives to store the error, and so it
/// doesn't work if `T` uses more than 2 primitives.
///
/// So, if you're adding support for a type that needs 3 or more primitives and
/// is able to be returned, you have to add another primitive here.
///
/// There's already one type that uses 3 primitives: `&mut [T]`. However, it
/// can't be returned anyway, so it doesn't matter that
/// `Result<&mut [T], JsValue>` wouldn't work.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait WasmAbi {
type Prim1: WasmPrimitive;
type Prim2: WasmPrimitive;
type Prim3: WasmPrimitive;
type Prim4: WasmPrimitive;
/// Splits this type up into primitives to be sent over the ABI.
fn split(self) -> (Self::Prim1, Self::Prim2, Self::Prim3, Self::Prim4);
/// Reconstructs this type from primitives received over the ABI.
fn join(prim1: Self::Prim1, prim2: Self::Prim2, prim3: Self::Prim3, prim4: Self::Prim4)
-> Self;
}
/// A trait representing how to interpret the return value of a function for
/// the Wasm ABI.
///
/// This is very similar to the `IntoWasmAbi` trait and in fact has a blanket
/// implementation for all implementors of the `IntoWasmAbi`. The primary use
/// case of this trait is to enable functions to return `Result`, interpreting
/// an error as "rethrow this to JS"
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait ReturnWasmAbi: WasmDescribe {
/// Same as `IntoWasmAbi::Abi`
type Abi: WasmAbi;
/// Same as `IntoWasmAbi::into_abi`, except that it may throw and never
/// return in the case of `Err`.
fn return_abi(self) -> Self::Abi;
}
impl<T: IntoWasmAbi> ReturnWasmAbi for T {
type Abi = T::Abi;
#[inline]
fn return_abi(self) -> Self::Abi {
self.into_abi()
}
}
use alloc::boxed::Box;
use core::marker::Sized;
/// Trait for element types to implement IntoWasmAbi for vectors of
/// themselves.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait VectorIntoWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi;
}
/// Trait for element types to implement FromWasmAbi for vectors of
/// themselves.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait VectorFromWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]>;
}
/// A repr(C) struct containing all of the primitives of a `WasmAbi` type, in
/// order.
///
/// This is used as the return type of imported/exported functions. `WasmAbi`
/// types aren't guaranteed to be FFI-safe, so we can't return them directly:
/// instead we return this.
///
/// If all but one of the primitives is `()`, this corresponds to returning the
/// remaining primitive directly, otherwise a return pointer is used.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
#[repr(C)]
pub struct WasmRet<T: WasmAbi> {
prim1: T::Prim1,
prim2: T::Prim2,
prim3: T::Prim3,
prim4: T::Prim4,
}
impl<T: WasmAbi> From<T> for WasmRet<T> {
fn from(value: T) -> Self {
let (prim1, prim2, prim3, prim4) = value.split();
Self {
prim1,
prim2,
prim3,
prim4,
}
}
}
// Ideally this'd just be an `Into<T>` implementation, but unfortunately that
// doesn't work because of the orphan rule.
impl<T: WasmAbi> WasmRet<T> {
/// Joins the components of this `WasmRet` back into the type they represent.
pub fn join(self) -> T {
T::join(self.prim1, self.prim2, self.prim3, self.prim4)
}
}
/// [`TryFromJsValue`] is a trait for converting a JavaScript value ([`JsValue`])
/// into a Rust type. It is used by the [`wasm_bindgen`](wasm_bindgen_macro::wasm_bindgen)
/// proc-macro to allow conversion to user types.
///
/// Types implementing this trait must specify their conversion logic from
/// [`JsValue`] to the Rust type, handling any potential errors that may occur
/// during the conversion process.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait TryFromJsValue: Sized {
/// The type returned in the event of a conversion error.
type Error;
/// Performs the conversion.
fn try_from_js_value(value: JsValue) -> Result<Self, Self::Error>;
}

200
vendor/wasm-bindgen/src/describe.rs vendored Normal file
View File

@@ -0,0 +1,200 @@
//! This is an internal module, no stability guarantees are provided. Use at
//! your own risk.
#![doc(hidden)]
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::{mem::MaybeUninit, ptr::NonNull};
use crate::{Clamped, JsCast, JsError, JsValue};
use cfg_if::cfg_if;
pub use wasm_bindgen_shared::tys::*;
#[inline(always)] // see the wasm-interpreter module
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
pub fn inform(a: u32) {
unsafe { super::__wbindgen_describe(a) }
}
pub trait WasmDescribe {
fn describe();
}
/// Trait for element types to implement WasmDescribe for vectors of
/// themselves.
pub trait WasmDescribeVector {
fn describe_vector();
}
macro_rules! simple {
($($t:ident => $d:ident)*) => ($(
impl WasmDescribe for $t {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() { inform($d) }
}
)*)
}
simple! {
i8 => I8
u8 => U8
i16 => I16
u16 => U16
i32 => I32
u32 => U32
i64 => I64
u64 => U64
i128 => I128
u128 => U128
isize => I32
usize => U32
f32 => F32
f64 => F64
bool => BOOLEAN
char => CHAR
JsValue => EXTERNREF
}
cfg_if! {
if #[cfg(feature = "enable-interning")] {
simple! {
str => CACHED_STRING
}
} else {
simple! {
str => STRING
}
}
}
impl<T> WasmDescribe for *const T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(U32)
}
}
impl<T> WasmDescribe for *mut T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(U32)
}
}
impl<T> WasmDescribe for NonNull<T> {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(NONNULL)
}
}
impl<T: WasmDescribe> WasmDescribe for [T] {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(SLICE);
T::describe();
}
}
impl<T: WasmDescribe + ?Sized> WasmDescribe for &T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(REF);
T::describe();
}
}
impl<T: WasmDescribe + ?Sized> WasmDescribe for &mut T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(REFMUT);
T::describe();
}
}
cfg_if! {
if #[cfg(feature = "enable-interning")] {
simple! {
String => CACHED_STRING
}
} else {
simple! {
String => STRING
}
}
}
impl<T: JsCast + WasmDescribe> WasmDescribeVector for T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe_vector() {
inform(VECTOR);
T::describe();
}
}
impl<T: WasmDescribeVector> WasmDescribe for Box<[T]> {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
T::describe_vector();
}
}
impl<T> WasmDescribe for Vec<T>
where
Box<[T]>: WasmDescribe,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
<Box<[T]>>::describe();
}
}
impl<T: WasmDescribe> WasmDescribe for Option<T> {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(OPTIONAL);
T::describe();
}
}
impl WasmDescribe for () {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(UNIT)
}
}
impl<T: WasmDescribe, E: Into<JsValue>> WasmDescribe for Result<T, E> {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(RESULT);
T::describe();
}
}
impl<T: WasmDescribe> WasmDescribe for MaybeUninit<T> {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
T::describe();
}
}
impl<T: WasmDescribe> WasmDescribe for Clamped<T> {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(CLAMPED);
T::describe();
}
}
impl WasmDescribe for JsError {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
JsValue::describe();
}
}

153
vendor/wasm-bindgen/src/externref.rs vendored Normal file
View File

@@ -0,0 +1,153 @@
use crate::JsValue;
use alloc::slice;
use alloc::vec::Vec;
use core::cell::RefCell;
use core::cmp::max;
externs! {
#[link(wasm_import_module = "__wbindgen_externref_xform__")]
extern "C" {
fn __wbindgen_externref_table_grow(delta: usize) -> i32;
fn __wbindgen_externref_table_set_null(idx: usize) -> ();
}
}
struct Slab {
data: Vec<usize>,
head: usize,
base: usize,
}
impl Slab {
const fn new() -> Self {
Self {
data: Vec::new(),
head: 0,
base: 0,
}
}
fn alloc(&mut self) -> usize {
let ret = self.head;
if ret == self.data.len() {
let curr_len = self.data.len();
if curr_len == self.data.capacity() {
let extra = max(128, curr_len);
let r = unsafe { __wbindgen_externref_table_grow(extra) };
if r == -1 {
internal_error("table grow failure")
}
if self.base == 0 {
self.base = r as usize;
} else if self.base + self.data.len() != r as usize {
internal_error("someone else allocated table entries?")
}
if self.data.try_reserve_exact(extra).is_err() {
internal_error("allocation failure");
}
}
// custom condition to ensure `push` below doesn't call `reserve` in
// optimized builds which pulls in lots of panic infrastructure
if self.data.len() >= self.data.capacity() {
internal_error("push should be infallible now")
}
self.data.push(ret + 1);
}
// usage of `get_mut` thwarts panicking infrastructure in optimized
// builds
match self.data.get_mut(ret) {
Some(slot) => self.head = *slot,
None => internal_error("ret out of bounds"),
}
ret + self.base
}
fn dealloc(&mut self, slot: usize) {
if slot < self.base {
internal_error("free reserved slot");
}
let slot = slot - self.base;
// usage of `get_mut` thwarts panicking infrastructure in optimized
// builds
match self.data.get_mut(slot) {
Some(ptr) => {
*ptr = self.head;
self.head = slot;
}
None => internal_error("slot out of bounds"),
}
}
fn live_count(&self) -> u32 {
let mut free_count = 0;
let mut next = self.head;
while next < self.data.len() {
debug_assert!((free_count as usize) < self.data.len());
free_count += 1;
match self.data.get(next) {
Some(n) => next = *n,
None => internal_error("slot out of bounds"),
};
}
self.data.len() as u32 - free_count
}
}
fn internal_error(_msg: &str) -> ! {
cfg_if::cfg_if! {
if #[cfg(debug_assertions)] {
super::throw_str(_msg)
} 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!()
}
}
}
// Management of `externref` is always thread local since an `externref` value
// can't cross threads in wasm. Indices as a result are always thread-local.
#[cfg_attr(target_feature = "atomics", thread_local)]
static HEAP_SLAB: crate::__rt::ThreadLocalWrapper<RefCell<Slab>> =
crate::__rt::ThreadLocalWrapper(RefCell::new(Slab::new()));
#[no_mangle]
pub extern "C" fn __externref_table_alloc() -> usize {
HEAP_SLAB.0.borrow_mut().alloc()
}
#[no_mangle]
pub extern "C" fn __externref_table_dealloc(idx: usize) {
if idx < super::JSIDX_RESERVED as usize {
return;
}
// clear this value from the table so while the table slot is un-allocated
// we don't keep around a strong reference to a potentially large object
unsafe {
__wbindgen_externref_table_set_null(idx);
}
HEAP_SLAB.0.borrow_mut().dealloc(idx)
}
#[no_mangle]
pub unsafe extern "C" fn __externref_drop_slice(ptr: *mut JsValue, len: usize) {
for slot in slice::from_raw_parts_mut(ptr, len) {
__externref_table_dealloc(slot.idx as usize);
}
}
// Implementation of `__wbindgen_externref_heap_live_count` for when we are using
// `externref` instead of the JS `heap`.
pub fn __wbindgen_externref_heap_live_count() -> u32 {
HEAP_SLAB.0.borrow_mut().live_count()
}

1718
vendor/wasm-bindgen/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load Diff

4
vendor/wasm-bindgen/src/link.rs vendored Normal file
View File

@@ -0,0 +1,4 @@
// see comment in module above this in `link_mem_intrinsics`
#[inline(never)]
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
pub fn link_intrinsics() {}

38
vendor/wasm-bindgen/src/rt/marker.rs vendored Normal file
View File

@@ -0,0 +1,38 @@
/// Marker trait for types that support `#[wasm_bindgen(constructor)]`.
#[cfg_attr(
wbg_diagnostic,
diagnostic::on_unimplemented(
message = "JavaScript constructors are not supported for `{Self}`",
label = "this function cannot be the constructor of `{Self}`",
note = "`#[wasm_bindgen(constructor)]` is only supported for `struct`s and cannot be used for `enum`s.",
note = "Consider removing the `constructor` option and using a regular static method instead."
)
)]
pub trait SupportsConstructor {}
pub struct CheckSupportsConstructor<T: SupportsConstructor>(T);
/// Marker trait for types that support `#[wasm_bindgen(getter)]` or
/// `#[wasm_bindgen(Setter)]` on instance methods.
#[cfg_attr(
wbg_diagnostic,
diagnostic::on_unimplemented(
message = "JavaScript instance getters and setters are not supported for `{Self}`",
label = "this method cannot be a getter or setter for `{Self}`",
note = "`#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are only supported for `struct`s and cannot be used for `enum`s.",
)
)]
pub trait SupportsInstanceProperty {}
pub struct CheckSupportsInstanceProperty<T: SupportsInstanceProperty>(T);
/// Marker trait for types that support `#[wasm_bindgen(getter)]` or
/// `#[wasm_bindgen(Setter)]` on static methods.
#[cfg_attr(
wbg_diagnostic,
diagnostic::on_unimplemented(
message = "JavaScript static getters and setters are not supported for `{Self}`",
label = "this static function cannot be a static getter or setter on `{Self}`",
note = "`#[wasm_bindgen(getter)]` and `#[wasm_bindgen(setter)]` are only supported for `struct`s and cannot be used for `enum`s.",
)
)]
pub trait SupportsStaticProperty {}
pub struct CheckSupportsStaticProperty<T: SupportsStaticProperty>(T);

760
vendor/wasm-bindgen/src/rt/mod.rs vendored Normal file
View File

@@ -0,0 +1,760 @@
use crate::convert::{FromWasmAbi, IntoWasmAbi, WasmAbi, WasmRet};
use crate::describe::inform;
use crate::JsValue;
use core::borrow::{Borrow, BorrowMut};
use core::cell::{Cell, UnsafeCell};
use core::convert::Infallible;
use core::ops::{Deref, DerefMut};
#[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;
// Cast between arbitrary types supported by wasm-bindgen by going via JS.
//
// The implementation generates a no-op JS adapter that simply takes an argument
// in one type, decodes it from the ABI, and then returns the same value back
// encoded with a different type.
pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
// Here we need to create a conversion function between arbitrary types
// supported by the wasm-bindgen's ABI.
// To do that we... take a few unconventional turns.
// In essence what happens here is this:
//
// 1. First up, below we call a function, `breaks_if_inlined`. This
// function, as the name implies, does not work if it's inlined.
// More on that in a moment.
// 2. This is actually a descriptor function, similar to ones we
// generate for imports and exports, except we can't name it here
// because it's generated by monomorphisation for specific types.
// 2. Since we can't name it to associate with a specific import or
// export, we use a different approach. After describing the input
// type, this function internally calls a special import recognized
// by the `wasm-bindgen` CLI tool, `__wbindgen_describe_cast`. This
// imported symbol is similar to `__wbindgen_describe` in that it's
// not intended to show up in the final binary but it's merely a
// signal for `wasm-bindgen` that marks the parent function
// (`breaks_if_inlined`) as a cast descriptor.
//
// Most of this doesn't actually make sense to happen at runtime! The
// real magic happens when `wasm-bindgen` comes along and updates our
// generated code. When `wasm-bindgen` runs it performs a few tasks:
//
// * First, it finds all functions that call
// `__wbindgen_describe_cast`. These are all `breaks_if_inlined`
// defined below as the symbol isn't called anywhere else.
// * Next, `wasm-bindgen` executes the `breaks_if_inlined`
// monomorphized functions, passing it dummy arguments. This will
// execute the function until it reaches the call to
// `__wbindgen_describe_cast`, at which point the interpreter stops.
// * Finally, and probably most heinously, the call to
// `breaks_if_inlined` is rewritten to call an otherwise globally
// imported function. This globally imported function will simply
// return the passed in argument, but because it's adapter for our
// descriptors, what we get is actually a general JS cast going via
// Rust input type -> ABI -> JS value -> Rust output type chain.
#[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();
// Pass all inputs and outputs across the opaque FFI boundary to prevent
// compiler from removing them as dead code.
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) 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> {}
/// Wrapper around [`Lazy`] adding `Send + Sync` when `atomics` is not enabled.
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 => {
// TODO: Block here if possible. This would require
// detecting if we can in the first place.
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");
}
/// A vendored version of `RefCell` from the standard library.
///
/// Now why, you may ask, would we do that? Surely `RefCell` in libstd is
/// quite good. And you're right, it is indeed quite good! Functionally
/// nothing more is needed from `RefCell` in the standard library but for
/// now this crate is also sort of optimizing for compiled code size.
///
/// One major factor to larger binaries in Rust is when a panic happens.
/// Panicking in the standard library involves a fair bit of machinery
/// (formatting, panic hooks, synchronization, etc). It's all worthwhile if
/// you need it but for something like `WasmRefCell` here we don't actually
/// need all that!
///
/// This is just a wrapper around all Rust objects passed to JS intended to
/// guard accidental reentrancy, so this vendored version is intended solely
/// to not panic in libstd. Instead when it "panics" it calls our `throw`
/// function in this crate which raises an error in JS.
pub struct WasmRefCell<T: ?Sized> {
borrow: Cell<usize>,
value: UnsafeCell<T>,
}
impl<T: ?Sized> WasmRefCell<T> {
pub fn new(value: T) -> WasmRefCell<T>
where
T: Sized,
{
WasmRefCell {
value: UnsafeCell::new(value),
borrow: Cell::new(0),
}
}
pub fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.value.get() }
}
pub fn borrow(&self) -> Ref<'_, T> {
unsafe {
if self.borrow.get() == usize::MAX {
borrow_fail();
}
self.borrow.set(self.borrow.get() + 1);
Ref {
value: &*self.value.get(),
borrow: &self.borrow,
}
}
}
pub fn borrow_mut(&self) -> RefMut<'_, T> {
unsafe {
if self.borrow.get() != 0 {
borrow_fail();
}
self.borrow.set(usize::MAX);
RefMut {
value: &mut *self.value.get(),
borrow: &self.borrow,
}
}
}
pub fn into_inner(self) -> T
where
T: Sized,
{
self.value.into_inner()
}
}
pub struct Ref<'b, T: ?Sized + 'b> {
value: &'b T,
borrow: &'b Cell<usize>,
}
impl<T: ?Sized> Deref for Ref<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.value
}
}
impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
#[inline]
fn borrow(&self) -> &T {
self.value
}
}
impl<T: ?Sized> Drop for Ref<'_, T> {
fn drop(&mut self) {
self.borrow.set(self.borrow.get() - 1);
}
}
pub struct RefMut<'b, T: ?Sized + 'b> {
value: &'b mut T,
borrow: &'b Cell<usize>,
}
impl<T: ?Sized> Deref for RefMut<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.value
}
}
impl<T: ?Sized> DerefMut for RefMut<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
self.value
}
}
impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
#[inline]
fn borrow(&self) -> &T {
self.value
}
}
impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self.value
}
}
impl<T: ?Sized> Drop for RefMut<'_, T> {
fn drop(&mut self) {
self.borrow.set(0);
}
}
fn borrow_fail() -> ! {
super::throw_str(
"recursive use of an object detected which would lead to \
unsafe aliasing in rust",
);
}
/// A type that encapsulates an `Rc<WasmRefCell<T>>` as well as a `Ref`
/// to the contents of that `WasmRefCell`.
///
/// The `'static` requirement is an unfortunate consequence of how this
/// is implemented.
pub struct RcRef<T: ?Sized + 'static> {
// The 'static is a lie.
//
// We could get away without storing this, since we're in the same module as
// `WasmRefCell` and can directly manipulate its `borrow`, but I'm considering
// turning it into a wrapper around `std`'s `RefCell` to reduce `unsafe` in
// which case that would stop working. This also requires less `unsafe` as is.
//
// It's important that this goes before `Rc` so that it gets dropped first.
ref_: Ref<'static, T>,
_rc: Rc<WasmRefCell<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_
}
}
/// A type that encapsulates an `Rc<WasmRefCell<T>>` as well as a
/// `RefMut` to the contents of that `WasmRefCell`.
///
/// The `'static` requirement is an unfortunate consequence of how this
/// is implemented.
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) {
// This happens for zero-length slices, and in that case `ptr` is
// likely bogus so don't actually send this to the system allocator
if size == 0 {
return;
}
let layout = Layout::from_size_align_unchecked(size, align);
dealloc(ptr, layout);
}
/// This is a curious function necessary to get wasm-bindgen working today,
/// and it's a bit of an unfortunate hack.
///
/// The general problem is that somehow we need the above two symbols to
/// exist in the final output binary (__wbindgen_malloc and
/// __wbindgen_free). These symbols may be called by JS for various
/// bindings, so we for sure need to make sure they're exported.
///
/// The problem arises, though, when what if no Rust code uses the symbols?
/// For all intents and purposes it looks to LLVM and the linker like the
/// above two symbols are dead code, so they're completely discarded!
///
/// Specifically what happens is this:
///
/// * The above two symbols are generated into some object file inside of
/// libwasm_bindgen.rlib
/// * The linker, LLD, will not load this object file unless *some* symbol
/// is loaded from the object. In this case, if the Rust code never calls
/// __wbindgen_malloc or __wbindgen_free then the symbols never get linked
/// in.
/// * Later when `wasm-bindgen` attempts to use the symbols they don't
/// exist, causing an error.
///
/// This function is a weird hack for this problem. We inject a call to this
/// function in all generated code. Usage of this function should then
/// ensure that the above two intrinsics are translated.
///
/// Due to how rustc creates object files this function (and anything inside
/// it) will be placed into the same object file as the two intrinsics
/// above. That means if this function is called and referenced we'll pull
/// in the object file and link the intrinsics.
///
/// Ideas for how to improve this are most welcome!
#[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]));
#[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
}
/// An internal helper trait for usage in `#[wasm_bindgen]` on `async`
/// functions to convert the return value of the function to
/// `Result<JsValue, JsValue>` which is what we'll return to JS (where an
/// error is a failed future).
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()),
}
}
}
/// An internal helper trait for usage in `#[wasm_bindgen(start)]`
/// functions to throw the error (if it is `Err`).
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());
}
}
}
/// An internal helper struct for usage in `#[wasm_bindgen(main)]`
/// functions to throw the error (if it is `Err`).
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
}
// NOTE: This method is used to encode u32 into a variable-length-integer during the compile-time .
// Generally speaking, the length of the encoded variable-length-integer depends on the size of the integer
// but the maximum capacity can be used here to simplify the amount of code during the compile-time .
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
}