2017-12-14 19:31:01 -08:00
|
|
|
#![feature(use_extern_macros)]
|
|
|
|
|
|
|
|
extern crate wasm_bindgen_macro;
|
|
|
|
|
2017-12-19 09:25:41 -08:00
|
|
|
use std::mem;
|
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
pub mod prelude {
|
|
|
|
pub use wasm_bindgen_macro::wasm_bindgen;
|
2017-12-19 09:25:41 -08:00
|
|
|
pub use JsObject;
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2017-12-19 09:25:41 -08:00
|
|
|
pub struct JsObject {
|
2017-12-14 19:31:01 -08:00
|
|
|
idx: u32,
|
|
|
|
}
|
2017-12-19 09:25:41 -08:00
|
|
|
|
|
|
|
impl JsObject {
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn __from_idx(idx: u32) -> JsObject {
|
|
|
|
JsObject { idx }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn __get_idx(&self) -> u32 {
|
|
|
|
self.idx
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn __into_idx(self) -> u32 {
|
|
|
|
let ret = self.idx;
|
|
|
|
mem::forget(self);
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern {
|
2017-12-19 20:00:25 -08:00
|
|
|
fn __wbindgen_object_clone_ref(idx: u32) -> u32;
|
|
|
|
fn __wbindgen_object_drop_ref(idx: u32);
|
2017-12-19 09:25:41 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Clone for JsObject {
|
|
|
|
fn clone(&self) -> JsObject {
|
|
|
|
unsafe {
|
2017-12-19 20:00:25 -08:00
|
|
|
let idx = __wbindgen_object_clone_ref(self.idx);
|
2017-12-19 09:25:41 -08:00
|
|
|
JsObject { idx }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for JsObject {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
2017-12-19 20:00:25 -08:00
|
|
|
__wbindgen_object_drop_ref(self.idx);
|
2017-12-19 09:25:41 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-19 19:50:06 -08:00
|
|
|
|
|
|
|
#[cold]
|
2017-12-21 12:25:13 -08:00
|
|
|
#[inline(never)]
|
2017-12-19 19:50:06 -08:00
|
|
|
pub fn throw(s: &str) -> ! {
|
|
|
|
extern {
|
|
|
|
fn __wbindgen_throw(a: *const u8, b: usize) -> !;
|
|
|
|
}
|
|
|
|
unsafe {
|
|
|
|
__wbindgen_throw(s.as_ptr(), s.len());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub mod __rt {
|
|
|
|
use std::cell::{Cell, UnsafeCell};
|
|
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn assert_not_null<T>(s: *mut T) {
|
|
|
|
if s.is_null() {
|
2017-12-21 12:25:13 -08:00
|
|
|
throw_null();
|
2017-12-19 19:50:06 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-21 12:25:13 -08:00
|
|
|
#[cold]
|
|
|
|
#[inline(never)]
|
|
|
|
fn throw_null() -> ! {
|
|
|
|
super::throw("null pointer passed to rust");
|
|
|
|
}
|
|
|
|
|
2017-12-19 19:50:06 -08:00
|
|
|
/// 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> {
|
|
|
|
borrow: Cell<usize>,
|
|
|
|
value: UnsafeCell<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> WasmRefCell<T> {
|
|
|
|
pub fn new(value: T) -> WasmRefCell<T> {
|
|
|
|
WasmRefCell {
|
|
|
|
value: UnsafeCell::new(value),
|
|
|
|
borrow: Cell::new(0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-21 12:28:30 -08:00
|
|
|
pub fn get_mut(&mut self) -> &mut T {
|
|
|
|
unsafe {
|
|
|
|
&mut *self.value.get()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-19 19:50:06 -08:00
|
|
|
pub fn borrow(&self) -> Ref<T> {
|
|
|
|
unsafe {
|
|
|
|
if self.borrow.get() == usize::max_value() {
|
|
|
|
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_value());
|
|
|
|
RefMut {
|
|
|
|
value: &mut *self.value.get(),
|
|
|
|
borrow: &self.borrow,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_inner(self) -> T {
|
|
|
|
unsafe {
|
|
|
|
self.value.into_inner()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Ref<'b, T: 'b> {
|
|
|
|
value: &'b T,
|
|
|
|
borrow: &'b Cell<usize>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b, T> Deref for Ref<'b, T> {
|
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn deref(&self) -> &T {
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b, T> Drop for Ref<'b, T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.borrow.set(self.borrow.get() - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct RefMut<'b, T: 'b> {
|
|
|
|
value: &'b mut T,
|
|
|
|
borrow: &'b Cell<usize>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b, T> Deref for RefMut<'b, T> {
|
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn deref(&self) -> &T {
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b, T> DerefMut for RefMut<'b, T> {
|
|
|
|
#[inline]
|
|
|
|
fn deref_mut(&mut self) -> &mut T {
|
|
|
|
self.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b, T> Drop for RefMut<'b, T> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.borrow.set(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn borrow_fail() -> ! {
|
|
|
|
super::throw("recursive use of an object detected which would lead to \
|
|
|
|
unsafe aliasing in rust");
|
|
|
|
}
|
|
|
|
}
|