Fix no-std compatibility (#4005)

This commit is contained in:
Chris 2024-07-29 00:14:06 +02:00 committed by GitHub
parent 7ad1a2703d
commit 06b347f908
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 678 additions and 643 deletions

View File

@ -37,6 +37,7 @@ jobs:
- uses: actions/checkout@v4
- run: rustup update --no-self-update stable && rustup default stable
- run: cargo check --all
- run: cargo check --no-default-features
# Run `cargo clippy` over everything
clippy:
@ -66,6 +67,7 @@ jobs:
- run: cargo clippy --no-deps --all-features -p wasm-bindgen-webidl -- -D warnings
- run: cargo clippy --no-deps --all-features -p webidl-tests -- -D warnings
- run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p web-sys -- -D warnings
- run: cargo clippy --no-deps --no-default-features --target wasm32-unknown-unknown -- -D warnings
- run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -- -D warnings
- run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown --tests -- -D warnings
- run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-benchmark -- -D warnings

View File

@ -130,6 +130,9 @@
* Fix `__wbindgen_thread_destroy()` ignoring parameters.
[#3995](https://github.com/rustwasm/wasm-bindgen/pull/3995)
* Fix `no_std` support and therefor compiling with `default-features = false`.
[#4005](https://github.com/rustwasm/wasm-bindgen/pull/4005)
--------------------------------------------------------------------------------
## [0.2.92](https://github.com/rustwasm/wasm-bindgen/compare/0.2.91...0.2.92)

View File

@ -221,12 +221,6 @@ impl ToTokens for ast::Struct {
impl #wasm_bindgen::describe::WasmDescribe for #name {
fn describe() {
use #wasm_bindgen::__wbindgen_if_not_std;
__wbindgen_if_not_std! {
compile_error! {
"exporting a class to JS requires the `std` feature to \
be enabled in the `wasm-bindgen` crate"
}
}
use #wasm_bindgen::describe::*;
inform(RUST_STRUCT);
inform(#name_len);
@ -239,7 +233,7 @@ impl ToTokens for ast::Struct {
type Abi = u32;
fn into_abi(self) -> u32 {
use #wasm_bindgen::__rt::std::rc::Rc;
use #wasm_bindgen::__rt::alloc::rc::Rc;
use #wasm_bindgen::__rt::WasmRefCell;
Rc::into_raw(Rc::new(WasmRefCell::new(self))) as u32
}
@ -250,8 +244,8 @@ impl ToTokens for ast::Struct {
type Abi = u32;
unsafe fn from_abi(js: u32) -> Self {
use #wasm_bindgen::__rt::std::rc::Rc;
use #wasm_bindgen::__rt::std::result::Result::{Ok, Err};
use #wasm_bindgen::__rt::alloc::rc::Rc;
use #wasm_bindgen::__rt::core::result::Result::{Ok, Err};
use #wasm_bindgen::__rt::{assert_not_null, WasmRefCell};
let ptr = js as *mut WasmRefCell<#name>;
@ -299,7 +293,7 @@ impl ToTokens for ast::Struct {
// `allow_delayed` is whether it's ok to not actually free the `ptr` immediately
// if it's still borrowed.
pub unsafe extern "C" fn #free_fn(ptr: u32, allow_delayed: u32) {
use #wasm_bindgen::__rt::std::rc::Rc;
use #wasm_bindgen::__rt::alloc::rc::Rc;
if allow_delayed != 0 {
// Just drop the implicit `Rc` owned by JS, and then if the value is still
@ -320,7 +314,7 @@ impl ToTokens for ast::Struct {
type Anchor = #wasm_bindgen::__rt::RcRef<#name>;
unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor {
use #wasm_bindgen::__rt::std::rc::Rc;
use #wasm_bindgen::__rt::alloc::rc::Rc;
let js = js as *mut #wasm_bindgen::__rt::WasmRefCell<#name>;
#wasm_bindgen::__rt::assert_not_null(js);
@ -337,7 +331,7 @@ impl ToTokens for ast::Struct {
type Anchor = #wasm_bindgen::__rt::RcRefMut<#name>;
unsafe fn ref_mut_from_abi(js: Self::Abi) -> Self::Anchor {
use #wasm_bindgen::__rt::std::rc::Rc;
use #wasm_bindgen::__rt::alloc::rc::Rc;
let js = js as *mut #wasm_bindgen::__rt::WasmRefCell<#name>;
#wasm_bindgen::__rt::assert_not_null(js);
@ -375,7 +369,7 @@ impl ToTokens for ast::Struct {
type Error = #wasm_bindgen::JsValue;
fn try_from_js_value(value: #wasm_bindgen::JsValue)
-> #wasm_bindgen::__rt::std::result::Result<Self, Self::Error> {
-> #wasm_bindgen::__rt::core::result::Result<Self, Self::Error> {
let idx = #wasm_bindgen::convert::IntoWasmAbi::into_abi(&value);
#[link(wasm_import_module = "__wbindgen_placeholder__")]
@ -391,13 +385,13 @@ impl ToTokens for ast::Struct {
let ptr = unsafe { #unwrap_fn(idx) };
if ptr == 0 {
#wasm_bindgen::__rt::std::result::Result::Err(value)
#wasm_bindgen::__rt::core::result::Result::Err(value)
} else {
// Don't run `JsValue`'s destructor, `unwrap_fn` already did that for us.
#[allow(clippy::mem_forget)]
#wasm_bindgen::__rt::std::mem::forget(value);
#wasm_bindgen::__rt::core::mem::forget(value);
unsafe {
#wasm_bindgen::__rt::std::result::Result::Ok(
#wasm_bindgen::__rt::core::result::Result::Ok(
<Self as #wasm_bindgen::convert::FromWasmAbi>::from_abi(ptr)
)
}
@ -417,12 +411,12 @@ impl ToTokens for ast::Struct {
impl #wasm_bindgen::convert::VectorIntoWasmAbi for #name {
type Abi = <
#wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]>
#wasm_bindgen::__rt::alloc::boxed::Box<[#wasm_bindgen::JsValue]>
as #wasm_bindgen::convert::IntoWasmAbi
>::Abi;
fn vector_into_abi(
vector: #wasm_bindgen::__rt::std::boxed::Box<[#name]>
vector: #wasm_bindgen::__rt::alloc::boxed::Box<[#name]>
) -> Self::Abi {
#wasm_bindgen::convert::js_value_vector_into_abi(vector)
}
@ -430,19 +424,19 @@ impl ToTokens for ast::Struct {
impl #wasm_bindgen::convert::VectorFromWasmAbi for #name {
type Abi = <
#wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]>
#wasm_bindgen::__rt::alloc::boxed::Box<[#wasm_bindgen::JsValue]>
as #wasm_bindgen::convert::FromWasmAbi
>::Abi;
unsafe fn vector_from_abi(
js: Self::Abi
) -> #wasm_bindgen::__rt::std::boxed::Box<[#name]> {
) -> #wasm_bindgen::__rt::alloc::boxed::Box<[#name]> {
#wasm_bindgen::convert::js_value_vector_from_abi(js)
}
}
impl #wasm_bindgen::__rt::VectorIntoJsValue for #name {
fn vector_into_jsvalue(vector: #wasm_bindgen::__rt::std::boxed::Box<[#name]>) -> #wasm_bindgen::JsValue {
fn vector_into_jsvalue(vector: #wasm_bindgen::__rt::alloc::boxed::Box<[#name]>) -> #wasm_bindgen::JsValue {
#wasm_bindgen::__rt::js_value_vector_into_jsvalue(vector)
}
}
@ -597,7 +591,7 @@ impl TryToTokens for ast::Export {
quote!(long_ref_from_abi),
quote!(
<<#class as #wasm_bindgen::convert::LongRefFromWasmAbi>
::Anchor as #wasm_bindgen::__rt::std::borrow::Borrow<#class>>
::Anchor as #wasm_bindgen::__rt::core::borrow::Borrow<#class>>
::borrow(&me)
),
)
@ -1589,13 +1583,13 @@ impl ToTokens for ast::Enum {
type Error = #wasm_bindgen::JsValue;
fn try_from_js_value(value: #wasm_bindgen::JsValue)
-> #wasm_bindgen::__rt::std::result::Result<Self, <#enum_name as #wasm_bindgen::convert::TryFromJsValue>::Error> {
-> #wasm_bindgen::__rt::core::result::Result<Self, <#enum_name as #wasm_bindgen::convert::TryFromJsValue>::Error> {
use #wasm_bindgen::__rt::core::convert::TryFrom;
let js = f64::try_from(&value)? as u32;
#wasm_bindgen::__rt::std::result::Result::Ok(
#wasm_bindgen::__rt::core::result::Result::Ok(
#(#try_from_cast_clauses else)* {
return #wasm_bindgen::__rt::std::result::Result::Err(value)
return #wasm_bindgen::__rt::core::result::Result::Err(value)
}
)
}
@ -1611,12 +1605,12 @@ impl ToTokens for ast::Enum {
impl #wasm_bindgen::convert::VectorIntoWasmAbi for #enum_name {
type Abi = <
#wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]>
#wasm_bindgen::__rt::alloc::boxed::Box<[#wasm_bindgen::JsValue]>
as #wasm_bindgen::convert::IntoWasmAbi
>::Abi;
fn vector_into_abi(
vector: #wasm_bindgen::__rt::std::boxed::Box<[#enum_name]>
vector: #wasm_bindgen::__rt::alloc::boxed::Box<[#enum_name]>
) -> Self::Abi {
#wasm_bindgen::convert::js_value_vector_into_abi(vector)
}
@ -1624,19 +1618,19 @@ impl ToTokens for ast::Enum {
impl #wasm_bindgen::convert::VectorFromWasmAbi for #enum_name {
type Abi = <
#wasm_bindgen::__rt::std::boxed::Box<[#wasm_bindgen::JsValue]>
#wasm_bindgen::__rt::alloc::boxed::Box<[#wasm_bindgen::JsValue]>
as #wasm_bindgen::convert::FromWasmAbi
>::Abi;
unsafe fn vector_from_abi(
js: Self::Abi
) -> #wasm_bindgen::__rt::std::boxed::Box<[#enum_name]> {
) -> #wasm_bindgen::__rt::alloc::boxed::Box<[#enum_name]> {
#wasm_bindgen::convert::js_value_vector_from_abi(js)
}
}
impl #wasm_bindgen::__rt::VectorIntoJsValue for #enum_name {
fn vector_into_jsvalue(vector: #wasm_bindgen::__rt::std::boxed::Box<[#enum_name]>) -> #wasm_bindgen::JsValue {
fn vector_into_jsvalue(vector: #wasm_bindgen::__rt::alloc::boxed::Box<[#enum_name]>) -> #wasm_bindgen::JsValue {
#wasm_bindgen::__rt::js_value_vector_into_jsvalue(vector)
}
}

View File

@ -6,9 +6,10 @@
#![allow(clippy::fn_to_numeric_cast)]
use std::fmt;
use std::mem::{self, ManuallyDrop};
use std::prelude::v1::*;
use alloc::boxed::Box;
use alloc::string::String;
use core::fmt;
use core::mem::{self, ManuallyDrop};
use crate::convert::*;
use crate::describe::*;
@ -356,7 +357,7 @@ where
/// 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
@ -685,7 +686,7 @@ macro_rules! doit {
}
fn into_js_function(self) -> JsValue {
use std::rc::Rc;
use alloc::rc::Rc;
use crate::__rt::WasmRefCell;
let mut me = Some(self);
@ -866,7 +867,7 @@ where
fn into_js_function(self) -> JsValue {
use crate::__rt::WasmRefCell;
use std::rc::Rc;
use alloc::rc::Rc;
let mut me = Some(self);

View File

@ -1,4 +1,7 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::char;
use core::fmt::Debug;
use core::mem::{self, ManuallyDrop};
use core::ptr::NonNull;
@ -8,12 +11,6 @@ use crate::convert::{FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, RefFromWasmAb
use crate::convert::{OptionFromWasmAbi, OptionIntoWasmAbi, ReturnWasmAbi};
use crate::{Clamped, JsError, JsValue, UnwrapThrowExt};
if_std! {
use std::boxed::Box;
use std::fmt::Debug;
use std::vec::Vec;
}
// Primitive types can always be passed over the ABI.
impl<T: WasmPrimitive> WasmAbi for T {
type Prim1 = Self;
@ -473,36 +470,39 @@ impl IntoWasmAbi for JsError {
}
}
if_std! {
// 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();
// 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()
}
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()
}
js_vals.into_abi()
}
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()
}

View File

@ -1,24 +1,24 @@
#[cfg(feature = "std")]
use std::prelude::v1::*;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::mem;
use core::ops::{Deref, DerefMut};
use core::str;
use crate::__wbindgen_copy_to_typed_array;
use crate::cast::JsObject;
use crate::convert::OptionIntoWasmAbi;
use crate::convert::{js_value_vector_from_abi, js_value_vector_into_abi};
use crate::convert::{
FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, RefFromWasmAbi, RefMutFromWasmAbi, WasmAbi,
FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, OptionFromWasmAbi, OptionIntoWasmAbi,
RefFromWasmAbi, RefMutFromWasmAbi, VectorFromWasmAbi, VectorIntoWasmAbi, WasmAbi,
};
use crate::convert::{VectorFromWasmAbi, VectorIntoWasmAbi};
use crate::describe::*;
use cfg_if::cfg_if;
use crate::JsValue;
if_std! {
use core::mem;
use crate::convert::OptionFromWasmAbi;
use crate::convert::{js_value_vector_from_abi, js_value_vector_into_abi};
}
use cfg_if::cfg_if;
// 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
@ -53,104 +53,100 @@ fn null_slice() -> WasmSlice {
WasmSlice { ptr: 0, len: 0 }
}
if_std! {
pub struct WasmMutSlice {
pub slice: WasmSlice,
pub idx: u32,
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, ())
}
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,
}
#[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,
}
/// 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) {
unsafe {
__wbindgen_copy_to_typed_array(
self.contents.as_ptr() as *const u8,
self.contents.len() * mem::size_of::<T>(),
self.js.idx
);
}
impl<T> Drop for MutSlice<T> {
fn drop(&mut self) {
unsafe {
__wbindgen_copy_to_typed_array(
self.contents.as_ptr() as *const u8,
self.contents.len() * mem::size_of::<T>(),
self.js.idx,
);
}
}
}
impl<T> Deref for MutSlice<T> {
type Target = [T];
impl<T> Deref for MutSlice<T> {
type Target = [T];
fn deref(&self) -> &[T] {
&self.contents
}
fn deref(&self) -> &[T] {
&self.contents
}
}
impl<T> DerefMut for MutSlice<T> {
fn deref_mut(&mut self) -> &mut [T] {
&mut self.contents
}
impl<T> DerefMut for MutSlice<T> {
fn deref_mut(&mut self) -> &mut [T] {
&mut self.contents
}
}
macro_rules! vectors {
($($t:ident)*) => ($(
if_std! {
impl WasmDescribeVector for $t {
fn describe_vector() {
inform(VECTOR);
$t::describe();
impl WasmDescribeVector for $t {
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 VectorIntoWasmAbi for $t {
type Abi = WasmSlice;
impl VectorFromWasmAbi 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()
}
#[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()
}
}
@ -223,36 +219,34 @@ vectors! {
u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64
}
if_std! {
impl WasmDescribeVector for String {
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 WasmDescribeVector for String {
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;
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)
}
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;
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)
}
unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]> {
js_value_vector_from_abi(js)
}
}
@ -272,63 +266,81 @@ cfg_if! {
}
}
if_std! {
impl<T> IntoWasmAbi for Vec<T> where Box<[T]>: IntoWasmAbi<Abi = WasmSlice> {
type Abi = <Box<[T]> as IntoWasmAbi>::Abi;
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()
}
#[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> 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;
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()
}
#[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<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;
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())
}
#[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 OptionIntoWasmAbi for String {
#[inline]
fn none() -> Self::Abi {
null_slice()
}
}
impl FromWasmAbi for String {
type Abi = <Vec<u8> as FromWasmAbi>::Abi;
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))
}
#[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 OptionFromWasmAbi for String {
#[inline]
fn is_none(slice: &WasmSlice) -> bool {
slice.ptr == 0
}
}
@ -370,87 +382,98 @@ impl LongRefFromWasmAbi for str {
}
}
if_std! {
use crate::JsValue;
impl<T: VectorIntoWasmAbi> IntoWasmAbi for Box<[T]> {
type Abi = <T as VectorIntoWasmAbi>::Abi;
impl<T: VectorIntoWasmAbi> IntoWasmAbi for Box<[T]> {
type Abi = <T as VectorIntoWasmAbi>::Abi;
fn into_abi(self) -> Self::Abi {
T::vector_into_abi(self)
}
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> 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;
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)
}
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> OptionFromWasmAbi for Box<[T]>
where
Self: FromWasmAbi<Abi = WasmSlice>,
{
fn is_none(slice: &WasmSlice) -> bool {
slice.ptr == 0
}
}
impl VectorIntoWasmAbi for JsValue {
type Abi = WasmSlice;
impl VectorIntoWasmAbi for JsValue {
type Abi = WasmSlice;
#[inline]
fn vector_into_abi(vector: Box<[Self]>) -> 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 JsValue {
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[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<T> VectorIntoWasmAbi for T where T: JsObject {
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<T> VectorFromWasmAbi for T where T: JsObject {
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[T]> {
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();
vec.into_boxed_slice()
#[inline]
fn vector_into_abi(vector: Box<[Self]>) -> 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 JsValue {
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[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<T> VectorIntoWasmAbi for T
where
T: JsObject,
{
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<T> VectorFromWasmAbi for T
where
T: JsObject,
{
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[T]> {
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();
vec.into_boxed_slice()
}
}

View File

@ -192,25 +192,23 @@ impl<T: IntoWasmAbi> ReturnWasmAbi for T {
}
}
if_std! {
use core::marker::Sized;
use std::boxed::Box;
use alloc::boxed::Box;
use core::marker::Sized;
/// Trait for element types to implement IntoWasmAbi for vectors of
/// themselves.
pub trait VectorIntoWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
/// Trait for element types to implement IntoWasmAbi for vectors of
/// themselves.
pub trait VectorIntoWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi;
}
fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi;
}
/// Trait for element types to implement FromWasmAbi for vectors of
/// themselves.
pub trait VectorFromWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
/// Trait for element types to implement FromWasmAbi for vectors of
/// themselves.
pub trait VectorFromWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]>;
}
unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]>;
}
/// A repr(C) struct containing all of the primitives of a `WasmAbi` type, in

View File

@ -3,6 +3,9 @@
#![doc(hidden)]
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::ptr::NonNull;
use crate::{Clamped, JsError, JsObject, JsValue};
@ -145,46 +148,45 @@ impl<'a, T: WasmDescribe + ?Sized> WasmDescribe for &'a mut T {
}
}
if_std! {
use std::prelude::v1::*;
cfg_if! {
if #[cfg(feature = "enable-interning")] {
simple! {
String => CACHED_STRING
}
cfg_if! {
if #[cfg(feature = "enable-interning")] {
simple! {
String => CACHED_STRING
}
} else {
simple! {
String => STRING
}
} else {
simple! {
String => STRING
}
}
}
impl WasmDescribeVector for JsValue {
fn describe_vector() {
inform(VECTOR);
JsValue::describe();
}
impl WasmDescribeVector for JsValue {
fn describe_vector() {
inform(VECTOR);
JsValue::describe();
}
}
impl<T: JsObject> WasmDescribeVector for T {
fn describe_vector() {
inform(VECTOR);
T::describe();
}
impl<T: JsObject> WasmDescribeVector for T {
fn describe_vector() {
inform(VECTOR);
T::describe();
}
}
impl<T: WasmDescribeVector> WasmDescribe for Box<[T]> {
fn describe() {
T::describe_vector();
}
impl<T: WasmDescribeVector> WasmDescribe for Box<[T]> {
fn describe() {
T::describe_vector();
}
}
impl<T> WasmDescribe for Vec<T> where Box<[T]>: WasmDescribe {
fn describe() {
<Box<[T]>>::describe();
}
impl<T> WasmDescribe for Vec<T>
where
Box<[T]>: WasmDescribe,
{
fn describe() {
<Box<[T]>>::describe();
}
}

View File

@ -1,8 +1,9 @@
use crate::JsValue;
use std::cell::Cell;
use std::slice;
use std::vec::Vec;
use std::cmp::max;
use alloc::slice;
use alloc::vec::Vec;
use core::cell::Cell;
use core::cmp::max;
externs! {
#[link(wasm_import_module = "__wbindgen_externref_xform__")]
@ -98,10 +99,19 @@ impl Slab {
}
fn internal_error(msg: &str) -> ! {
if cfg!(debug_assertions) {
super::throw_str(msg)
} else {
std::process::abort()
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",
not(any(target_os = "emscripten", target_os = "wasi"))
))] {
core::arch::wasm32::unreachable();
} else {
unreachable!()
}
}
}
@ -160,7 +170,3 @@ pub unsafe extern "C" fn __externref_heap_live_count() -> u32 {
})
.unwrap_or_else(|_| internal_error("tls access failure"))
}
// see comment in module above this in `link_mem_intrinsics`
#[inline(never)]
pub fn link_intrinsics() {}

View File

@ -9,8 +9,12 @@
#![allow(coherence_leak_check)]
#![doc(html_root_url = "https://docs.rs/wasm-bindgen/0.2")]
extern crate alloc;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::convert::TryFrom;
use core::fmt;
use core::marker;
use core::mem;
use core::ops::{
@ -50,6 +54,7 @@ macro_rules! externs {
/// use wasm_bindgen::prelude::*;
/// ```
pub mod prelude {
pub use crate::closure::Closure;
pub use crate::JsCast;
pub use crate::JsValue;
pub use crate::UnwrapThrowExt;
@ -57,17 +62,15 @@ pub mod prelude {
pub use wasm_bindgen_macro::__wasm_bindgen_class_marker;
pub use wasm_bindgen_macro::wasm_bindgen;
if_std! {
pub use crate::closure::Closure;
}
pub use crate::JsError;
}
pub use wasm_bindgen_macro::link_to;
pub mod closure;
pub mod convert;
pub mod describe;
mod link;
mod cast;
pub use crate::cast::{JsCast, JsObject};
@ -75,9 +78,7 @@ pub use crate::cast::{JsCast, JsObject};
if_std! {
extern crate std;
use std::prelude::v1::*;
pub mod closure;
mod externref;
mod cache;
pub use cache::intern::{intern, unintern};
}
@ -293,7 +294,6 @@ impl JsValue {
/// caveats about the encodings.
///
/// [caveats]: https://rustwasm.github.io/docs/wasm-bindgen/reference/types/str.html
#[cfg(feature = "std")]
#[inline]
pub fn as_string(&self) -> Option<String> {
unsafe { FromWasmAbi::from_abi(__wbindgen_string_get(self.idx)) }
@ -512,18 +512,16 @@ impl<'a> PartialEq<&'a str> for JsValue {
}
}
if_std! {
impl PartialEq<String> for JsValue {
#[inline]
fn eq(&self, other: &String) -> bool {
<JsValue as PartialEq<str>>::eq(self, other)
}
impl PartialEq<String> for JsValue {
#[inline]
fn eq(&self, other: &String) -> bool {
<JsValue as PartialEq<str>>::eq(self, other)
}
impl<'a> PartialEq<&'a String> for JsValue {
#[inline]
fn eq(&self, other: &&'a String) -> bool {
<JsValue as PartialEq<str>>::eq(self, other)
}
}
impl<'a> PartialEq<&'a String> for JsValue {
#[inline]
fn eq(&self, other: &&'a String) -> bool {
<JsValue as PartialEq<str>>::eq(self, other)
}
}
@ -797,40 +795,38 @@ impl<T> From<NonNull<T>> for JsValue {
}
}
if_std! {
impl<'a> From<&'a String> for JsValue {
#[inline]
fn from(s: &'a String) -> JsValue {
JsValue::from_str(s)
impl<'a> From<&'a String> for JsValue {
#[inline]
fn from(s: &'a String) -> JsValue {
JsValue::from_str(s)
}
}
impl From<String> for JsValue {
#[inline]
fn from(s: String) -> JsValue {
JsValue::from_str(&s)
}
}
impl TryFrom<JsValue> for String {
type Error = JsValue;
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
match value.as_string() {
Some(s) => Ok(s),
None => Err(value),
}
}
}
impl From<String> for JsValue {
#[inline]
fn from(s: String) -> JsValue {
JsValue::from_str(&s)
}
}
impl TryFromJsValue for String {
type Error = JsValue;
impl TryFrom<JsValue> for String {
type Error = JsValue;
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
match value.as_string() {
Some(s) => Ok(s),
None => Err(value),
}
}
}
impl TryFromJsValue for String {
type Error = JsValue;
fn try_from_js_value(value: JsValue) -> Result<Self, Self::Error> {
match value.as_string() {
Some(s) => Ok(s),
None => Err(value),
}
fn try_from_js_value(value: JsValue) -> Result<Self, Self::Error> {
match value.as_string() {
Some(s) => Ok(s),
None => Err(value),
}
}
}
@ -1132,15 +1128,15 @@ impl Clone for JsValue {
}
#[cfg(feature = "std")]
impl fmt::Debug for JsValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl core::fmt::Debug for JsValue {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "JsValue({})", self.as_debug_string())
}
}
#[cfg(not(feature = "std"))]
impl fmt::Debug for JsValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl core::fmt::Debug for JsValue {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.write_str("JsValue")
}
}
@ -1345,7 +1341,7 @@ pub trait UnwrapThrowExt<T>: Sized {
fn unwrap_throw(self) -> T {
if cfg!(all(debug_assertions, feature = "std")) {
let loc = core::panic::Location::caller();
let msg = std::format!(
let msg = alloc::format!(
"`unwrap_throw` failed ({}:{}:{})",
loc.file(),
loc.line(),
@ -1430,12 +1426,18 @@ pub mod __rt {
use core::borrow::{Borrow, BorrowMut};
use core::cell::{Cell, UnsafeCell};
use core::convert::Infallible;
use core::mem;
use core::ops::{Deref, DerefMut};
pub extern crate alloc;
pub extern crate core;
#[cfg(feature = "std")]
pub extern crate std;
use alloc::alloc::{alloc, dealloc, realloc, Layout};
use alloc::boxed::Box;
use alloc::rc::Rc;
#[macro_export]
#[doc(hidden)]
#[cfg(feature = "std")]
@ -1609,151 +1611,157 @@ pub mod __rt {
);
}
if_std! {
use std::rc::Rc;
/// 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>>,
}
/// 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> 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;
}
}
}
impl<T: ?Sized> Deref for RcRef<T> {
type Target = T;
malloc_failure();
}
#[inline]
fn deref(&self) -> &T {
&self.ref_
#[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();
}
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_
#[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",
not(any(target_os = "emscripten", target_os = "wasi"))
))] {
core::arch::wasm32::unreachable();
} else {
unreachable!()
}
}
}
if_std! {
use std::alloc::{alloc, dealloc, realloc, Layout};
#[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() -> ! {
if cfg!(debug_assertions) {
super::throw_str("invalid malloc request")
} else {
std::process::abort();
}
}
#[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);
#[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,
@ -1790,31 +1798,33 @@ pub mod __rt {
///
/// Ideas for how to improve this are most welcome!
pub fn link_mem_intrinsics() {
crate::externref::link_intrinsics();
crate::link::link_intrinsics();
}
std::thread_local! {
static GLOBAL_EXNDATA: Cell<[u32; 2]> = Cell::new([0; 2]);
}
if_std! {
std::thread_local! {
static GLOBAL_EXNDATA: Cell<[u32; 2]> = Cell::new([0; 2]);
}
#[no_mangle]
pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
GLOBAL_EXNDATA.with(|data| {
debug_assert_eq!(data.get()[0], 0);
data.set([1, idx]);
});
}
#[no_mangle]
pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
GLOBAL_EXNDATA.with(|data| {
debug_assert_eq!(data.get()[0], 0);
data.set([1, idx]);
});
}
pub fn take_last_exception() -> Result<(), super::JsValue> {
GLOBAL_EXNDATA.with(|data| {
let ret = if data.get()[0] == 1 {
Err(super::JsValue::_new(data.get()[1]))
} else {
Ok(())
};
data.set([0, 0]);
ret
})
pub fn take_last_exception() -> Result<(), super::JsValue> {
GLOBAL_EXNDATA.with(|data| {
let ret = if data.get()[0] == 1 {
Err(super::JsValue::_new(data.get()[1]))
} else {
Ok(())
};
data.set([0, 0]);
ret
})
}
}
/// An internal helper trait for usage in `#[wasm_bindgen]` on `async`
@ -1902,11 +1912,11 @@ pub mod __rt {
}
}
impl<E: std::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
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(&std::format!("{:?}", e));
crate::throw_str(&alloc::format!("{:?}", e));
}
}
}
@ -1957,33 +1967,28 @@ pub mod __rt {
result
}
if_std! {
use core::mem;
use std::boxed::Box;
/// Trait for element types to implement `Into<JsValue>` for vectors of
/// themselves, which isn't possible directly thanks to the orphan rule.
pub trait VectorIntoJsValue: Sized {
fn vector_into_jsvalue(vector: Box<[Self]>) -> JsValue;
}
/// Trait for element types to implement `Into<JsValue>` for vectors of
/// themselves, which isn't possible directly thanks to the orphan rule.
pub trait VectorIntoJsValue: Sized {
fn vector_into_jsvalue(vector: Box<[Self]>) -> JsValue;
impl<T: VectorIntoJsValue> From<Box<[T]>> for JsValue {
fn from(vector: Box<[T]>) -> Self {
T::vector_into_jsvalue(vector)
}
}
impl<T: VectorIntoJsValue> From<Box<[T]>> for JsValue {
fn from(vector: Box<[T]>) -> Self {
T::vector_into_jsvalue(vector)
}
}
pub fn js_value_vector_into_jsvalue<T: Into<JsValue>>(vector: Box<[T]>) -> JsValue {
let result = unsafe { JsValue::_new(super::__wbindgen_array_new()) };
for value in vector.into_vec() {
let js: JsValue = value.into();
unsafe { super::__wbindgen_array_push(result.idx, js.idx) }
// `__wbindgen_array_push` takes ownership over `js` and has already dropped it,
// so don't drop it again.
mem::forget(js);
}
result
pub fn js_value_vector_into_jsvalue<T: Into<JsValue>>(vector: Box<[T]>) -> JsValue {
let result = unsafe { JsValue::_new(super::__wbindgen_array_new()) };
for value in vector.into_vec() {
let js: JsValue = value.into();
unsafe { super::__wbindgen_array_push(result.idx, js.idx) }
// `__wbindgen_array_push` takes ownership over `js` and has already dropped it,
// so don't drop it again.
mem::forget(js);
}
result
}
}
@ -2105,74 +2110,72 @@ impl From<JsError> for JsValue {
}
macro_rules! typed_arrays {
($($ty:ident $ctor:ident $clamped_ctor:ident,)*) => {
$(
impl From<Box<[$ty]>> for JsValue {
fn from(mut vector: Box<[$ty]>) -> Self {
let result = unsafe { JsValue::_new($ctor(vector.as_mut_ptr(), vector.len())) };
mem::forget(vector);
result
($($ty:ident $ctor:ident $clamped_ctor:ident,)*) => {
$(
impl From<Box<[$ty]>> for JsValue {
fn from(mut vector: Box<[$ty]>) -> Self {
let result = unsafe { JsValue::_new($ctor(vector.as_mut_ptr(), vector.len())) };
mem::forget(vector);
result
}
}
}
impl From<Clamped<Box<[$ty]>>> for JsValue {
fn from(mut vector: Clamped<Box<[$ty]>>) -> Self {
let result = unsafe { JsValue::_new($clamped_ctor(vector.as_mut_ptr(), vector.len())) };
mem::forget(vector);
result
impl From<Clamped<Box<[$ty]>>> for JsValue {
fn from(mut vector: Clamped<Box<[$ty]>>) -> Self {
let result = unsafe { JsValue::_new($clamped_ctor(vector.as_mut_ptr(), vector.len())) };
mem::forget(vector);
result
}
}
}
)*
};
)*
};
}
typed_arrays! {
u8 __wbindgen_uint8_array_new __wbindgen_uint8_clamped_array_new,
u16 __wbindgen_uint16_array_new __wbindgen_uint16_array_new,
u32 __wbindgen_uint32_array_new __wbindgen_uint32_array_new,
u64 __wbindgen_biguint64_array_new __wbindgen_biguint64_array_new,
i8 __wbindgen_int8_array_new __wbindgen_int8_array_new,
i16 __wbindgen_int16_array_new __wbindgen_int16_array_new,
i32 __wbindgen_int32_array_new __wbindgen_int32_array_new,
i64 __wbindgen_bigint64_array_new __wbindgen_bigint64_array_new,
f32 __wbindgen_float32_array_new __wbindgen_float32_array_new,
f64 __wbindgen_float64_array_new __wbindgen_float64_array_new,
}
if_std! {
typed_arrays! {
u8 __wbindgen_uint8_array_new __wbindgen_uint8_clamped_array_new,
u16 __wbindgen_uint16_array_new __wbindgen_uint16_array_new,
u32 __wbindgen_uint32_array_new __wbindgen_uint32_array_new,
u64 __wbindgen_biguint64_array_new __wbindgen_biguint64_array_new,
i8 __wbindgen_int8_array_new __wbindgen_int8_array_new,
i16 __wbindgen_int16_array_new __wbindgen_int16_array_new,
i32 __wbindgen_int32_array_new __wbindgen_int32_array_new,
i64 __wbindgen_bigint64_array_new __wbindgen_bigint64_array_new,
f32 __wbindgen_float32_array_new __wbindgen_float32_array_new,
f64 __wbindgen_float64_array_new __wbindgen_float64_array_new,
}
impl __rt::VectorIntoJsValue for JsValue {
fn vector_into_jsvalue(vector: Box<[JsValue]>) -> JsValue {
__rt::js_value_vector_into_jsvalue::<JsValue>(vector)
}
}
impl<T: JsObject> __rt::VectorIntoJsValue for T {
fn vector_into_jsvalue(vector: Box<[T]>) -> JsValue {
__rt::js_value_vector_into_jsvalue::<T>(vector)
}
}
impl __rt::VectorIntoJsValue for String {
fn vector_into_jsvalue(vector: Box<[String]>) -> JsValue {
__rt::js_value_vector_into_jsvalue::<String>(vector)
}
}
impl<T> From<Vec<T>> for JsValue
where
JsValue: From<Box<[T]>>,
{
fn from(vector: Vec<T>) -> Self {
JsValue::from(vector.into_boxed_slice())
}
}
impl<T> From<Clamped<Vec<T>>> for JsValue
where
JsValue: From<Clamped<Box<[T]>>>,
{
fn from(vector: Clamped<Vec<T>>) -> Self {
JsValue::from(Clamped(vector.0.into_boxed_slice()))
}
impl __rt::VectorIntoJsValue for JsValue {
fn vector_into_jsvalue(vector: Box<[JsValue]>) -> JsValue {
__rt::js_value_vector_into_jsvalue::<JsValue>(vector)
}
}
impl<T: JsObject> __rt::VectorIntoJsValue for T {
fn vector_into_jsvalue(vector: Box<[T]>) -> JsValue {
__rt::js_value_vector_into_jsvalue::<T>(vector)
}
}
impl __rt::VectorIntoJsValue for String {
fn vector_into_jsvalue(vector: Box<[String]>) -> JsValue {
__rt::js_value_vector_into_jsvalue::<String>(vector)
}
}
impl<T> From<Vec<T>> for JsValue
where
JsValue: From<Box<[T]>>,
{
fn from(vector: Vec<T>) -> Self {
JsValue::from(vector.into_boxed_slice())
}
}
impl<T> From<Clamped<Vec<T>>> for JsValue
where
JsValue: From<Clamped<Box<[T]>>>,
{
fn from(vector: Clamped<Vec<T>>) -> Self {
JsValue::from(Clamped(vector.0.into_boxed_slice()))
}
}

3
src/link.rs Normal file
View File

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