mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-08 13:18:07 +00:00
Merge pull request #955 from alexcrichton/non-send
Ensure that `JsValue` isn't considered `Send`
This commit is contained in:
commit
e03e40451e
@ -1042,11 +1042,9 @@ impl ToTokens for ast::ImportStatic {
|
|||||||
fn init() -> #ty {
|
fn init() -> #ty {
|
||||||
panic!("cannot access imported statics on non-wasm targets")
|
panic!("cannot access imported statics on non-wasm targets")
|
||||||
}
|
}
|
||||||
static mut _VAL: ::wasm_bindgen::__rt::core::cell::UnsafeCell<Option<#ty>> =
|
thread_local!(static _VAL: #ty = init(););
|
||||||
::wasm_bindgen::__rt::core::cell::UnsafeCell::new(None);
|
|
||||||
::wasm_bindgen::JsStatic {
|
::wasm_bindgen::JsStatic {
|
||||||
__inner: unsafe { &_VAL },
|
__inner: &_VAL,
|
||||||
__init: init,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}).to_tokens(into);
|
}).to_tokens(into);
|
||||||
|
@ -214,7 +214,7 @@ impl<T> Closure<T>
|
|||||||
};
|
};
|
||||||
|
|
||||||
Closure {
|
Closure {
|
||||||
js: ManuallyDrop::new(JsValue { idx }),
|
js: ManuallyDrop::new(JsValue::_new(idx)),
|
||||||
data: ManuallyDrop::new(data),
|
data: ManuallyDrop::new(data),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,7 @@ impl FromWasmAbi for JsValue {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> JsValue {
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> JsValue {
|
||||||
JsValue { idx: js }
|
JsValue::_new(js)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ impl RefFromWasmAbi for JsValue {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn ref_from_abi(js: u32, _extra: &mut Stack) -> Self::Anchor {
|
unsafe fn ref_from_abi(js: u32, _extra: &mut Stack) -> Self::Anchor {
|
||||||
ManuallyDrop::new(JsValue { idx: js })
|
ManuallyDrop::new(JsValue::_new(js))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
90
src/lib.rs
90
src/lib.rs
@ -16,8 +16,8 @@ extern crate serde_json;
|
|||||||
|
|
||||||
extern crate wasm_bindgen_macro;
|
extern crate wasm_bindgen_macro;
|
||||||
|
|
||||||
use core::cell::UnsafeCell;
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use core::marker;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
@ -64,6 +64,7 @@ if_std! {
|
|||||||
/// but for now it may be slightly slow.
|
/// but for now it may be slightly slow.
|
||||||
pub struct JsValue {
|
pub struct JsValue {
|
||||||
idx: u32,
|
idx: u32,
|
||||||
|
_marker: marker::PhantomData<*mut u8>, // not at all threadsafe
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSIDX_UNDEFINED: u32 = 0;
|
const JSIDX_UNDEFINED: u32 = 0;
|
||||||
@ -74,18 +75,36 @@ const JSIDX_RESERVED: u32 = 8;
|
|||||||
|
|
||||||
impl JsValue {
|
impl JsValue {
|
||||||
/// The `null` JS value constant.
|
/// The `null` JS value constant.
|
||||||
pub const NULL: JsValue = JsValue { idx: JSIDX_NULL };
|
pub const NULL: JsValue = JsValue {
|
||||||
|
idx: JSIDX_NULL,
|
||||||
|
_marker: marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
/// The `undefined` JS value constant.
|
/// The `undefined` JS value constant.
|
||||||
pub const UNDEFINED: JsValue = JsValue {
|
pub const UNDEFINED: JsValue = JsValue {
|
||||||
idx: JSIDX_UNDEFINED,
|
idx: JSIDX_UNDEFINED,
|
||||||
|
_marker: marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// The `true` JS value constant.
|
/// The `true` JS value constant.
|
||||||
pub const TRUE: JsValue = JsValue { idx: JSIDX_TRUE };
|
pub const TRUE: JsValue = JsValue {
|
||||||
|
idx: JSIDX_TRUE,
|
||||||
|
_marker: marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
/// The `false` JS value constant.
|
/// The `false` JS value constant.
|
||||||
pub const FALSE: JsValue = JsValue { idx: JSIDX_FALSE };
|
pub const FALSE: JsValue = JsValue {
|
||||||
|
idx: JSIDX_FALSE,
|
||||||
|
_marker: marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn _new(idx: u32) -> JsValue {
|
||||||
|
JsValue {
|
||||||
|
idx,
|
||||||
|
_marker: marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new JS value which is a string.
|
/// Creates a new JS value which is a string.
|
||||||
///
|
///
|
||||||
@ -94,9 +113,7 @@ impl JsValue {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_str(s: &str) -> JsValue {
|
pub fn from_str(s: &str) -> JsValue {
|
||||||
unsafe {
|
unsafe {
|
||||||
JsValue {
|
JsValue::_new(__wbindgen_string_new(s.as_ptr(), s.len()))
|
||||||
idx: __wbindgen_string_new(s.as_ptr(), s.len()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,9 +124,7 @@ impl JsValue {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_f64(n: f64) -> JsValue {
|
pub fn from_f64(n: f64) -> JsValue {
|
||||||
unsafe {
|
unsafe {
|
||||||
JsValue {
|
JsValue::_new(__wbindgen_number_new(n))
|
||||||
idx: __wbindgen_number_new(n),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +157,7 @@ impl JsValue {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let ptr = description.map(|s| s.as_ptr()).unwrap_or(ptr::null());
|
let ptr = description.map(|s| s.as_ptr()).unwrap_or(ptr::null());
|
||||||
let len = description.map(|s| s.len()).unwrap_or(0);
|
let len = description.map(|s| s.len()).unwrap_or(0);
|
||||||
JsValue {
|
JsValue::_new(__wbindgen_symbol_new(ptr, len))
|
||||||
idx: __wbindgen_symbol_new(ptr, len),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,9 +183,7 @@ impl JsValue {
|
|||||||
{
|
{
|
||||||
let s = serde_json::to_string(t)?;
|
let s = serde_json::to_string(t)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
Ok(JsValue {
|
Ok(JsValue::_new(__wbindgen_json_parse(s.as_ptr(), s.len())))
|
||||||
idx: __wbindgen_json_parse(s.as_ptr(), s.len()),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +497,7 @@ impl Clone for JsValue {
|
|||||||
fn clone(&self) -> JsValue {
|
fn clone(&self) -> JsValue {
|
||||||
unsafe {
|
unsafe {
|
||||||
let idx = __wbindgen_object_clone_ref(self.idx);
|
let idx = __wbindgen_object_clone_ref(self.idx);
|
||||||
JsValue { idx }
|
JsValue::_new(idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -552,43 +563,26 @@ impl Drop for JsValue {
|
|||||||
///
|
///
|
||||||
/// This type implements `Deref` to the inner type so it's typically used as if
|
/// This type implements `Deref` to the inner type so it's typically used as if
|
||||||
/// it were `&T`.
|
/// it were `&T`.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
pub struct JsStatic<T: 'static> {
|
pub struct JsStatic<T: 'static> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub __inner: &'static UnsafeCell<Option<T>>,
|
pub __inner: &'static std::thread::LocalKey<T>,
|
||||||
#[doc(hidden)]
|
|
||||||
pub __init: fn() -> T,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: Sync> Sync for JsStatic<T> {}
|
#[cfg(feature = "std")]
|
||||||
unsafe impl<T: Send> Send for JsStatic<T> {}
|
|
||||||
|
|
||||||
impl<T: FromWasmAbi + 'static> Deref for JsStatic<T> {
|
impl<T: FromWasmAbi + 'static> Deref for JsStatic<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
|
// We know that our tls key is never overwritten after initialization,
|
||||||
|
// so it should be safe (on that axis at least) to hand out a reference
|
||||||
|
// that lives longer than the closure below.
|
||||||
|
//
|
||||||
|
// FIXME: this is not sound if we ever implement thread exit hooks on
|
||||||
|
// wasm, as the pointer will eventually be invalidated but you can get
|
||||||
|
// `&'static T` from this interface. We... probably need to deprecate
|
||||||
|
// and/or remove this interface nowadays.
|
||||||
unsafe {
|
unsafe {
|
||||||
// Ideally we want to use `get_or_insert_with` here but
|
self.__inner.with(|ptr| &*(ptr as *const T))
|
||||||
// unfortunately that has subpar codegen for now.
|
|
||||||
//
|
|
||||||
// If we get past the `Some` branch here LLVM statically
|
|
||||||
// knows that we're `None`, but the after the call to the `__init`
|
|
||||||
// function LLVM can no longer know this because `__init` could
|
|
||||||
// recursively call this function again (aka if JS came back to Rust
|
|
||||||
// and Rust referenced this static).
|
|
||||||
//
|
|
||||||
// We know, however, that cannot happen. As a result we can
|
|
||||||
// conclude that even after the call to `__init` our `ptr` still
|
|
||||||
// points to `None` (and a debug assertion to this effect). Then
|
|
||||||
// using `ptr::write` should tell rustc to not run destuctors
|
|
||||||
// (as one isn't there) and this should tighten up codegen for
|
|
||||||
// `JsStatic` a bit as well.
|
|
||||||
let ptr = self.__inner.get();
|
|
||||||
if let Some(ref t) = *ptr {
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
let init = Some((self.__init)());
|
|
||||||
debug_assert!((*ptr).is_none());
|
|
||||||
ptr::write(ptr, init);
|
|
||||||
(*ptr).as_ref().unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -642,9 +636,7 @@ pub fn throw_val(s: JsValue) -> ! {
|
|||||||
/// Returns a handle to this wasm instance's `WebAssembly.Memory`
|
/// Returns a handle to this wasm instance's `WebAssembly.Memory`
|
||||||
pub fn memory() -> JsValue {
|
pub fn memory() -> JsValue {
|
||||||
unsafe {
|
unsafe {
|
||||||
JsValue {
|
JsValue::_new(__wbindgen_memory())
|
||||||
idx: __wbindgen_memory(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user