mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-11-28 05:52:21 +03:00
Work with #![no_std]
contexts
This commit adds support for both `#![no_std]` in the wasm-bindgen runtime support (disabled by default with an on-by-default `std` feature). This also adds support to work and compile in the context of `#![no_std]` crates. Closes #146
This commit is contained in:
parent
792a8e132e
commit
748184ae66
@ -16,6 +16,10 @@ Easy support for interacting between JS and Rust.
|
|||||||
test = false
|
test = false
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.4" }
|
wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.4" }
|
||||||
|
|
||||||
|
@ -116,13 +116,22 @@ impl ToTokens for ast::Struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::wasm_bindgen::__wbindgen_if_not_std! {
|
||||||
|
compile_error! {
|
||||||
|
"exporting a class to JS requires the `std` feature to \
|
||||||
|
be enabled in the `wasm-bindgen` crate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::IntoWasmAbi for #name {
|
impl ::wasm_bindgen::convert::IntoWasmAbi for #name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut ::wasm_bindgen::convert::Stack)
|
fn into_abi(self, _extra: &mut ::wasm_bindgen::convert::Stack)
|
||||||
-> u32
|
-> u32
|
||||||
{
|
{
|
||||||
Box::into_raw(Box::new(::wasm_bindgen::__rt::WasmRefCell::new(self))) as u32
|
use wasm_bindgen::__rt::std::boxed::Box;
|
||||||
|
use wasm_bindgen::__rt::WasmRefCell;
|
||||||
|
Box::into_raw(Box::new(WasmRefCell::new(self))) as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,14 +141,49 @@ impl ToTokens for ast::Struct {
|
|||||||
unsafe fn from_abi(js: u32, _extra: &mut ::wasm_bindgen::convert::Stack)
|
unsafe fn from_abi(js: u32, _extra: &mut ::wasm_bindgen::convert::Stack)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
let ptr = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
use wasm_bindgen::__rt::std::boxed::Box;
|
||||||
::wasm_bindgen::__rt::assert_not_null(ptr);
|
use wasm_bindgen::__rt::{assert_not_null, WasmRefCell};
|
||||||
|
|
||||||
|
let ptr = js as *mut WasmRefCell<#name>;
|
||||||
|
assert_not_null(ptr);
|
||||||
let js = Box::from_raw(ptr);
|
let js = Box::from_raw(ptr);
|
||||||
js.borrow_mut(); // make sure no one's borrowing
|
js.borrow_mut(); // make sure no one's borrowing
|
||||||
js.into_inner()
|
js.into_inner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::wasm_bindgen::__rt::core::convert::From<#name> for
|
||||||
|
::wasm_bindgen::JsValue
|
||||||
|
{
|
||||||
|
fn from(value: #name) -> Self {
|
||||||
|
let ptr = ::wasm_bindgen::convert::IntoWasmAbi::into_abi(
|
||||||
|
value,
|
||||||
|
unsafe { &mut ::wasm_bindgen::convert::GlobalStack::new() },
|
||||||
|
);
|
||||||
|
|
||||||
|
#[wasm_import_module = "__wbindgen_placeholder__"]
|
||||||
|
extern {
|
||||||
|
fn #new_fn(ptr: u32) -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
<::wasm_bindgen::JsValue as ::wasm_bindgen::convert::FromWasmAbi>
|
||||||
|
::from_abi(
|
||||||
|
#new_fn(ptr),
|
||||||
|
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern fn #free_fn(ptr: u32) {
|
||||||
|
<#name as ::wasm_bindgen::convert::FromWasmAbi>::from_abi(
|
||||||
|
ptr,
|
||||||
|
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::RefFromWasmAbi for #name {
|
impl ::wasm_bindgen::convert::RefFromWasmAbi for #name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
type Anchor = ::wasm_bindgen::__rt::Ref<'static, #name>;
|
type Anchor = ::wasm_bindgen::__rt::Ref<'static, #name>;
|
||||||
@ -167,36 +211,6 @@ impl ToTokens for ast::Struct {
|
|||||||
(*js).borrow_mut()
|
(*js).borrow_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::convert::From<#name> for ::wasm_bindgen::JsValue {
|
|
||||||
fn from(value: #name) -> Self {
|
|
||||||
let ptr = ::wasm_bindgen::convert::IntoWasmAbi::into_abi(
|
|
||||||
value,
|
|
||||||
unsafe { &mut ::wasm_bindgen::convert::GlobalStack::new() },
|
|
||||||
);
|
|
||||||
|
|
||||||
#[wasm_import_module = "__wbindgen_placeholder__"]
|
|
||||||
extern {
|
|
||||||
fn #new_fn(ptr: u32) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
<::wasm_bindgen::JsValue as ::wasm_bindgen::convert::FromWasmAbi>
|
|
||||||
::from_abi(
|
|
||||||
#new_fn(ptr),
|
|
||||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn #free_fn(ptr: u32) {
|
|
||||||
<#name as ::wasm_bindgen::convert::FromWasmAbi>::from_abi(
|
|
||||||
ptr,
|
|
||||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}).to_tokens(tokens);
|
}).to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,7 +433,7 @@ impl ToTokens for ast::ImportType {
|
|||||||
impl ::wasm_bindgen::convert::RefFromWasmAbi for #name {
|
impl ::wasm_bindgen::convert::RefFromWasmAbi for #name {
|
||||||
type Abi = <::wasm_bindgen::JsValue as
|
type Abi = <::wasm_bindgen::JsValue as
|
||||||
::wasm_bindgen::convert::RefFromWasmAbi>::Abi;
|
::wasm_bindgen::convert::RefFromWasmAbi>::Abi;
|
||||||
type Anchor = ::std::mem::ManuallyDrop<#name>;
|
type Anchor = ::wasm_bindgen::__rt::core::mem::ManuallyDrop<#name>;
|
||||||
|
|
||||||
unsafe fn ref_from_abi(
|
unsafe fn ref_from_abi(
|
||||||
js: Self::Abi,
|
js: Self::Abi,
|
||||||
@ -427,8 +441,8 @@ impl ToTokens for ast::ImportType {
|
|||||||
) -> Self::Anchor {
|
) -> Self::Anchor {
|
||||||
let tmp = <::wasm_bindgen::JsValue as ::wasm_bindgen::convert::RefFromWasmAbi>
|
let tmp = <::wasm_bindgen::JsValue as ::wasm_bindgen::convert::RefFromWasmAbi>
|
||||||
::ref_from_abi(js, extra);
|
::ref_from_abi(js, extra);
|
||||||
::std::mem::ManuallyDrop::new(#name {
|
::wasm_bindgen::__rt::core::mem::ManuallyDrop::new(#name {
|
||||||
obj: ::std::mem::ManuallyDrop::into_inner(tmp),
|
obj: ::wasm_bindgen::__rt::core::mem::ManuallyDrop::into_inner(tmp),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -702,7 +716,7 @@ impl ToTokens for ast::ImportStatic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
::wasm_bindgen::JsStatic {
|
::wasm_bindgen::JsStatic {
|
||||||
__inner: ::std::cell::UnsafeCell::new(None),
|
__inner: ::wasm_bindgen::__rt::core::cell::UnsafeCell::new(None),
|
||||||
__init: init,
|
__init: init,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -119,9 +119,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
self.finally(&format!("\
|
self.finally(&format!("\
|
||||||
wasm.__wbindgen_free(ptr{i}, len{i} * {size});\n\
|
wasm.__wbindgen_free(ptr{i}, len{i} * {size});\n\
|
||||||
", i = i, size = kind.size()));
|
", i = i, size = kind.size()));
|
||||||
self.cx.required_internal_exports.insert(
|
self.cx.require_internal_export("__wbindgen_free");
|
||||||
"__wbindgen_free",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
self.rust_arguments.push(format!("ptr{}", i));
|
self.rust_arguments.push(format!("ptr{}", i));
|
||||||
return
|
return
|
||||||
@ -216,7 +214,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
self.ret_ty = ty.js_ty().to_string();
|
self.ret_ty = ty.js_ty().to_string();
|
||||||
let f = self.cx.expose_get_vector_from_wasm(ty);
|
let f = self.cx.expose_get_vector_from_wasm(ty);
|
||||||
self.cx.expose_get_global_argument();
|
self.cx.expose_get_global_argument();
|
||||||
self.cx.required_internal_exports.insert("__wbindgen_free");
|
self.cx.require_internal_export("__wbindgen_free");
|
||||||
self.ret_expr = format!("\
|
self.ret_expr = format!("\
|
||||||
const ret = RET;\n\
|
const ret = RET;\n\
|
||||||
const len = getGlobalArgument(0);\n\
|
const len = getGlobalArgument(0);\n\
|
||||||
|
@ -62,6 +62,22 @@ impl<'a> Context<'a> {
|
|||||||
self.global(&global);
|
self.global(&global);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn require_internal_export(&mut self, name: &'static str) {
|
||||||
|
if !self.required_internal_exports.insert(name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let Some(s) = self.module.export_section() {
|
||||||
|
if s.entries().iter().any(|e| e.field() == name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("\n\nthe exported function `{}` is required to generate bindings \
|
||||||
|
but it was not found in the wasm file, perhaps the `std` feature \
|
||||||
|
of the `wasm-bindgen` crate needs to be enabled?\n\n",
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn finalize(&mut self, module_name: &str) -> (String, String) {
|
pub fn finalize(&mut self, module_name: &str) -> (String, String) {
|
||||||
self.unexport_unused_internal_exports();
|
self.unexport_unused_internal_exports();
|
||||||
self.gc();
|
self.gc();
|
||||||
@ -642,7 +658,7 @@ impl<'a> Context<'a> {
|
|||||||
if !self.exposed_globals.insert("pass_string_to_wasm") {
|
if !self.exposed_globals.insert("pass_string_to_wasm") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
self.require_internal_export("__wbindgen_malloc");
|
||||||
self.expose_text_encoder();
|
self.expose_text_encoder();
|
||||||
self.expose_uint8_memory();
|
self.expose_uint8_memory();
|
||||||
let debug = if self.config.debug {
|
let debug = if self.config.debug {
|
||||||
@ -668,7 +684,7 @@ impl<'a> Context<'a> {
|
|||||||
if !self.exposed_globals.insert("pass_array8_to_wasm") {
|
if !self.exposed_globals.insert("pass_array8_to_wasm") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
self.require_internal_export("__wbindgen_malloc");
|
||||||
self.expose_uint8_memory();
|
self.expose_uint8_memory();
|
||||||
self.global(&format!("
|
self.global(&format!("
|
||||||
function passArray8ToWasm(arg) {{
|
function passArray8ToWasm(arg) {{
|
||||||
@ -683,7 +699,7 @@ impl<'a> Context<'a> {
|
|||||||
if !self.exposed_globals.insert("pass_array16_to_wasm") {
|
if !self.exposed_globals.insert("pass_array16_to_wasm") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
self.require_internal_export("__wbindgen_malloc");
|
||||||
self.expose_uint16_memory();
|
self.expose_uint16_memory();
|
||||||
self.global(&format!("
|
self.global(&format!("
|
||||||
function passArray16ToWasm(arg) {{
|
function passArray16ToWasm(arg) {{
|
||||||
@ -698,7 +714,7 @@ impl<'a> Context<'a> {
|
|||||||
if !self.exposed_globals.insert("pass_array32_to_wasm") {
|
if !self.exposed_globals.insert("pass_array32_to_wasm") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
self.require_internal_export("__wbindgen_malloc");
|
||||||
self.expose_uint32_memory();
|
self.expose_uint32_memory();
|
||||||
self.global(&format!("
|
self.global(&format!("
|
||||||
function passArray32ToWasm(arg) {{
|
function passArray32ToWasm(arg) {{
|
||||||
@ -713,7 +729,7 @@ impl<'a> Context<'a> {
|
|||||||
if !self.exposed_globals.insert("pass_array_f32_to_wasm") {
|
if !self.exposed_globals.insert("pass_array_f32_to_wasm") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
self.require_internal_export("__wbindgen_malloc");
|
||||||
self.global(&format!("
|
self.global(&format!("
|
||||||
function passArrayF32ToWasm(arg) {{
|
function passArrayF32ToWasm(arg) {{
|
||||||
const ptr = wasm.__wbindgen_malloc(arg.length * 4);
|
const ptr = wasm.__wbindgen_malloc(arg.length * 4);
|
||||||
@ -727,7 +743,7 @@ impl<'a> Context<'a> {
|
|||||||
if !self.exposed_globals.insert("pass_array_f64_to_wasm") {
|
if !self.exposed_globals.insert("pass_array_f64_to_wasm") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.required_internal_exports.insert("__wbindgen_malloc");
|
self.require_internal_export("__wbindgen_malloc");
|
||||||
self.global(&format!("
|
self.global(&format!("
|
||||||
function passArrayF64ToWasm(arg) {{
|
function passArrayF64ToWasm(arg) {{
|
||||||
const ptr = wasm.__wbindgen_malloc(arg.length * 8);
|
const ptr = wasm.__wbindgen_malloc(arg.length * 8);
|
||||||
@ -1172,7 +1188,7 @@ impl<'a> Context<'a> {
|
|||||||
if !self.exposed_globals.insert("global_argument_ptr") {
|
if !self.exposed_globals.insert("global_argument_ptr") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.required_internal_exports.insert("__wbindgen_global_argument_ptr");
|
self.require_internal_export("__wbindgen_global_argument_ptr");
|
||||||
self.global("
|
self.global("
|
||||||
let cachedGlobalArgumentPtr = null;
|
let cachedGlobalArgumentPtr = null;
|
||||||
function globalArgumentPtr() {
|
function globalArgumentPtr() {
|
||||||
|
@ -91,9 +91,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
self.prelude(&format!("\
|
self.prelude(&format!("\
|
||||||
wasm.__wbindgen_free(arg{0}, len{0} * {size});\
|
wasm.__wbindgen_free(arg{0}, len{0} * {size});\
|
||||||
", i, size = ty.size()));
|
", i, size = ty.size()));
|
||||||
self.cx.required_internal_exports.insert(
|
self.cx.require_internal_export("__wbindgen_free");
|
||||||
"__wbindgen_free"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
self.js_arguments.push(format!("v{}", i));
|
self.js_arguments.push(format!("v{}", i));
|
||||||
return
|
return
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::marker::Unsize;
|
use std::marker::Unsize;
|
||||||
use std::mem::{self, ManuallyDrop};
|
use std::mem::{self, ManuallyDrop};
|
||||||
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
use JsValue;
|
use JsValue;
|
||||||
use convert::*;
|
use convert::*;
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
//! This is mostly an internal module, no stability guarantees are provied. Use
|
//! This is mostly an internal module, no stability guarantees are provied. Use
|
||||||
//! at your own risk.
|
//! at your own risk.
|
||||||
|
|
||||||
use std::mem::{self, ManuallyDrop};
|
use core::mem::{self, ManuallyDrop};
|
||||||
use std::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use std::slice;
|
use core::slice;
|
||||||
use std::str;
|
use core::str;
|
||||||
|
|
||||||
use {JsValue, throw};
|
use {JsValue, throw};
|
||||||
use describe::*;
|
use describe::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||||
pub struct Descriptor {
|
pub struct Descriptor {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -132,6 +135,7 @@ impl<T> FromWasmAbi for *mut T {
|
|||||||
|
|
||||||
macro_rules! vectors {
|
macro_rules! vectors {
|
||||||
($($t:ident)*) => ($(
|
($($t:ident)*) => ($(
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl IntoWasmAbi for Box<[$t]> {
|
impl IntoWasmAbi for Box<[$t]> {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
@ -144,6 +148,7 @@ macro_rules! vectors {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl FromWasmAbi for Box<[$t]> {
|
impl FromWasmAbi for Box<[$t]> {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
@ -183,34 +188,36 @@ vectors! {
|
|||||||
u8 i8 u16 i16 u32 i32 f32 f64
|
u8 i8 u16 i16 u32 i32 f32 f64
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IntoWasmAbi for Vec<T> where Box<[T]>: IntoWasmAbi {
|
if_std! {
|
||||||
type Abi = <Box<[T]> as IntoWasmAbi>::Abi;
|
impl<T> IntoWasmAbi for Vec<T> where Box<[T]>: IntoWasmAbi {
|
||||||
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
type Abi = <Box<[T]> as IntoWasmAbi>::Abi;
|
||||||
self.into_boxed_slice().into_abi(extra)
|
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
||||||
|
self.into_boxed_slice().into_abi(extra)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> FromWasmAbi for Vec<T> where Box<[T]>: FromWasmAbi {
|
impl<T> FromWasmAbi for Vec<T> where Box<[T]>: FromWasmAbi {
|
||||||
type Abi = <Box<[T]> as FromWasmAbi>::Abi;
|
type Abi = <Box<[T]> as FromWasmAbi>::Abi;
|
||||||
|
|
||||||
unsafe fn from_abi(js: Self::Abi, extra: &mut Stack) -> Self {
|
unsafe fn from_abi(js: Self::Abi, extra: &mut Stack) -> Self {
|
||||||
<Box<[T]>>::from_abi(js, extra).into()
|
<Box<[T]>>::from_abi(js, extra).into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoWasmAbi for String {
|
impl IntoWasmAbi for String {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
self.into_bytes().into_abi(extra)
|
self.into_bytes().into_abi(extra)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl FromWasmAbi for String {
|
impl FromWasmAbi for String {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Self {
|
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Self {
|
||||||
String::from_utf8_unchecked(<Vec<u8>>::from_abi(js, extra))
|
String::from_utf8_unchecked(<Vec<u8>>::from_abi(js, extra))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,25 +272,27 @@ impl RefFromWasmAbi for JsValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoWasmAbi for Box<[JsValue]> {
|
if_std! {
|
||||||
type Abi = u32;
|
impl IntoWasmAbi for Box<[JsValue]> {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
let ptr = self.as_ptr();
|
let ptr = self.as_ptr();
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
extra.push(len as u32);
|
extra.push(len as u32);
|
||||||
ptr.into_abi(extra)
|
ptr.into_abi(extra)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl FromWasmAbi for Box<[JsValue]> {
|
impl FromWasmAbi for Box<[JsValue]> {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Self {
|
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Self {
|
||||||
let ptr = <*mut JsValue>::from_abi(js, extra);
|
let ptr = <*mut JsValue>::from_abi(js, extra);
|
||||||
let len = extra.pop() as usize;
|
let len = extra.pop() as usize;
|
||||||
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
|
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,6 @@ simple! {
|
|||||||
f64 => F64
|
f64 => F64
|
||||||
bool => BOOLEAN
|
bool => BOOLEAN
|
||||||
str => STRING
|
str => STRING
|
||||||
String => STRING
|
|
||||||
JsValue => ANYREF
|
JsValue => ANYREF
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,16 +104,24 @@ impl<'a, T: WasmDescribe + ?Sized> WasmDescribe for &'a mut T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: WasmDescribe> WasmDescribe for Box<[T]> {
|
if_std! {
|
||||||
fn describe() {
|
use std::prelude::v1::*;
|
||||||
inform(VECTOR);
|
|
||||||
T::describe();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> WasmDescribe for Vec<T> where Box<[T]>: WasmDescribe {
|
impl WasmDescribe for String {
|
||||||
fn describe() {
|
fn describe() { inform(STRING) }
|
||||||
<Box<[T]>>::describe();
|
}
|
||||||
|
|
||||||
|
impl<T: WasmDescribe> WasmDescribe for Box<[T]> {
|
||||||
|
fn describe() {
|
||||||
|
inform(VECTOR);
|
||||||
|
T::describe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WasmDescribe for Vec<T> where Box<[T]>: WasmDescribe {
|
||||||
|
fn describe() {
|
||||||
|
<Box<[T]>>::describe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
86
src/lib.rs
86
src/lib.rs
@ -6,15 +6,22 @@
|
|||||||
//! interface.
|
//! interface.
|
||||||
|
|
||||||
#![feature(use_extern_macros, wasm_import_module, try_reserve, unsize)]
|
#![feature(use_extern_macros, wasm_import_module, try_reserve, unsize)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
extern crate wasm_bindgen_macro;
|
extern crate wasm_bindgen_macro;
|
||||||
|
|
||||||
use std::cell::UnsafeCell;
|
use core::cell::UnsafeCell;
|
||||||
use std::ops::Deref;
|
use core::ops::Deref;
|
||||||
use std::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
use convert::FromWasmAbi;
|
use convert::FromWasmAbi;
|
||||||
|
|
||||||
|
macro_rules! if_std {
|
||||||
|
($($i:item)*) => ($(
|
||||||
|
#[cfg(feature = "std")] $i
|
||||||
|
)*)
|
||||||
|
}
|
||||||
|
|
||||||
/// A module which is typically glob imported from:
|
/// A module which is typically glob imported from:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -23,13 +30,21 @@ use convert::FromWasmAbi;
|
|||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use wasm_bindgen_macro::wasm_bindgen;
|
pub use wasm_bindgen_macro::wasm_bindgen;
|
||||||
pub use JsValue;
|
pub use JsValue;
|
||||||
pub use closure::Closure;
|
|
||||||
|
if_std! {
|
||||||
|
pub use closure::Closure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod convert;
|
pub mod convert;
|
||||||
pub mod closure;
|
|
||||||
pub mod describe;
|
pub mod describe;
|
||||||
|
|
||||||
|
if_std! {
|
||||||
|
extern crate std;
|
||||||
|
use std::prelude::v1::*;
|
||||||
|
pub mod closure;
|
||||||
|
}
|
||||||
|
|
||||||
/// Representation of an object owned by JS.
|
/// Representation of an object owned by JS.
|
||||||
///
|
///
|
||||||
/// A `JsValue` doesn't actually live in Rust right now but actually in a table
|
/// A `JsValue` doesn't actually live in Rust right now but actually in a table
|
||||||
@ -136,6 +151,7 @@ impl JsValue {
|
|||||||
///
|
///
|
||||||
/// If this JS value is not an instance of a string or if it's not valid
|
/// If this JS value is not an instance of a string or if it's not valid
|
||||||
/// utf-8 then this returns `None`.
|
/// utf-8 then this returns `None`.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
pub fn as_string(&self) -> Option<String> {
|
pub fn as_string(&self) -> Option<String> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
@ -192,9 +208,11 @@ impl<'a> From<&'a str> for JsValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a String> for JsValue {
|
if_std! {
|
||||||
fn from(s: &'a String) -> JsValue {
|
impl<'a> From<&'a String> for JsValue {
|
||||||
JsValue::from_str(s)
|
fn from(s: &'a String) -> JsValue {
|
||||||
|
JsValue::from_str(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,9 +339,23 @@ pub fn throw(s: &str) -> ! {
|
|||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod __rt {
|
pub mod __rt {
|
||||||
use std::cell::{Cell, UnsafeCell};
|
use core::cell::{Cell, UnsafeCell};
|
||||||
use std::mem;
|
use core::ops::{Deref, DerefMut};
|
||||||
use std::ops::{Deref, DerefMut};
|
pub extern crate core;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub extern crate std;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
macro_rules! __wbindgen_if_not_std {
|
||||||
|
($($i:item)*) => ()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
macro_rules! __wbindgen_if_not_std {
|
||||||
|
($($i:item)*) => ($($i)*)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn assert_not_null<T>(s: *mut T) {
|
pub fn assert_not_null<T>(s: *mut T) {
|
||||||
@ -457,20 +489,26 @@ pub mod __rt {
|
|||||||
unsafe aliasing in rust");
|
unsafe aliasing in rust");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
if_std! {
|
||||||
pub extern fn __wbindgen_malloc(size: usize) -> *mut u8 {
|
use std::prelude::v1::*;
|
||||||
let mut ret = Vec::new();
|
|
||||||
if ret.try_reserve_exact(size).is_err() {
|
|
||||||
super::throw("invalid malloc request");
|
|
||||||
}
|
|
||||||
let ptr = ret.as_mut_ptr();
|
|
||||||
mem::forget(ret);
|
|
||||||
return ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern fn __wbindgen_free(ptr: *mut u8, size: usize) {
|
pub extern fn __wbindgen_malloc(size: usize) -> *mut u8 {
|
||||||
drop(Vec::<u8>::from_raw_parts(ptr, 0, size));
|
use core::mem;
|
||||||
|
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
if ret.try_reserve_exact(size).is_err() {
|
||||||
|
super::throw("invalid malloc request");
|
||||||
|
}
|
||||||
|
let ptr = ret.as_mut_ptr();
|
||||||
|
mem::forget(ret);
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern fn __wbindgen_free(ptr: *mut u8, size: usize) {
|
||||||
|
drop(Vec::<u8>::from_raw_parts(ptr, 0, size));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_this_library() {}
|
pub fn link_this_library() {}
|
||||||
|
@ -15,6 +15,7 @@ struct Project {
|
|||||||
files: Vec<(String, String)>,
|
files: Vec<(String, String)>,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
node: bool,
|
node: bool,
|
||||||
|
no_std: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project() -> Project {
|
fn project() -> Project {
|
||||||
@ -25,6 +26,7 @@ fn project() -> Project {
|
|||||||
Project {
|
Project {
|
||||||
debug: true,
|
debug: true,
|
||||||
node: false,
|
node: false,
|
||||||
|
no_std: false,
|
||||||
files: vec![
|
files: vec![
|
||||||
("Cargo.toml".to_string(), format!(r#"
|
("Cargo.toml".to_string(), format!(r#"
|
||||||
[package]
|
[package]
|
||||||
@ -40,8 +42,7 @@ fn project() -> Project {
|
|||||||
# XXX: It is important that `[dependencies]` is the last section
|
# XXX: It is important that `[dependencies]` is the last section
|
||||||
# here, so that `add_local_dependency` functions correctly!
|
# here, so that `add_local_dependency` functions correctly!
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = {{ path = '{}' }}
|
"#, IDX.with(|x| *x))),
|
||||||
"#, IDX.with(|x| *x), dir.display())),
|
|
||||||
|
|
||||||
("Cargo.lock".to_string(), lockfile),
|
("Cargo.lock".to_string(), lockfile),
|
||||||
|
|
||||||
@ -138,6 +139,11 @@ impl Project {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn no_std(&mut self, no_std: bool) -> &mut Project {
|
||||||
|
self.no_std = no_std;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn add_local_dependency(&mut self, name: &str, path: &str) -> &mut Project {
|
fn add_local_dependency(&mut self, name: &str, path: &str) -> &mut Project {
|
||||||
{
|
{
|
||||||
let cargo_toml = self.files
|
let cargo_toml = self.files
|
||||||
@ -145,14 +151,28 @@ impl Project {
|
|||||||
.find(|f| f.0 == "Cargo.toml")
|
.find(|f| f.0 == "Cargo.toml")
|
||||||
.expect("should have Cargo.toml file!");
|
.expect("should have Cargo.toml file!");
|
||||||
cargo_toml.1.push_str(name);
|
cargo_toml.1.push_str(name);
|
||||||
cargo_toml.1.push_str(" = { path = \"");
|
cargo_toml.1.push_str(" = { path = '");
|
||||||
cargo_toml.1.push_str(path);
|
cargo_toml.1.push_str(path);
|
||||||
cargo_toml.1.push_str("\" }");
|
cargo_toml.1.push_str("' }\n");
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test(&mut self) {
|
fn test(&mut self) {
|
||||||
|
{
|
||||||
|
let cargo_toml = self.files
|
||||||
|
.iter_mut()
|
||||||
|
.find(|f| f.0 == "Cargo.toml")
|
||||||
|
.expect("should have Cargo.toml file!");
|
||||||
|
cargo_toml.1.push_str("wasm-bindgen = { path = '");
|
||||||
|
cargo_toml.1.push_str(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
if self.no_std {
|
||||||
|
cargo_toml.1.push_str("', default-features = false");
|
||||||
|
} else {
|
||||||
|
cargo_toml.1.push_str("'");
|
||||||
|
}
|
||||||
|
cargo_toml.1.push_str(" }\n");
|
||||||
|
}
|
||||||
let root = root();
|
let root = root();
|
||||||
drop(fs::remove_dir_all(&root));
|
drop(fs::remove_dir_all(&root));
|
||||||
for &(ref file, ref contents) in self.files.iter() {
|
for &(ref file, ref contents) in self.files.iter() {
|
||||||
|
@ -201,3 +201,89 @@ fn other_exports() {
|
|||||||
"#)
|
"#)
|
||||||
.test();
|
.test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_std() {
|
||||||
|
project()
|
||||||
|
.no_std(true)
|
||||||
|
.file("src/lib.rs", r#"
|
||||||
|
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||||
|
#![no_std]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
extern crate std as _some_other_name;
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern {
|
||||||
|
fn test(a: &str);
|
||||||
|
|
||||||
|
type Js;
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
fn new() -> Js;
|
||||||
|
#[wasm_bindgen(method)]
|
||||||
|
fn init(this: &Js);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn foo(_a: u32) {}
|
||||||
|
"#)
|
||||||
|
.file("test.ts", r#"
|
||||||
|
import * as wasm from "./out_bg";
|
||||||
|
|
||||||
|
export function test() {
|
||||||
|
// mostly just testing the project compiles here
|
||||||
|
wasm.foo(1);
|
||||||
|
}
|
||||||
|
"#)
|
||||||
|
.test();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_std_class() {
|
||||||
|
project()
|
||||||
|
.file("src/lib.rs", r#"
|
||||||
|
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||||
|
#![no_std]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
extern crate wasm_bindgen;
|
||||||
|
extern crate std as _some_other_name;
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern {
|
||||||
|
fn test(a: &str);
|
||||||
|
|
||||||
|
type Js;
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
fn new() -> Js;
|
||||||
|
#[wasm_bindgen(method, structural)]
|
||||||
|
fn init(this: &Js);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn foo(_a: u32) {}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct A {}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl A {
|
||||||
|
pub fn foo(&self) {}
|
||||||
|
pub fn bar(&mut self) {}
|
||||||
|
}
|
||||||
|
"#)
|
||||||
|
.file("test.ts", r#"
|
||||||
|
import * as wasm from "./out_bg";
|
||||||
|
|
||||||
|
export function test() {
|
||||||
|
// mostly just testing the project compiles here
|
||||||
|
wasm.foo(1);
|
||||||
|
}
|
||||||
|
"#)
|
||||||
|
.test();
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user