summaryrefslogtreecommitdiffstats
path: root/vendor/wasm-bindgen/src/convert
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/wasm-bindgen/src/convert')
-rw-r--r--vendor/wasm-bindgen/src/convert/closures.rs225
-rw-r--r--vendor/wasm-bindgen/src/convert/impls.rs378
-rw-r--r--vendor/wasm-bindgen/src/convert/mod.rs11
-rw-r--r--vendor/wasm-bindgen/src/convert/slices.rs311
-rw-r--r--vendor/wasm-bindgen/src/convert/traits.rs131
5 files changed, 1056 insertions, 0 deletions
diff --git a/vendor/wasm-bindgen/src/convert/closures.rs b/vendor/wasm-bindgen/src/convert/closures.rs
new file mode 100644
index 000000000..97755b8ee
--- /dev/null
+++ b/vendor/wasm-bindgen/src/convert/closures.rs
@@ -0,0 +1,225 @@
+use core::mem;
+
+use crate::convert::slices::WasmSlice;
+use crate::convert::RefFromWasmAbi;
+use crate::convert::{FromWasmAbi, IntoWasmAbi, ReturnWasmAbi};
+use crate::describe::{inform, WasmDescribe, FUNCTION};
+use crate::throw_str;
+
+macro_rules! stack_closures {
+ ($( ($cnt:tt $invoke:ident $invoke_mut:ident $($var:ident)*) )*) => ($(
+ impl<'a, 'b, $($var,)* R> IntoWasmAbi for &'a (dyn Fn($($var),*) -> R + 'b)
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ 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,
+ $($var: <$var as FromWasmAbi>::Abi),*
+ ) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // Scope all local variables before we call `return_abi` to
+ // ensure they're all destroyed as `return_abi` may throw
+ let ret = {
+ let f: &dyn Fn($($var),*) -> R = mem::transmute((a, b));
+ $(
+ let $var = <$var as FromWasmAbi>::from_abi($var);
+ )*
+ f($($var),*)
+ };
+ ret.return_abi()
+ }
+
+ impl<'a, $($var,)* R> WasmDescribe for dyn Fn($($var),*) -> R + 'a
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ fn describe() {
+ inform(FUNCTION);
+ inform($invoke::<$($var,)* R> as u32);
+ inform($cnt);
+ $(<$var as WasmDescribe>::describe();)*
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+ }
+
+ impl<'a, 'b, $($var,)* R> IntoWasmAbi for &'a mut (dyn FnMut($($var),*) -> R + 'b)
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ 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_mut<$($var: FromWasmAbi,)* R: ReturnWasmAbi>(
+ a: usize,
+ b: usize,
+ $($var: <$var as FromWasmAbi>::Abi),*
+ ) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // 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 FnMut($($var),*) -> R = mem::transmute((a, b));
+ $(
+ let $var = <$var as FromWasmAbi>::from_abi($var);
+ )*
+ f($($var),*)
+ };
+ ret.return_abi()
+ }
+
+ impl<'a, $($var,)* R> WasmDescribe for dyn FnMut($($var),*) -> R + 'a
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ fn describe() {
+ inform(FUNCTION);
+ inform($invoke_mut::<$($var,)* R> as u32);
+ inform($cnt);
+ $(<$var as WasmDescribe>::describe();)*
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+ }
+ )*)
+}
+
+stack_closures! {
+ (0 invoke0 invoke0_mut)
+ (1 invoke1 invoke1_mut A)
+ (2 invoke2 invoke2_mut A B)
+ (3 invoke3 invoke3_mut A B C)
+ (4 invoke4 invoke4_mut A B C D)
+ (5 invoke5 invoke5_mut A B C D E)
+ (6 invoke6 invoke6_mut A B C D E F)
+ (7 invoke7 invoke7_mut A B C D E F G)
+ (8 invoke8 invoke8_mut A B C D E F G H)
+}
+
+impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(&A) -> R + 'b)
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ 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 invoke1_ref<A: RefFromWasmAbi, R: ReturnWasmAbi>(
+ a: usize,
+ b: usize,
+ arg: <A as RefFromWasmAbi>::Abi,
+) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // Scope all local variables before we call `return_abi` to
+ // ensure they're all destroyed as `return_abi` may throw
+ let ret = {
+ let f: &dyn Fn(&A) -> R = mem::transmute((a, b));
+ let arg = <A as RefFromWasmAbi>::ref_from_abi(arg);
+ f(&*arg)
+ };
+ ret.return_abi()
+}
+
+impl<'a, A, R> WasmDescribe for dyn Fn(&A) -> R + 'a
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ fn describe() {
+ inform(FUNCTION);
+ inform(invoke1_ref::<A, R> as u32);
+ inform(1);
+ <&A as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+}
+
+impl<'a, 'b, A, R> IntoWasmAbi for &'a mut (dyn FnMut(&A) -> R + 'b)
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ 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 invoke1_mut_ref<A: RefFromWasmAbi, R: ReturnWasmAbi>(
+ a: usize,
+ b: usize,
+ arg: <A as RefFromWasmAbi>::Abi,
+) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // 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 FnMut(&A) -> R = mem::transmute((a, b));
+ let arg = <A as RefFromWasmAbi>::ref_from_abi(arg);
+ f(&*arg)
+ };
+ ret.return_abi()
+}
+
+impl<'a, A, R> WasmDescribe for dyn FnMut(&A) -> R + 'a
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ fn describe() {
+ inform(FUNCTION);
+ inform(invoke1_mut_ref::<A, R> as u32);
+ inform(1);
+ <&A as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+}
diff --git a/vendor/wasm-bindgen/src/convert/impls.rs b/vendor/wasm-bindgen/src/convert/impls.rs
new file mode 100644
index 000000000..79ccd67af
--- /dev/null
+++ b/vendor/wasm-bindgen/src/convert/impls.rs
@@ -0,0 +1,378 @@
+use core::char;
+use core::mem::{self, ManuallyDrop};
+
+use crate::convert::traits::WasmAbi;
+use crate::convert::{FromWasmAbi, IntoWasmAbi, RefFromWasmAbi};
+use crate::convert::{OptionFromWasmAbi, OptionIntoWasmAbi, ReturnWasmAbi};
+use crate::{Clamped, JsError, JsValue};
+
+unsafe impl WasmAbi for () {}
+
+#[repr(C, u32)]
+pub enum WasmOption<T: WasmAbi> {
+ None,
+ Some(T),
+}
+
+unsafe impl<T: WasmAbi> WasmAbi for WasmOption<T> {}
+
+impl<Abi: WasmAbi> WasmOption<Abi> {
+ pub fn from_option<T: IntoWasmAbi<Abi = Abi>>(option: Option<T>) -> Self {
+ match option {
+ Some(v) => WasmOption::Some(v.into_abi()),
+ None => WasmOption::None,
+ }
+ }
+
+ pub unsafe fn into_option<T: FromWasmAbi<Abi = Abi>>(v: Self) -> Option<T> {
+ match v {
+ WasmOption::Some(v) => Some(T::from_abi(v)),
+ WasmOption::None => None,
+ }
+ }
+}
+
+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 = WasmOption<$c>;
+
+ #[inline]
+ fn into_abi(self) -> Self::Abi {
+ WasmOption::from_option(self.map(|v| v as $c))
+ }
+ }
+
+ impl FromWasmAbi for Option<$t> {
+ type Abi = WasmOption<$c>;
+
+ #[inline]
+ unsafe fn from_abi(js: Self::Abi) -> Self {
+ WasmOption::into_option(js).map(|v: $c| v as $t)
+ }
+ }
+ )*)
+}
+
+type_wasm_native!(
+ i32 as i32
+ isize as i32
+ u32 as u32
+ usize as u32
+ i64 as i64
+ u64 as u64
+ f32 as f32
+ f64 as f64
+);
+
+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 { 0x00FF_FFFFu32 }
+ }
+
+ impl OptionFromWasmAbi for $t {
+ #[inline]
+ fn is_none(js: &u32) -> bool { *js == 0x00FF_FFFFu32 }
+ }
+ )*)
+}
+
+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 {
+ 0x00FF_FFFFu32
+ }
+}
+
+impl OptionFromWasmAbi for bool {
+ #[inline]
+ fn is_none(js: &u32) -> bool {
+ *js == 0x00FF_FFFFu32
+ }
+}
+
+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 {
+ char::from_u32_unchecked(js)
+ }
+}
+
+impl OptionIntoWasmAbi for char {
+ #[inline]
+ fn none() -> u32 {
+ 0x00FF_FFFFu32
+ }
+}
+
+impl OptionFromWasmAbi for char {
+ #[inline]
+ fn is_none(js: &u32) -> bool {
+ *js == 0x00FF_FFFFu32
+ }
+}
+
+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 *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 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<'a> IntoWasmAbi for &'a 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<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
+ }
+}
+
+/// This is an encoding of a Result. It can only store things that can be decoded by the JS
+/// bindings.
+///
+/// At the moment, we do not write the exact struct packing layout of everything into the
+/// glue/descriptions of datatypes, so T cannot be arbitrary. The current requirements of the
+/// struct unpacker (StructUnpacker), which apply to ResultAbi<T> as a whole, are as follows:
+///
+/// - repr(C), of course
+/// - u32/i32/f32/f64 fields at the "leaf fields" of the "field tree"
+/// - layout equivalent to a completely flattened repr(C) struct, constructed by an in order
+/// traversal of all the leaf fields in it.
+///
+/// This means that you can't embed struct A(u32, f64) as struct B(u32, A); because the "completely
+/// flattened" struct AB(u32, u32, f64) would miss the 4 byte padding that is actually present
+/// within B and then as a consequence also miss the 4 byte padding within A that repr(C) inserts.
+///
+/// The enemy is padding. Padding is only required when there is an `f64` field. So the enemy is
+/// `f64` after anything else, particularly anything arbitrary. There is no smaller sized type, so
+/// we don't need to worry about 1-byte integers, etc. It's best, therefore, to place your f64s
+/// first in your structs, that's why we have `abi` first, although here it doesn't matter as the
+/// other two fields total 8 bytes anyway.
+///
+#[repr(C)]
+pub struct ResultAbi<T> {
+ /// This field is the same size/align as `T`.
+ abi: ResultAbiUnion<T>,
+ /// Order of args here is such that we can pop() the possible error first, deal with it and
+ /// move on. Later fields are popped off the stack first.
+ err: u32,
+ is_err: u32,
+}
+
+#[repr(C)]
+pub union ResultAbiUnion<T> {
+ // ManuallyDrop is #[repr(transparent)]
+ ok: std::mem::ManuallyDrop<T>,
+ err: (),
+}
+
+unsafe impl<T: WasmAbi> WasmAbi for ResultAbi<T> {}
+unsafe impl<T: WasmAbi> WasmAbi for ResultAbiUnion<T> {}
+
+impl<T: IntoWasmAbi, E: Into<JsValue>> ReturnWasmAbi for Result<T, E> {
+ type Abi = ResultAbi<T::Abi>;
+ #[inline]
+ fn return_abi(self) -> Self::Abi {
+ match self {
+ Ok(v) => {
+ let abi = ResultAbiUnion {
+ ok: std::mem::ManuallyDrop::new(v.into_abi()),
+ };
+ ResultAbi {
+ abi,
+ is_err: 0,
+ err: 0,
+ }
+ }
+ Err(e) => {
+ let jsval = e.into();
+ ResultAbi {
+ abi: ResultAbiUnion { err: () },
+ is_err: 1,
+ err: jsval.into_abi(),
+ }
+ }
+ }
+ }
+}
+
+impl IntoWasmAbi for JsError {
+ type Abi = <JsValue as IntoWasmAbi>::Abi;
+
+ fn into_abi(self) -> Self::Abi {
+ self.value.into_abi()
+ }
+}
diff --git a/vendor/wasm-bindgen/src/convert/mod.rs b/vendor/wasm-bindgen/src/convert/mod.rs
new file mode 100644
index 000000000..ce2c0b2c8
--- /dev/null
+++ b/vendor/wasm-bindgen/src/convert/mod.rs
@@ -0,0 +1,11 @@
+//! This is mostly an internal module, no stability guarantees are provided. Use
+//! at your own risk.
+
+mod closures;
+mod impls;
+mod slices;
+mod traits;
+
+pub use self::impls::*;
+pub use self::slices::WasmSlice;
+pub use self::traits::*;
diff --git a/vendor/wasm-bindgen/src/convert/slices.rs b/vendor/wasm-bindgen/src/convert/slices.rs
new file mode 100644
index 000000000..9d0970f4e
--- /dev/null
+++ b/vendor/wasm-bindgen/src/convert/slices.rs
@@ -0,0 +1,311 @@
+#[cfg(feature = "std")]
+use std::prelude::v1::*;
+
+use core::slice;
+use core::str;
+
+use crate::cast::JsObject;
+use crate::convert::OptionIntoWasmAbi;
+use crate::convert::{FromWasmAbi, IntoWasmAbi, RefFromWasmAbi, RefMutFromWasmAbi, WasmAbi};
+use cfg_if::cfg_if;
+
+if_std! {
+ use core::mem;
+ use crate::convert::OptionFromWasmAbi;
+}
+
+#[repr(C)]
+pub struct WasmSlice {
+ pub ptr: u32,
+ pub len: u32,
+}
+
+unsafe impl WasmAbi for WasmSlice {}
+
+#[inline]
+fn null_slice() -> WasmSlice {
+ WasmSlice { ptr: 0, len: 0 }
+}
+
+macro_rules! vectors {
+ ($($t:ident)*) => ($(
+ if_std! {
+ impl IntoWasmAbi for Box<[$t]> {
+ type Abi = WasmSlice;
+
+ #[inline]
+ fn into_abi(self) -> WasmSlice {
+ let ptr = self.as_ptr();
+ let len = self.len();
+ mem::forget(self);
+ WasmSlice {
+ ptr: ptr.into_abi(),
+ len: len as u32,
+ }
+ }
+ }
+
+ impl OptionIntoWasmAbi for Box<[$t]> {
+ #[inline]
+ fn none() -> WasmSlice { null_slice() }
+ }
+
+ impl FromWasmAbi for Box<[$t]> {
+ type Abi = WasmSlice;
+
+ #[inline]
+ unsafe fn from_abi(js: WasmSlice) -> 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 OptionFromWasmAbi for Box<[$t]> {
+ #[inline]
+ fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 }
+ }
+ }
+
+ 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 = WasmSlice;
+ type Anchor = &'static mut [$t];
+
+ #[inline]
+ unsafe fn ref_mut_from_abi(js: WasmSlice)
+ -> &'static mut [$t]
+ {
+ slice::from_raw_parts_mut(
+ <*mut $t>::from_abi(js.ptr),
+ js.len as usize,
+ )
+ }
+ }
+ )*)
+}
+
+vectors! {
+ u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64
+}
+
+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
+ }
+ }
+}
+
+if_std! {
+ 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<'a> OptionIntoWasmAbi for &'a 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))
+ }
+}
+
+if_std! {
+ use crate::JsValue;
+
+ impl IntoWasmAbi for Box<[JsValue]> {
+ type Abi = WasmSlice;
+
+ #[inline]
+ fn into_abi(self) -> WasmSlice {
+ let ptr = self.as_ptr();
+ let len = self.len();
+ mem::forget(self);
+ WasmSlice {
+ ptr: ptr.into_abi(),
+ len: len as u32,
+ }
+ }
+ }
+
+ impl OptionIntoWasmAbi for Box<[JsValue]> {
+ #[inline]
+ fn none() -> WasmSlice { null_slice() }
+ }
+
+ impl FromWasmAbi for Box<[JsValue]> {
+ type Abi = WasmSlice;
+
+ #[inline]
+ unsafe fn from_abi(js: WasmSlice) -> Self {
+ let ptr = <*mut JsValue>::from_abi(js.ptr);
+ let len = js.len as usize;
+ Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
+ }
+ }
+
+ impl OptionFromWasmAbi for Box<[JsValue]> {
+ #[inline]
+ fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 }
+ }
+
+ impl<T> IntoWasmAbi for Box<[T]> where T: JsObject {
+ type Abi = WasmSlice;
+
+ #[inline]
+ fn into_abi(self) -> WasmSlice {
+ let ptr = self.as_ptr();
+ let len = self.len();
+ mem::forget(self);
+ WasmSlice {
+ ptr: ptr.into_abi(),
+ len: len as u32,
+ }
+ }
+ }
+
+ impl<T> OptionIntoWasmAbi for Box<[T]> where T: JsObject {
+ #[inline]
+ fn none() -> WasmSlice { null_slice() }
+ }
+
+ impl<T> FromWasmAbi for Box<[T]> where T: JsObject {
+ type Abi = WasmSlice;
+
+ #[inline]
+ unsafe fn from_abi(js: WasmSlice) -> Self {
+ let ptr = <*mut JsValue>::from_abi(js.ptr);
+ let len = js.len as usize;
+ let vec: Vec<T> = Vec::from_raw_parts(ptr, len, len).drain(..).map(|js_value| T::unchecked_from_js(js_value)).collect();
+ return vec.into_boxed_slice();
+ }
+ }
+
+ impl<T> OptionFromWasmAbi for Box<[T]> where T: JsObject {
+ #[inline]
+ fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 }
+ }
+}
diff --git a/vendor/wasm-bindgen/src/convert/traits.rs b/vendor/wasm-bindgen/src/convert/traits.rs
new file mode 100644
index 000000000..b9d12b4c8
--- /dev/null
+++ b/vendor/wasm-bindgen/src/convert/traits.rs
@@ -0,0 +1,131 @@
+use core::ops::{Deref, DerefMut};
+
+use crate::describe::*;
+
+/// 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`.
+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`.
+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`.
+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;
+}
+
+/// Dual of the `RefFromWasmAbi` trait, except for mutable references.
+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>`.
+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>`.
+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;
+}
+
+/// An unsafe trait which represents types that are ABI-safe to pass via wasm
+/// arguments.
+///
+/// This is an unsafe trait to implement as there's no guarantee the type is
+/// actually safe to transfer across the was boundary, it's up to you to
+/// guarantee this so codegen works correctly.
+pub unsafe trait WasmAbi {}
+
+unsafe impl WasmAbi for u32 {}
+unsafe impl WasmAbi for i32 {}
+unsafe impl WasmAbi for u64 {}
+unsafe impl WasmAbi for i64 {}
+unsafe impl WasmAbi for f32 {}
+unsafe impl WasmAbi for f64 {}
+
+/// A trait representing how to interepret 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"
+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()
+ }
+}