mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-25 14:12:13 +00:00
Merge branch 'master' into add-wasm-bindgen-skip-attr
This commit is contained in:
commit
00c4dd9b6f
72
CHANGELOG.md
72
CHANGELOG.md
@ -32,6 +32,78 @@ Released YYYY-MM-DD.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## 0.2.42
|
||||
|
||||
Released 2019-04-11.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed an issue in Firefox where using `encodeInto` accidentally caused empty
|
||||
strings to keep getting passed to Rust.
|
||||
[#1434](https://github.com/rustwasm/wasm-bindgen/pull/1434)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## 0.2.41
|
||||
|
||||
Released 2019-04-10.
|
||||
|
||||
### Added
|
||||
|
||||
* Initial support for transitive NPM dependencies has been added, although
|
||||
support has not fully landed in `wasm-pack` yet so it's not 100% integrated.
|
||||
[#1305](https://github.com/rustwasm/wasm-bindgen/pull/1305)
|
||||
|
||||
* The `constructor` property of `Object` is now bound in `js-sys`.
|
||||
[#1403](https://github.com/rustwasm/wasm-bindgen/pull/1403)
|
||||
|
||||
* The `Closure` type now always implements `Debug`.
|
||||
[#1408](https://github.com/rustwasm/wasm-bindgen/pull/1408)
|
||||
|
||||
* Closures which take one `&T` argument are now supported. More implementations
|
||||
may be added in the future, but for now it's just one argument closures.
|
||||
[#1417](https://github.com/rustwasm/wasm-bindgen/pull/1417)
|
||||
|
||||
* The TypeScript bindings for `--web` now expose the `init` function.
|
||||
[#1412](https://github.com/rustwasm/wasm-bindgen/pull/1412)
|
||||
|
||||
* A `js_sys::JsString::is_valid_utf16` method has been added to handle unpaired
|
||||
surrogates in JS strings. Surrounding documentation has also been updated to
|
||||
document this potential pitfall.
|
||||
[#1416](https://github.com/rustwasm/wasm-bindgen/pull/1416)
|
||||
|
||||
* A `wasm_bindgen::function_table()` function has been added to expose the
|
||||
`WebAssembly.Table` and get access to it in wasm code.
|
||||
[#1431](https://github.com/rustwasm/wasm-bindgen/pull/1431)
|
||||
|
||||
### Fixed
|
||||
|
||||
* Reexporting the `wasm_bindgen` macro in crates has been fixed.
|
||||
[#1359](https://github.com/rustwasm/wasm-bindgen/pull/1359)
|
||||
|
||||
* Returning `u32` to JS has been fixed where large `u32` values would show up in
|
||||
JS as large negative numbers.
|
||||
[#1401](https://github.com/rustwasm/wasm-bindgen/pull/1401)
|
||||
|
||||
* Manual instantiation with `WebAssembly.Module` has been fixed.
|
||||
[#1419](https://github.com/rustwasm/wasm-bindgen/pull/1419)
|
||||
|
||||
* Error message for non-`Copy` public struct fields has been improved.
|
||||
[#1430](https://github.com/rustwasm/wasm-bindgen/pull/1430)
|
||||
|
||||
### Changed
|
||||
|
||||
* Performance of passing strings to Rust in Node.js has been improved.
|
||||
[#1391](https://github.com/rustwasm/wasm-bindgen/pull/1391)
|
||||
|
||||
* Performance of `js_sys::try_iter` has been improved.
|
||||
[#1393](https://github.com/rustwasm/wasm-bindgen/pull/1393)
|
||||
|
||||
* Performance of using `TextEncoder#encodeInto` has been improved.
|
||||
[#1414](https://github.com/rustwasm/wasm-bindgen/pull/1414)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
## 0.2.40
|
||||
|
||||
Released 2019-03-21.
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
readme = "README.md"
|
||||
@ -35,13 +35,13 @@ strict-macro = ["wasm-bindgen-macro/strict-macro"]
|
||||
xxx_debug_only_print_generated_code = ["wasm-bindgen-macro/xxx_debug_only_print_generated_code"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.40" }
|
||||
wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.42" }
|
||||
serde = { version = "1.0", optional = true }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
|
||||
js-sys = { path = 'crates/js-sys', version = '0.3.17' }
|
||||
wasm-bindgen-test = { path = 'crates/test', version = '=0.2.40' }
|
||||
js-sys = { path = 'crates/js-sys', version = '0.3.19' }
|
||||
wasm-bindgen-test = { path = 'crates/test', version = '=0.2.42' }
|
||||
serde_derive = "1.0"
|
||||
wasm-bindgen-test-crate-a = { path = 'tests/crates/a', version = '0.1' }
|
||||
wasm-bindgen-test-crate-b = { path = 'tests/crates/b', version = '0.1' }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-anyref-xform"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/anyref-xform"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/backend"
|
||||
@ -22,4 +22,4 @@ log = "0.4"
|
||||
proc-macro2 = "0.4.8"
|
||||
quote = '0.6'
|
||||
syn = { version = '0.15', features = ['full'] }
|
||||
wasm-bindgen-shared = { path = "../shared", version = "=0.2.40" }
|
||||
wasm-bindgen-shared = { path = "../shared", version = "=0.2.42" }
|
||||
|
@ -183,6 +183,7 @@ pub struct ImportType {
|
||||
pub attrs: Vec<syn::Attribute>,
|
||||
pub doc_comment: Option<String>,
|
||||
pub instanceof_shim: String,
|
||||
pub is_type_of: Option<syn::Expr>,
|
||||
pub extends: Vec<syn::Path>,
|
||||
pub vendor_prefixes: Vec<Ident>,
|
||||
}
|
||||
|
@ -291,11 +291,13 @@ impl ToTokens for ast::StructField {
|
||||
let ty = &self.ty;
|
||||
let getter = &self.getter;
|
||||
let setter = &self.setter;
|
||||
|
||||
let assert_copy = quote! { assert_copy::<#ty>() };
|
||||
let assert_copy = respan(assert_copy, ty);
|
||||
(quote! {
|
||||
#[no_mangle]
|
||||
#[doc(hidden)]
|
||||
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
|
||||
#[allow(clippy::all)]
|
||||
#[cfg_attr(all(target_arch = "wasm32", not(target_os = "emscripten")), no_mangle)]
|
||||
pub unsafe extern "C" fn #getter(js: u32)
|
||||
-> <#ty as wasm_bindgen::convert::IntoWasmAbi>::Abi
|
||||
{
|
||||
@ -303,7 +305,7 @@ impl ToTokens for ast::StructField {
|
||||
use wasm_bindgen::convert::{GlobalStack, IntoWasmAbi};
|
||||
|
||||
fn assert_copy<T: Copy>(){}
|
||||
assert_copy::<#ty>();
|
||||
#assert_copy;
|
||||
|
||||
let js = js as *mut WasmRefCell<#struct_name>;
|
||||
assert_not_null(js);
|
||||
@ -576,6 +578,24 @@ impl ToTokens for ast::ImportType {
|
||||
let const_name = format!("__wbg_generated_const_{}", rust_name);
|
||||
let const_name = Ident::new(&const_name, Span::call_site());
|
||||
let instanceof_shim = Ident::new(&self.instanceof_shim, Span::call_site());
|
||||
|
||||
let internal_obj = match self.extends.first() {
|
||||
Some(target) => {
|
||||
quote! { #target }
|
||||
}
|
||||
None => {
|
||||
quote! { wasm_bindgen::JsValue }
|
||||
}
|
||||
};
|
||||
|
||||
let is_type_of = self.is_type_of.as_ref().map(|is_type_of| quote! {
|
||||
#[inline]
|
||||
fn is_type_of(val: &JsValue) -> bool {
|
||||
let is_type_of: fn(&JsValue) -> bool = #is_type_of;
|
||||
is_type_of(val)
|
||||
}
|
||||
});
|
||||
|
||||
(quote! {
|
||||
#[allow(bad_style)]
|
||||
#(#attrs)*
|
||||
@ -583,7 +603,7 @@ impl ToTokens for ast::ImportType {
|
||||
#[repr(transparent)]
|
||||
#[allow(clippy::all)]
|
||||
#vis struct #rust_name {
|
||||
obj: wasm_bindgen::JsValue,
|
||||
obj: #internal_obj
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
@ -602,6 +622,15 @@ impl ToTokens for ast::ImportType {
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for #rust_name {
|
||||
type Target = #internal_obj;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &#internal_obj {
|
||||
&self.obj
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoWasmAbi for #rust_name {
|
||||
type Abi = <JsValue as IntoWasmAbi>::Abi;
|
||||
|
||||
@ -627,7 +656,7 @@ impl ToTokens for ast::ImportType {
|
||||
#[inline]
|
||||
unsafe fn from_abi(js: Self::Abi, extra: &mut Stack) -> Self {
|
||||
#rust_name {
|
||||
obj: JsValue::from_abi(js, extra),
|
||||
obj: JsValue::from_abi(js, extra).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -654,7 +683,7 @@ impl ToTokens for ast::ImportType {
|
||||
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor {
|
||||
let tmp = <JsValue as RefFromWasmAbi>::ref_from_abi(js, extra);
|
||||
core::mem::ManuallyDrop::new(#rust_name {
|
||||
obj: core::mem::ManuallyDrop::into_inner(tmp),
|
||||
obj: core::mem::ManuallyDrop::into_inner(tmp).into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -663,20 +692,20 @@ impl ToTokens for ast::ImportType {
|
||||
impl From<JsValue> for #rust_name {
|
||||
#[inline]
|
||||
fn from(obj: JsValue) -> #rust_name {
|
||||
#rust_name { obj }
|
||||
#rust_name { obj: obj.into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<JsValue> for #rust_name {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &JsValue { &self.obj }
|
||||
fn as_ref(&self) -> &JsValue { self.obj.as_ref() }
|
||||
}
|
||||
|
||||
|
||||
impl From<#rust_name> for JsValue {
|
||||
#[inline]
|
||||
fn from(obj: #rust_name) -> JsValue {
|
||||
obj.obj
|
||||
obj.obj.into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -699,9 +728,11 @@ impl ToTokens for ast::ImportType {
|
||||
panic!("cannot check instanceof on non-wasm targets");
|
||||
}
|
||||
|
||||
#is_type_of
|
||||
|
||||
#[inline]
|
||||
fn unchecked_from_js(val: JsValue) -> Self {
|
||||
#rust_name { obj: val }
|
||||
#rust_name { obj: val.into() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -714,24 +745,9 @@ impl ToTokens for ast::ImportType {
|
||||
|
||||
()
|
||||
};
|
||||
}).to_tokens(tokens);
|
||||
|
||||
let deref_target = match self.extends.first() {
|
||||
Some(target) => quote! { #target },
|
||||
None => quote! { JsValue },
|
||||
};
|
||||
(quote! {
|
||||
#[allow(clippy::all)]
|
||||
impl core::ops::Deref for #rust_name {
|
||||
type Target = #deref_target;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &#deref_target {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
})
|
||||
.to_tokens(tokens);
|
||||
|
||||
for superclass in self.extends.iter() {
|
||||
(quote! {
|
||||
#[allow(clippy::all)]
|
||||
@ -1430,3 +1446,31 @@ impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> {
|
||||
.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
fn respan(
|
||||
input: TokenStream,
|
||||
span: &dyn ToTokens,
|
||||
) -> TokenStream {
|
||||
let mut first_span = Span::call_site();
|
||||
let mut last_span = Span::call_site();
|
||||
let mut spans = TokenStream::new();
|
||||
span.to_tokens(&mut spans);
|
||||
|
||||
for (i, token) in spans.into_iter().enumerate() {
|
||||
if i == 0 {
|
||||
first_span = token.span();
|
||||
}
|
||||
last_span = token.span();
|
||||
}
|
||||
|
||||
let mut new_tokens = Vec::new();
|
||||
for (i, mut token) in input.into_iter().enumerate() {
|
||||
if i == 0 {
|
||||
token.set_span(first_span);
|
||||
} else {
|
||||
token.set_span(last_span);
|
||||
}
|
||||
new_tokens.push(token);
|
||||
}
|
||||
new_tokens.into_iter().collect()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-cli-support"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/cli-support"
|
||||
@ -19,7 +19,7 @@ rustc-demangle = "0.1.13"
|
||||
serde_json = "1.0"
|
||||
tempfile = "3.0"
|
||||
walrus = "0.5.0"
|
||||
wasm-bindgen-anyref-xform = { path = '../anyref-xform', version = '=0.2.40' }
|
||||
wasm-bindgen-shared = { path = "../shared", version = '=0.2.40' }
|
||||
wasm-bindgen-threads-xform = { path = '../threads-xform', version = '=0.2.40' }
|
||||
wasm-bindgen-wasm-interpreter = { path = "../wasm-interpreter", version = '=0.2.40' }
|
||||
wasm-bindgen-anyref-xform = { path = '../anyref-xform', version = '=0.2.42' }
|
||||
wasm-bindgen-shared = { path = "../shared", version = '=0.2.42' }
|
||||
wasm-bindgen-threads-xform = { path = '../threads-xform', version = '=0.2.42' }
|
||||
wasm-bindgen-wasm-interpreter = { path = "../wasm-interpreter", version = '=0.2.42' }
|
||||
|
@ -311,6 +311,7 @@ impl<'a> Context<'a> {
|
||||
/// `--target no-modules`, `--target web`, or for bundlers. This is the very
|
||||
/// last step performed in `finalize`.
|
||||
fn finalize_js(&mut self, module_name: &str, needs_manual_start: bool) -> (String, String) {
|
||||
let mut ts = self.typescript.clone();
|
||||
let mut js = String::new();
|
||||
if self.config.mode.no_modules() {
|
||||
js.push_str("(function() {\n");
|
||||
@ -318,7 +319,7 @@ impl<'a> Context<'a> {
|
||||
|
||||
// Depending on the output mode, generate necessary glue to actually
|
||||
// import the wasm file in one way or another.
|
||||
let mut init = String::new();
|
||||
let mut init = (String::new(), String::new());
|
||||
match &self.config.mode {
|
||||
// In `--target no-modules` mode we need to both expose a name on
|
||||
// the global object as well as generate our own custom start
|
||||
@ -353,7 +354,8 @@ impl<'a> Context<'a> {
|
||||
| OutputMode::Node {
|
||||
experimental_modules: true,
|
||||
} => {
|
||||
js.push_str(&format!("import * as wasm from './{}_bg';\n", module_name));
|
||||
self.imports
|
||||
.push_str(&format!("import * as wasm from './{}_bg';\n", module_name));
|
||||
if needs_manual_start {
|
||||
self.footer.push_str("wasm.__wbindgen_start();\n");
|
||||
}
|
||||
@ -364,14 +366,22 @@ impl<'a> Context<'a> {
|
||||
// expose the same initialization function as `--target no-modules`
|
||||
// as the default export of the module.
|
||||
OutputMode::Web => {
|
||||
js.push_str("const __exports = {};\n");
|
||||
self.imports_post.push_str("const __exports = {};\n");
|
||||
self.imports_post.push_str("let wasm;\n");
|
||||
init = self.gen_init(&module_name, needs_manual_start);
|
||||
self.footer.push_str("export default init;\n");
|
||||
}
|
||||
}
|
||||
|
||||
let (init_js, init_ts) = init;
|
||||
|
||||
ts.push_str(&init_ts);
|
||||
|
||||
// Emit all the JS for importing all our functionality
|
||||
assert!(
|
||||
!self.config.mode.uses_es_modules() || js.is_empty(),
|
||||
"ES modules require imports to be at the start of the file"
|
||||
);
|
||||
js.push_str(&self.imports);
|
||||
js.push_str("\n");
|
||||
js.push_str(&self.imports_post);
|
||||
@ -382,7 +392,7 @@ impl<'a> Context<'a> {
|
||||
js.push_str("\n");
|
||||
|
||||
// Generate the initialization glue, if there was any
|
||||
js.push_str(&init);
|
||||
js.push_str(&init_js);
|
||||
js.push_str("\n");
|
||||
js.push_str(&self.footer);
|
||||
js.push_str("\n");
|
||||
@ -394,7 +404,7 @@ impl<'a> Context<'a> {
|
||||
js = js.replace("\n\n\n", "\n\n");
|
||||
}
|
||||
|
||||
(js, self.typescript.clone())
|
||||
(js, ts)
|
||||
}
|
||||
|
||||
fn wire_up_initial_intrinsics(&mut self) -> Result<(), Error> {
|
||||
@ -773,6 +783,14 @@ impl<'a> Context<'a> {
|
||||
))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_function_table", &|me| {
|
||||
me.function_table_needed = true;
|
||||
Ok(format!(
|
||||
"function() {{ return {}; }}",
|
||||
me.add_heap_object("wasm.__wbg_function_table")
|
||||
))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_rethrow", &|me| {
|
||||
Ok(format!(
|
||||
"function(idx) {{ throw {}; }}",
|
||||
@ -842,7 +860,34 @@ impl<'a> Context<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gen_init(&mut self, module_name: &str, needs_manual_start: bool) -> String {
|
||||
fn ts_for_init_fn(has_memory: bool) -> String {
|
||||
let (memory_doc, memory_param) = if has_memory {
|
||||
(
|
||||
"* @param {WebAssembly.Memory} maybe_memory\n",
|
||||
", maybe_memory: WebAssembly.Memory",
|
||||
)
|
||||
} else {
|
||||
("", "")
|
||||
};
|
||||
format!(
|
||||
"\n\
|
||||
/**\n\
|
||||
* If `module_or_path` is {{RequestInfo}}, makes a request and\n\
|
||||
* for everything else, calls `WebAssembly.instantiate` directly.\n\
|
||||
*\n\
|
||||
* @param {{RequestInfo | BufferSource | WebAssembly.Module}} module_or_path\n\
|
||||
{}\
|
||||
*\n\
|
||||
* @returns {{Promise<any>}}\n\
|
||||
*/\n\
|
||||
export function init \
|
||||
(module_or_path: RequestInfo | BufferSource | WebAssembly.Module{}): Promise<any>;
|
||||
",
|
||||
memory_doc, memory_param
|
||||
)
|
||||
}
|
||||
|
||||
fn gen_init(&mut self, module_name: &str, needs_manual_start: bool) -> (String, String) {
|
||||
let mem = self.module.memories.get(self.memory);
|
||||
let (init_memory1, init_memory2) = if mem.import.is_some() {
|
||||
let mut memory = String::from("new WebAssembly.Memory({");
|
||||
@ -862,15 +907,21 @@ impl<'a> Context<'a> {
|
||||
} else {
|
||||
(String::new(), String::new())
|
||||
};
|
||||
let init_memory_arg = if mem.import.is_some() {
|
||||
", maybe_memory"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
format!(
|
||||
let ts = Self::ts_for_init_fn(mem.import.is_some());
|
||||
let js = format!(
|
||||
"\
|
||||
function init(module_or_path, maybe_memory) {{
|
||||
function init(module{init_memory_arg}) {{
|
||||
let result;
|
||||
const imports = {{ './{module}': __exports }};
|
||||
if (module_or_path instanceof URL || typeof module_or_path === 'string' || module_or_path instanceof Request) {{
|
||||
if (module instanceof URL || typeof module === 'string' || module instanceof Request) {{
|
||||
{init_memory2}
|
||||
const response = fetch(module_or_path);
|
||||
const response = fetch(module);
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {{
|
||||
result = WebAssembly.instantiateStreaming(response, imports)
|
||||
.catch(e => {{
|
||||
@ -890,9 +941,13 @@ impl<'a> Context<'a> {
|
||||
}}
|
||||
}} else {{
|
||||
{init_memory1}
|
||||
result = WebAssembly.instantiate(module_or_path, imports)
|
||||
.then(instance => {{
|
||||
return {{ instance, module: module_or_path }};
|
||||
result = WebAssembly.instantiate(module, imports)
|
||||
.then(result => {{
|
||||
if (result instanceof WebAssembly.Instance) {{
|
||||
return {{ instance: result, module }};
|
||||
}} else {{
|
||||
return result;
|
||||
}}
|
||||
}});
|
||||
}}
|
||||
return result.then(({{instance, module}}) => {{
|
||||
@ -903,6 +958,7 @@ impl<'a> Context<'a> {
|
||||
}});
|
||||
}}
|
||||
",
|
||||
init_memory_arg = init_memory_arg,
|
||||
module = module_name,
|
||||
init_memory1 = init_memory1,
|
||||
init_memory2 = init_memory2,
|
||||
@ -911,7 +967,9 @@ impl<'a> Context<'a> {
|
||||
} else {
|
||||
""
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
(js, ts)
|
||||
}
|
||||
|
||||
fn bind(
|
||||
@ -1306,13 +1364,12 @@ impl<'a> Context<'a> {
|
||||
while (true) {{
|
||||
const view = getUint8Memory().subarray(ptr + writeOffset, ptr + size);
|
||||
const {{ read, written }} = cachedTextEncoder.encodeInto(arg, view);
|
||||
arg = arg.substring(read);
|
||||
writeOffset += written;
|
||||
if (arg.length === 0) {{
|
||||
if (read === arg.length) {{
|
||||
break;
|
||||
}}
|
||||
ptr = wasm.__wbindgen_realloc(ptr, size, size * 2);
|
||||
size *= 2;
|
||||
arg = arg.substring(read);
|
||||
ptr = wasm.__wbindgen_realloc(ptr, size, size += arg.length * 3);
|
||||
}}
|
||||
WASM_VECTOR_LEN = writeOffset;
|
||||
return ptr;
|
||||
|
@ -42,6 +42,19 @@ enum OutputMode {
|
||||
Node { experimental_modules: bool },
|
||||
}
|
||||
|
||||
impl OutputMode {
|
||||
fn uses_es_modules(&self) -> bool {
|
||||
match self {
|
||||
OutputMode::Bundler { .. }
|
||||
| OutputMode::Web
|
||||
| OutputMode::Node {
|
||||
experimental_modules: true,
|
||||
} => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Input {
|
||||
Path(PathBuf),
|
||||
Module(Module, String),
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-cli"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/cli"
|
||||
@ -25,8 +25,8 @@ serde = { version = "1.0", features = ['derive'] }
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
walrus = "0.5"
|
||||
wasm-bindgen-cli-support = { path = "../cli-support", version = "=0.2.40" }
|
||||
wasm-bindgen-shared = { path = "../shared", version = "=0.2.40" }
|
||||
wasm-bindgen-cli-support = { path = "../cli-support", version = "=0.2.42" }
|
||||
wasm-bindgen-shared = { path = "../shared", version = "=0.2.42" }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "0.11"
|
||||
|
@ -7,13 +7,13 @@ license = "MIT/Apache-2.0"
|
||||
name = "wasm-bindgen-futures"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/futures"
|
||||
readme = "./README.md"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
futures = "0.1.20"
|
||||
js-sys = { path = "../js-sys", version = '0.3.17' }
|
||||
wasm-bindgen = { path = "../..", version = '0.2.40' }
|
||||
js-sys = { path = "../js-sys", version = '0.3.19' }
|
||||
wasm-bindgen = { path = "../..", version = '0.2.42' }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
|
||||
wasm-bindgen-test = { path = '../test', version = '0.2.40' }
|
||||
wasm-bindgen-test = { path = '../test', version = '0.2.42' }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "js-sys"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
readme = "./README.md"
|
||||
categories = ["wasm"]
|
||||
@ -19,9 +19,9 @@ test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = { path = "../..", version = "0.2.40" }
|
||||
wasm-bindgen = { path = "../..", version = "0.2.42" }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
|
||||
futures = "0.1.20"
|
||||
wasm-bindgen-test = { path = '../test', version = '=0.2.40' }
|
||||
wasm-bindgen-futures = { path = '../futures', version = '=0.3.17' }
|
||||
wasm-bindgen-test = { path = '../test', version = '=0.2.42' }
|
||||
wasm-bindgen-futures = { path = '../futures', version = '=0.3.19' }
|
||||
|
@ -126,8 +126,8 @@ extern "C" {
|
||||
// Array
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object, is_type_of = Array::is_array)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Array;
|
||||
|
||||
/// Creates a new empty array
|
||||
@ -392,7 +392,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type ArrayBuffer;
|
||||
|
||||
/// The `ArrayBuffer` object is used to represent a generic,
|
||||
@ -466,14 +466,15 @@ extern "C" {
|
||||
// Boolean
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object, is_type_of = |v| v.as_bool().is_some())]
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub type Boolean;
|
||||
|
||||
/// The `Boolean()` constructor creates an object wrapper for a boolean value.
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)
|
||||
#[wasm_bindgen(constructor)]
|
||||
#[deprecated(note = "recommended to use `Boolean::from` instead")]
|
||||
pub fn new(value: &JsValue) -> Boolean;
|
||||
|
||||
/// The `valueOf()` method returns the primitive value of a `Boolean` object.
|
||||
@ -483,11 +484,38 @@ extern "C" {
|
||||
pub fn value_of(this: &Boolean) -> bool;
|
||||
}
|
||||
|
||||
impl From<bool> for Boolean {
|
||||
#[inline]
|
||||
fn from(b: bool) -> Boolean {
|
||||
Boolean::unchecked_from_js(JsValue::from(b))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Boolean> for bool {
|
||||
#[inline]
|
||||
fn from(b: Boolean) -> bool {
|
||||
b.value_of()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<bool> for Boolean {
|
||||
#[inline]
|
||||
fn eq(&self, other: &bool) -> bool {
|
||||
self.value_of() == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Boolean {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.value_of().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// DataView
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type DataView;
|
||||
|
||||
/// The `DataView` view provides a low-level interface for reading and
|
||||
@ -719,7 +747,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Error;
|
||||
|
||||
/// The Error constructor creates an error object.
|
||||
@ -758,7 +786,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object, extends = Error)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type EvalError;
|
||||
|
||||
/// The EvalError object indicates an error regarding the global eval() function. This
|
||||
@ -773,8 +801,8 @@ extern "C" {
|
||||
// Function
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object, is_type_of = JsValue::is_function)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Function;
|
||||
|
||||
/// The `Function` constructor creates a new `Function` object. Calling the
|
||||
@ -869,11 +897,7 @@ impl Function {
|
||||
/// If this JS value is not an instance of a function then this returns
|
||||
/// `None`.
|
||||
pub fn try_from(val: &JsValue) -> Option<&Function> {
|
||||
if val.is_function() {
|
||||
Some(unsafe { mem::transmute(val) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
val.dyn_ref()
|
||||
}
|
||||
}
|
||||
|
||||
@ -881,7 +905,7 @@ impl Function {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Generator;
|
||||
|
||||
/// The next() method returns an object with two properties done and value.
|
||||
@ -909,7 +933,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Map;
|
||||
|
||||
/// The clear() method removes all elements from a Map object.
|
||||
@ -1001,6 +1025,7 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(is_type_of = Iterator::looks_like_iterator)]
|
||||
pub type Iterator;
|
||||
|
||||
/// The next method always has to return an object with appropriate
|
||||
@ -1011,6 +1036,26 @@ extern "C" {
|
||||
pub fn next(this: &Iterator) -> Result<IteratorNext, JsValue>;
|
||||
}
|
||||
|
||||
impl Iterator {
|
||||
fn looks_like_iterator(it: &JsValue) -> bool {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type MaybeIterator;
|
||||
|
||||
#[wasm_bindgen(method, getter)]
|
||||
fn next(this: &MaybeIterator) -> JsValue;
|
||||
}
|
||||
|
||||
if !it.is_object() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let it = it.unchecked_ref::<MaybeIterator>();
|
||||
|
||||
it.next().is_function()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the JS `Symbol.iterator` iteration protocol.
|
||||
///
|
||||
/// Use the `IntoIterator for &js_sys::Iterator` implementation to create this.
|
||||
@ -1099,34 +1144,20 @@ impl IterState {
|
||||
/// Create an iterator over `val` using the JS iteration protocol and
|
||||
/// `Symbol.iterator`.
|
||||
pub fn try_iter(val: &JsValue) -> Result<Option<IntoIter>, JsValue> {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type MaybeIterator;
|
||||
|
||||
#[wasm_bindgen(method, getter)]
|
||||
fn next(this: &MaybeIterator) -> JsValue;
|
||||
}
|
||||
|
||||
let iter_sym = Symbol::iterator();
|
||||
let iter_fn = Reflect::get(val, iter_sym.as_ref())?;
|
||||
if !iter_fn.is_function() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let iter_fn: Function = iter_fn.unchecked_into();
|
||||
let it = iter_fn.call0(val)?;
|
||||
if !it.is_object() {
|
||||
return Ok(None);
|
||||
}
|
||||
let iter_fn: Function = match iter_fn.dyn_into() {
|
||||
Ok(iter_fn) => iter_fn,
|
||||
Err(_) => return Ok(None),
|
||||
};
|
||||
|
||||
let next = it.unchecked_ref::<MaybeIterator>().next();
|
||||
let it: Iterator = match iter_fn.call0(val)?.dyn_into() {
|
||||
Ok(it) => it,
|
||||
Err(_) => return Ok(None),
|
||||
};
|
||||
|
||||
Ok(if next.is_function() {
|
||||
let it: Iterator = it.unchecked_into();
|
||||
Some(it.into_iter())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
Ok(Some(it.into_iter()))
|
||||
}
|
||||
|
||||
// IteratorNext
|
||||
@ -1135,7 +1166,8 @@ extern "C" {
|
||||
/// The result of calling `next()` on a JS iterator.
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type IteratorNext;
|
||||
|
||||
/// Has the value `true` if the iterator is past the end of the iterated
|
||||
@ -1157,8 +1189,8 @@ extern "C" {
|
||||
// Math
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Math;
|
||||
|
||||
/// The Math.abs() function returns the absolute value of a number, that is
|
||||
@ -1405,8 +1437,8 @@ extern "C" {
|
||||
// Number.
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object, is_type_of = |v| v.as_f64().is_some())]
|
||||
#[derive(Clone)]
|
||||
pub type Number;
|
||||
|
||||
/// The Number.isFinite() method determines whether the passed value is a finite number.
|
||||
@ -1441,6 +1473,7 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)
|
||||
#[wasm_bindgen(constructor)]
|
||||
#[deprecated(note = "recommended to use `Number::from` instead")]
|
||||
pub fn new(value: &JsValue) -> Number;
|
||||
|
||||
/// The Number.parseInt() method parses a string argument and returns an
|
||||
@ -1500,11 +1533,43 @@ extern "C" {
|
||||
pub fn value_of(this: &Number) -> f64;
|
||||
}
|
||||
|
||||
macro_rules! number_from {
|
||||
($($x:ident)*) => ($(
|
||||
impl From<$x> for Number {
|
||||
#[inline]
|
||||
fn from(x: $x) -> Number {
|
||||
Number::unchecked_from_js(JsValue::from(x))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<$x> for Number {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$x) -> bool {
|
||||
self.value_of() == f64::from(*other)
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
number_from!(i8 u8 i16 u16 i32 u32 f32 f64);
|
||||
|
||||
impl From<Number> for f64 {
|
||||
#[inline]
|
||||
fn from(n: Number) -> f64 {
|
||||
n.value_of()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Number {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.value_of().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// Date.
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Date;
|
||||
|
||||
/// The getDate() method returns the day of the month for the
|
||||
@ -2091,13 +2156,22 @@ impl Object {
|
||||
/// `None`.
|
||||
pub fn try_from(val: &JsValue) -> Option<&Object> {
|
||||
if val.is_object() {
|
||||
Some(unsafe { mem::transmute(val) })
|
||||
Some(val.unchecked_ref())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Object {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Object) -> bool {
|
||||
Object::is(self.as_ref(), other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Object {}
|
||||
|
||||
// Proxy
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
@ -2128,7 +2202,7 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError)
|
||||
#[wasm_bindgen(extends = Error, extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type RangeError;
|
||||
|
||||
/// The RangeError object indicates an error when a value is not in the set
|
||||
@ -2147,7 +2221,7 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError)
|
||||
#[wasm_bindgen(extends = Error, extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type ReferenceError;
|
||||
|
||||
/// The ReferenceError object represents an error when a non-existent
|
||||
@ -2161,8 +2235,8 @@ extern "C" {
|
||||
// Reflect
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Reflect;
|
||||
|
||||
/// The static `Reflect.apply()` method calls a target function with
|
||||
@ -2321,7 +2395,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type RegExp;
|
||||
|
||||
/// The exec() method executes a search for a match in a specified
|
||||
@ -2498,7 +2572,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Set;
|
||||
|
||||
/// The `add()` method appends a new element with a specified value to the
|
||||
@ -2588,7 +2662,7 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError)
|
||||
#[wasm_bindgen(extends = Error, extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type SyntaxError;
|
||||
|
||||
/// A SyntaxError is thrown when the JavaScript engine encounters tokens or
|
||||
@ -2608,7 +2682,7 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError)
|
||||
#[wasm_bindgen(extends = Error, extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type TypeError;
|
||||
|
||||
/// The TypeError object represents an error when a value is not of the
|
||||
@ -2627,7 +2701,7 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError)
|
||||
#[wasm_bindgen(extends = Error, extends = Object, js_name = URIError)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type UriError;
|
||||
|
||||
/// The URIError object represents an error when a global URI handling
|
||||
@ -2642,7 +2716,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type WeakMap;
|
||||
|
||||
/// The [`WeakMap`] object is a collection of key/value pairs in which the
|
||||
@ -2686,7 +2760,7 @@ extern "C" {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type WeakSet;
|
||||
|
||||
/// The `WeakSet` object lets you store weakly held objects in a collection.
|
||||
@ -2773,7 +2847,7 @@ pub mod WebAssembly {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/CompileError)
|
||||
#[wasm_bindgen(extends = Error, js_namespace = WebAssembly)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type CompileError;
|
||||
|
||||
/// The `WebAssembly.CompileError()` constructor creates a new
|
||||
@ -2795,7 +2869,7 @@ pub mod WebAssembly {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance)
|
||||
#[wasm_bindgen(extends = Object, js_namespace = WebAssembly)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Instance;
|
||||
|
||||
/// The `WebAssembly.Instance()` constructor function can be called to
|
||||
@ -2826,7 +2900,7 @@ pub mod WebAssembly {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/LinkError)
|
||||
#[wasm_bindgen(extends = Error, js_namespace = WebAssembly)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type LinkError;
|
||||
|
||||
/// The `WebAssembly.LinkError()` constructor creates a new WebAssembly
|
||||
@ -2847,7 +2921,7 @@ pub mod WebAssembly {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/RuntimeError)
|
||||
#[wasm_bindgen(extends = Error, js_namespace = WebAssembly)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type RuntimeError;
|
||||
|
||||
/// The `WebAssembly.RuntimeError()` constructor creates a new WebAssembly
|
||||
@ -2868,7 +2942,7 @@ pub mod WebAssembly {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module)
|
||||
#[wasm_bindgen(js_namespace = WebAssembly, extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Module;
|
||||
|
||||
/// A `WebAssembly.Module` object contains stateless WebAssembly code
|
||||
@ -2910,7 +2984,7 @@ pub mod WebAssembly {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table)
|
||||
#[wasm_bindgen(js_namespace = WebAssembly, extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Table;
|
||||
|
||||
/// The `WebAssembly.Table()` constructor creates a new `Table` object
|
||||
@ -2956,7 +3030,7 @@ pub mod WebAssembly {
|
||||
extern "C" {
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory)
|
||||
#[wasm_bindgen(js_namespace = WebAssembly, extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type Memory;
|
||||
|
||||
/// The `WebAssembly.Memory()` constructor creates a new `Memory` object
|
||||
@ -2997,8 +3071,8 @@ extern "C" {
|
||||
/// Notation (JSON)](https://json.org/) and converting values to JSON. It
|
||||
/// can't be called or constructed, and aside from its two method
|
||||
/// properties, it has no interesting functionality of its own.
|
||||
#[derive(Clone, Debug)]
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub type JSON;
|
||||
|
||||
/// The `JSON.parse()` method parses a JSON string, constructing the
|
||||
@ -3056,8 +3130,8 @@ extern "C" {
|
||||
// JsString
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_name = String, extends = Object)]
|
||||
#[derive(Clone)]
|
||||
#[wasm_bindgen(js_name = String, extends = Object, is_type_of = JsValue::is_string)]
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub type JsString;
|
||||
|
||||
/// The length property of a String object indicates the length of a string,
|
||||
@ -3516,11 +3590,38 @@ impl JsString {
|
||||
/// If this JS value is not an instance of a string then this returns
|
||||
/// `None`.
|
||||
pub fn try_from(val: &JsValue) -> Option<&JsString> {
|
||||
if val.is_string() {
|
||||
Some(unsafe { mem::transmute(val) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
val.dyn_ref()
|
||||
}
|
||||
|
||||
/// Returns whether this string is a valid UTF-16 string.
|
||||
///
|
||||
/// This is useful for learning whether `String::from(..)` will return a
|
||||
/// lossless representation of the JS string. If this string contains
|
||||
/// unpaired surrogates then `String::from` will succeed but it will be a
|
||||
/// lossy representation of the JS string because unpaired surrogates will
|
||||
/// become replacement characters.
|
||||
///
|
||||
/// If this function returns `false` then to get a lossless representation
|
||||
/// of the string you'll need to manually use the `iter` method (or the
|
||||
/// `char_code_at` accessor) to view the raw character codes.
|
||||
///
|
||||
/// For more information, see the documentation on [JS strings vs Rust
|
||||
/// strings][docs]
|
||||
///
|
||||
/// [docs]: https://rustwasm.github.io/docs/wasm-bindgen/reference/types/str.html
|
||||
pub fn is_valid_utf16(&self) -> bool {
|
||||
std::char::decode_utf16(self.iter()).all(|i| i.is_ok())
|
||||
}
|
||||
|
||||
/// Returns an iterator over the `u16` character codes that make up this JS
|
||||
/// string.
|
||||
///
|
||||
/// This method will call `char_code_at` for each code in this JS string,
|
||||
/// returning an iterator of the codes in sequence.
|
||||
pub fn iter<'a>(
|
||||
&'a self,
|
||||
) -> impl ExactSizeIterator<Item = u16> + DoubleEndedIterator<Item = u16> + 'a {
|
||||
(0..self.length()).map(move |i| self.char_code_at(i) as u16)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3550,9 +3651,7 @@ impl<'a> PartialEq<&'a String> for JsString {
|
||||
|
||||
impl<'a> From<&'a str> for JsString {
|
||||
fn from(s: &'a str) -> Self {
|
||||
JsString {
|
||||
obj: JsValue::from_str(s),
|
||||
}
|
||||
JsString::unchecked_from_js(JsValue::from_str(s))
|
||||
}
|
||||
}
|
||||
|
||||
@ -3583,6 +3682,7 @@ impl fmt::Debug for JsString {
|
||||
// Symbol
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(is_type_of = JsValue::is_symbol)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub type Symbol;
|
||||
|
||||
|
@ -541,3 +541,15 @@ fn raw() {
|
||||
);
|
||||
assert!(JsString::raw_0(&JsValue::null().unchecked_into()).is_err());
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn is_valid_utf16() {
|
||||
assert!(JsString::from("a").is_valid_utf16());
|
||||
assert!(JsString::from("").is_valid_utf16());
|
||||
assert!(JsString::from("🥑").is_valid_utf16());
|
||||
assert!(JsString::from("Why hello there this, 🥑, is 🥑 and is 🥑").is_valid_utf16());
|
||||
|
||||
assert!(JsString::from_char_code1(0x00).is_valid_utf16());
|
||||
assert!(!JsString::from_char_code1(0xd800).is_valid_utf16());
|
||||
assert!(!JsString::from_char_code1(0xdc00).is_valid_utf16());
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro-support"
|
||||
@ -20,5 +20,5 @@ strict-macro = []
|
||||
syn = { version = '0.15.0', features = ['visit'] }
|
||||
quote = '0.6'
|
||||
proc-macro2 = "0.4.9"
|
||||
wasm-bindgen-backend = { path = "../backend", version = "=0.2.40" }
|
||||
wasm-bindgen-shared = { path = "../shared", version = "=0.2.40" }
|
||||
wasm-bindgen-backend = { path = "../backend", version = "=0.2.42" }
|
||||
wasm-bindgen-shared = { path = "../shared", version = "=0.2.42" }
|
||||
|
@ -45,6 +45,7 @@ macro_rules! attrgen {
|
||||
(readonly, Readonly(Span)),
|
||||
(js_name, JsName(Span, String, Span)),
|
||||
(js_class, JsClass(Span, String, Span)),
|
||||
(is_type_of, IsTypeOf(Span, syn::Expr)),
|
||||
(extends, Extends(Span, syn::Path)),
|
||||
(vendor_prefix, VendorPrefix(Span, Ident)),
|
||||
(variadic, Variadic(Span)),
|
||||
@ -241,6 +242,11 @@ impl Parse for BindgenAttr {
|
||||
return Ok(BindgenAttr::$variant(attr_span, input.parse()?));
|
||||
});
|
||||
|
||||
(@parser $variant:ident(Span, syn::Expr)) => ({
|
||||
input.parse::<Token![=]>()?;
|
||||
return Ok(BindgenAttr::$variant(attr_span, input.parse()?));
|
||||
});
|
||||
|
||||
(@parser $variant:ident(Span, String, Span)) => ({
|
||||
input.parse::<Token![=]>()?;
|
||||
let (val, span) = match input.parse::<syn::LitStr>() {
|
||||
@ -523,6 +529,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
|
||||
.js_name()
|
||||
.map(|s| s.0)
|
||||
.map_or_else(|| self.ident.to_string(), |s| s.to_string());
|
||||
let is_type_of = attrs.is_type_of().cloned();
|
||||
let shim = format!("__wbg_instanceof_{}_{}", self.ident, ShortHash(&self.ident));
|
||||
let mut extends = Vec::new();
|
||||
let mut vendor_prefixes = Vec::new();
|
||||
@ -545,6 +552,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
|
||||
attrs: self.attrs,
|
||||
doc_comment: None,
|
||||
instanceof_shim: shim,
|
||||
is_type_of,
|
||||
rust_name: self.ident,
|
||||
js_name,
|
||||
extends,
|
||||
@ -904,7 +912,7 @@ fn prepare_for_impl_recursion(
|
||||
pound_token: Default::default(),
|
||||
style: syn::AttrStyle::Outer,
|
||||
bracket_token: Default::default(),
|
||||
path: syn::Ident::new("__wasm_bindgen_class_marker", Span::call_site()).into(),
|
||||
path: syn::parse_quote! { wasm_bindgen::prelude::__wasm_bindgen_class_marker },
|
||||
tts: quote::quote! { (#class = #js_class) }.into(),
|
||||
},
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro"
|
||||
@ -20,5 +20,5 @@ xxx_debug_only_print_generated_code = []
|
||||
strict-macro = ["wasm-bindgen-macro-support/strict-macro"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen-macro-support = { path = "../macro-support", version = "=0.2.40" }
|
||||
wasm-bindgen-macro-support = { path = "../macro-support", version = "=0.2.42" }
|
||||
quote = "0.6"
|
||||
|
10
crates/macro/ui-tests/pub-not-copy.rs
Normal file
10
crates/macro/ui-tests/pub-not-copy.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct A {
|
||||
pub field: String,
|
||||
}
|
15
crates/macro/ui-tests/pub-not-copy.stderr
Normal file
15
crates/macro/ui-tests/pub-not-copy.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
|
||||
--> $DIR/pub-not-copy.rs:9:16
|
||||
|
|
||||
9 | pub field: String,
|
||||
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
||||
|
|
||||
note: required by `__wbg_get_a_field::assert_copy`
|
||||
--> $DIR/pub-not-copy.rs:7:1
|
||||
|
|
||||
7 | #[wasm_bindgen]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/shared"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
description = "Internal testing macro for wasm-bindgen"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
description = "Internal testing crate for wasm-bindgen"
|
||||
license = "MIT/Apache-2.0"
|
||||
@ -10,11 +10,11 @@ edition = "2018"
|
||||
[dependencies]
|
||||
console_error_panic_hook = '0.1'
|
||||
futures = "0.1"
|
||||
js-sys = { path = '../js-sys', version = '0.3.17' }
|
||||
js-sys = { path = '../js-sys', version = '0.3.19' }
|
||||
scoped-tls = "1.0"
|
||||
wasm-bindgen = { path = '../..', version = '0.2.40' }
|
||||
wasm-bindgen-futures = { path = '../futures', version = '0.3.17' }
|
||||
wasm-bindgen-test-macro = { path = '../test-macro', version = '=0.2.40' }
|
||||
wasm-bindgen = { path = '../..', version = '0.2.42' }
|
||||
wasm-bindgen-futures = { path = '../futures', version = '0.3.19' }
|
||||
wasm-bindgen-test-macro = { path = '../test-macro', version = '=0.2.42' }
|
||||
|
||||
[lib]
|
||||
test = false
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-threads-xform"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/threads-xform"
|
||||
|
@ -11,6 +11,13 @@ cargo run -p wasm-bindgen-cli --bin wasm-bindgen -- \
|
||||
--out-dir pkg \
|
||||
--typescript
|
||||
|
||||
mkdir pkg/web
|
||||
cargo run -p wasm-bindgen-cli --bin wasm-bindgen -- \
|
||||
../../target/wasm32-unknown-unknown/debug/typescript_tests.wasm \
|
||||
--out-dir pkg/web \
|
||||
--target web \
|
||||
--typescript
|
||||
|
||||
if [ ! -d node_modules ]; then
|
||||
npm install
|
||||
fi
|
||||
|
3
crates/typescript-tests/src/web/init.ts
Normal file
3
crates/typescript-tests/src/web/init.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import * as wbg from '../../pkg/web/typescript_tests';
|
||||
|
||||
const init: Promise<any> = wbg.init('.');
|
@ -9,6 +9,6 @@
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": [
|
||||
"src/*.ts"
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-wasm-interpreter"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rustwasm/wasm-bindgen/tree/master/crates/wasm-interpreter"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "web-sys"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
readme = "./README.md"
|
||||
homepage = "https://rustwasm.github.io/wasm-bindgen/web-sys/index.html"
|
||||
@ -22,17 +22,17 @@ test = false
|
||||
[build-dependencies]
|
||||
env_logger = "0.6.0"
|
||||
failure = "0.1.2"
|
||||
wasm-bindgen-webidl = { path = "../webidl", version = "=0.2.40" }
|
||||
wasm-bindgen-webidl = { path = "../webidl", version = "=0.2.42" }
|
||||
sourcefile = "0.1"
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = { path = "../..", version = "0.2.40" }
|
||||
js-sys = { path = '../js-sys', version = '0.3.17' }
|
||||
wasm-bindgen = { path = "../..", version = "0.2.42" }
|
||||
js-sys = { path = '../js-sys', version = '0.3.19' }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
|
||||
futures = "0.1"
|
||||
wasm-bindgen-test = { path = '../test', version = '0.2.40' }
|
||||
wasm-bindgen-futures = { path = '../futures', version = '0.3.17' }
|
||||
wasm-bindgen-test = { path = '../test', version = '0.2.42' }
|
||||
wasm-bindgen-futures = { path = '../futures', version = '0.3.19' }
|
||||
|
||||
# This list is generated by passing `__WASM_BINDGEN_DUMP_FEATURES=foo` when
|
||||
# compiling this crate which dumps the total list of features to a file called
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "wasm-bindgen-webidl"
|
||||
version = "0.2.40"
|
||||
version = "0.2.42"
|
||||
authors = ["The wasm-bindgen Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
categories = ["wasm"]
|
||||
@ -19,5 +19,5 @@ log = "0.4.1"
|
||||
proc-macro2 = "0.4.8"
|
||||
quote = '0.6'
|
||||
syn = { version = '0.15', features = ['full'] }
|
||||
wasm-bindgen-backend = { version = "=0.2.40", path = "../backend" }
|
||||
wasm-bindgen-backend = { version = "=0.2.42", path = "../backend" }
|
||||
weedle = "0.8"
|
||||
|
@ -514,6 +514,7 @@ impl<'src> FirstPassRecord<'src> {
|
||||
attrs,
|
||||
doc_comment: None,
|
||||
instanceof_shim: format!("__widl_instanceof_{}", name),
|
||||
is_type_of: None,
|
||||
extends: Vec::new(),
|
||||
vendor_prefixes: Vec::new(),
|
||||
};
|
||||
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
@ -8,8 +8,8 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
js-sys = "0.3.17"
|
||||
wasm-bindgen = "0.2.40"
|
||||
js-sys = "0.3.19"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
@ -8,8 +8,8 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
js-sys = "0.3.17"
|
||||
wasm-bindgen = "0.2.42"
|
||||
js-sys = "0.3.19"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,5 +8,5 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
web-sys = { version = "0.3.17", features = ['console'] }
|
||||
wasm-bindgen = "0.2.42"
|
||||
web-sys = { version = "0.3.19", features = ['console'] }
|
||||
|
@ -8,7 +8,7 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
@ -9,9 +9,9 @@ crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
futures = "0.1.20"
|
||||
wasm-bindgen = { version = "0.2.40", features = ["serde-serialize"] }
|
||||
js-sys = "0.3.17"
|
||||
wasm-bindgen-futures = "0.3.17"
|
||||
wasm-bindgen = { version = "0.2.42", features = ["serde-serialize"] }
|
||||
js-sys = "0.3.19"
|
||||
wasm-bindgen-futures = "0.3.19"
|
||||
serde = { version = "1.0.80", features = ["derive"] }
|
||||
serde_derive = "^1.0.59"
|
||||
|
||||
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
@ -8,7 +8,7 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,8 +8,8 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
js-sys = "0.3.17"
|
||||
wasm-bindgen = "0.2.40"
|
||||
js-sys = "0.3.19"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,7 +8,7 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
humantime = "1"
|
||||
|
||||
[dependencies.web-sys]
|
||||
|
@ -10,10 +10,10 @@ crate-type = ["cdylib"]
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1"
|
||||
futures = "0.1"
|
||||
js-sys = "0.3.17"
|
||||
js-sys = "0.3.19"
|
||||
raytracer = { git = 'https://github.com/alexcrichton/raytracer', branch = 'update-deps' }
|
||||
wasm-bindgen = { version = "0.2.40", features = ['serde-serialize'] }
|
||||
wasm-bindgen-futures = "0.3.17"
|
||||
wasm-bindgen = { version = "0.2.42", features = ['serde-serialize'] }
|
||||
wasm-bindgen-futures = "0.3.19"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,7 +8,7 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -11,8 +11,8 @@ crate-type = ["cdylib"]
|
||||
askama = "0.7.2"
|
||||
|
||||
[dependencies]
|
||||
js-sys = "0.3.17"
|
||||
wasm-bindgen = "0.2.40"
|
||||
js-sys = "0.3.19"
|
||||
wasm-bindgen = "0.2.42"
|
||||
askama = "0.7.2"
|
||||
console_error_panic_hook = "0.1.5"
|
||||
|
||||
|
@ -8,5 +8,5 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
js-sys = "0.3.17"
|
||||
wasm-bindgen = "0.2.42"
|
||||
js-sys = "0.3.19"
|
||||
|
@ -8,4 +8,4 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
@ -8,7 +8,7 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,8 +8,8 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
js-sys = "0.3.17"
|
||||
wasm-bindgen = "0.2.40"
|
||||
js-sys = "0.3.19"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -8,7 +8,7 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2.40"
|
||||
wasm-bindgen = "0.2.42"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.4"
|
||||
|
@ -20,3 +20,7 @@ development. You may want to browse the [unpublished guide documentation] for
|
||||
as that is when WebAssembly support was introduced. [Install Node].
|
||||
|
||||
[Install Node]: https://nodejs.org/en/
|
||||
|
||||
## Code Formatting
|
||||
|
||||
Although formatting rules are not mandatory, it is encouraged to run `cargo run` (`rustfmt`) with its default rules within a PR to maintain a more organized code base. If necessary, a PR with a single commit that formats the entire project is also welcome.
|
@ -20,3 +20,30 @@ with handles to JavaScript string values, use the `js_sys::JsString` type.
|
||||
```js
|
||||
{{#include ../../../../examples/guide-supported-types-examples/str.js}}
|
||||
```
|
||||
|
||||
## UTF-16 vs UTF-8
|
||||
|
||||
Strings in JavaScript are encoded as UTF-16, but with one major exception: they
|
||||
can contain unpaired surrogates. For some Unicode characters UTF-16 uses two
|
||||
16-byte values. These are called "surrogate pairs" because they always come in
|
||||
pairs. In JavaScript, it is possible for these surrogate pairs to be missing the
|
||||
other half, creating an "unpaired surrogate".
|
||||
|
||||
When passing a string from JavaScript to Rust, it uses the `TextEncoder` API to
|
||||
convert from UTF-16 to UTF-8. This is normally perfectly fine... unless there
|
||||
are unpaired surrogates. In that case it will replace the unpaired surrogates
|
||||
with U+FFFD (<28>, the replacement character). That means the string in Rust is
|
||||
now different from the string in JavaScript!
|
||||
|
||||
If you want to guarantee that the Rust string is the same as the JavaScript
|
||||
string, you should instead use `js_sys::JsString` (which keeps the string in
|
||||
JavaScript and doesn't copy it into Rust).
|
||||
|
||||
If you want to access the raw value of a JS string, you can use `JsString::iter`,
|
||||
which returns an `Iterator<Item = u16>`. This perfectly preserves everything
|
||||
(including unpaired surrogates), but it does not do any encoding (so you
|
||||
have to do that yourself!).
|
||||
|
||||
If you simply want to ignore strings which contain unpaired surrogates, you can
|
||||
use `JsString::is_valid_utf16` to test whether the string contains unpaired
|
||||
surrogates or not.
|
||||
|
@ -8,6 +8,9 @@ Copies the string's contents back and forth between the JavaScript
|
||||
garbage-collected heap and the Wasm linear memory with `TextDecoder` and
|
||||
`TextEncoder`
|
||||
|
||||
> **Note**: Be sure to check out the [documentation for `str`](str.html) to
|
||||
> learn about some caveats when working with strings between JS and Rust.
|
||||
|
||||
## Example Rust Usage
|
||||
|
||||
```rust
|
||||
|
61
src/cast.rs
61
src/cast.rs
@ -16,28 +16,35 @@ pub trait JsCast
|
||||
where
|
||||
Self: AsRef<JsValue> + Into<JsValue>,
|
||||
{
|
||||
/// Test whether this JS value is an instance of the type `T`.
|
||||
/// Test whether this JS value has a type `T`.
|
||||
///
|
||||
/// This method performs a dynamic check (at runtime) using the JS
|
||||
/// `instanceof` operator. This method returns `self instanceof T`.
|
||||
fn is_instance_of<T>(&self) -> bool
|
||||
/// This method will dynamically check to see if this JS object can be
|
||||
/// casted to the JS object of type `T`. Usually this uses the `instanceof`
|
||||
/// operator. This also works with primitive types like
|
||||
/// booleans/strings/numbers as well as cross-realm object like `Array`
|
||||
/// which can originate from other iframes.
|
||||
///
|
||||
/// In general this is intended to be a more robust version of
|
||||
/// `is_instance_of`, but if you want strictly the `instanceof` operator
|
||||
/// it's recommended to use that instead.
|
||||
fn has_type<T>(&self) -> bool
|
||||
where
|
||||
T: JsCast,
|
||||
{
|
||||
T::instanceof(self.as_ref())
|
||||
T::is_type_of(self.as_ref())
|
||||
}
|
||||
|
||||
/// Performs a dynamic cast (checked at runtime) of this value into the
|
||||
/// target type `T`.
|
||||
///
|
||||
/// This method will return `Err(self)` if `self.is_instance_of::<T>()`
|
||||
/// This method will return `Err(self)` if `self.has_type::<T>()`
|
||||
/// returns `false`, and otherwise it will return `Ok(T)` manufactured with
|
||||
/// an unchecked cast (verified correct via the `instanceof` operation).
|
||||
/// an unchecked cast (verified correct via the `has_type` operation).
|
||||
fn dyn_into<T>(self) -> Result<T, Self>
|
||||
where
|
||||
T: JsCast,
|
||||
{
|
||||
if self.is_instance_of::<T>() {
|
||||
if self.has_type::<T>() {
|
||||
Ok(self.unchecked_into())
|
||||
} else {
|
||||
Err(self)
|
||||
@ -47,14 +54,14 @@ where
|
||||
/// Performs a dynamic cast (checked at runtime) of this value into the
|
||||
/// target type `T`.
|
||||
///
|
||||
/// This method will return `None` if `self.is_instance_of::<T>()`
|
||||
/// This method will return `None` if `self.has_type::<T>()`
|
||||
/// returns `false`, and otherwise it will return `Some(&T)` manufactured
|
||||
/// with an unchecked cast (verified correct via the `instanceof` operation).
|
||||
/// with an unchecked cast (verified correct via the `has_type` operation).
|
||||
fn dyn_ref<T>(&self) -> Option<&T>
|
||||
where
|
||||
T: JsCast,
|
||||
{
|
||||
if self.is_instance_of::<T>() {
|
||||
if self.has_type::<T>() {
|
||||
Some(self.unchecked_ref())
|
||||
} else {
|
||||
None
|
||||
@ -93,13 +100,43 @@ where
|
||||
T::unchecked_from_js_ref(self.as_ref())
|
||||
}
|
||||
|
||||
/// Test whether this JS value is an instance of the type `T`.
|
||||
///
|
||||
/// This method performs a dynamic check (at runtime) using the JS
|
||||
/// `instanceof` operator. This method returns `self instanceof T`.
|
||||
///
|
||||
/// Note that `instanceof` does not always work with primitive values or
|
||||
/// across different realms (e.g. iframes). If you're not sure whether you
|
||||
/// specifically need only `instanceof` it's recommended to use `has_type`
|
||||
/// instead.
|
||||
fn is_instance_of<T>(&self) -> bool
|
||||
where
|
||||
T: JsCast,
|
||||
{
|
||||
T::instanceof(self.as_ref())
|
||||
}
|
||||
|
||||
/// Performs a dynamic `instanceof` check to see whether the `JsValue`
|
||||
/// provided is an instance of this type.
|
||||
///
|
||||
/// This is intended to be an internal implementation detail, you likely
|
||||
/// won't need to call this.
|
||||
/// won't need to call this. It's generally called through the
|
||||
/// `is_instance_of` method instead.
|
||||
fn instanceof(val: &JsValue) -> bool;
|
||||
|
||||
/// Performs a dynamic check to see whether the `JsValue` provided
|
||||
/// is a value of this type.
|
||||
///
|
||||
/// Unlike `instanceof`, this can be specialised to use a custom check by
|
||||
/// adding a `#[wasm_bindgen(is_type_of = callback)]` attribute to the
|
||||
/// type import declaration.
|
||||
///
|
||||
/// Other than that, this is intended to be an internal implementation
|
||||
/// detail of `has_type` and you likely won't need to call this.
|
||||
fn is_type_of(val: &JsValue) -> bool {
|
||||
Self::instanceof(val)
|
||||
}
|
||||
|
||||
/// Performs a zero-cost unchecked conversion from a `JsValue` into an
|
||||
/// instance of `Self`
|
||||
///
|
||||
|
151
src/closure.rs
151
src/closure.rs
@ -519,7 +519,7 @@ where
|
||||
/// This trait is not stable and it's not recommended to use this in bounds or
|
||||
/// implement yourself.
|
||||
#[doc(hidden)]
|
||||
pub unsafe trait WasmClosure: 'static {
|
||||
pub unsafe trait WasmClosure {
|
||||
fn describe();
|
||||
}
|
||||
|
||||
@ -541,7 +541,7 @@ macro_rules! doit {
|
||||
($(
|
||||
($($var:ident)*)
|
||||
)*) => ($(
|
||||
unsafe impl<$($var,)* R> WasmClosure for Fn($($var),*) -> R
|
||||
unsafe impl<$($var,)* R> WasmClosure for Fn($($var),*) -> R + 'static
|
||||
where $($var: FromWasmAbi + 'static,)*
|
||||
R: ReturnWasmAbi + 'static,
|
||||
{
|
||||
@ -587,7 +587,7 @@ macro_rules! doit {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<$($var,)* R> WasmClosure for FnMut($($var),*) -> R
|
||||
unsafe impl<$($var,)* R> WasmClosure for FnMut($($var),*) -> R + 'static
|
||||
where $($var: FromWasmAbi + 'static,)*
|
||||
R: ReturnWasmAbi + 'static,
|
||||
{
|
||||
@ -696,3 +696,148 @@ doit! {
|
||||
(A B C D E F)
|
||||
(A B C D E F G)
|
||||
}
|
||||
|
||||
// Copy the above impls down here for where there's only one argument and it's a
|
||||
// reference. We could add more impls for more kinds of references, but it
|
||||
// becomes a combinatorial explosion quickly. Let's see how far we can get with
|
||||
// just this one! Maybe someone else can figure out voodoo so we don't have to
|
||||
// duplicate.
|
||||
|
||||
unsafe impl<A, R> WasmClosure for Fn(&A) -> R
|
||||
where A: RefFromWasmAbi,
|
||||
R: ReturnWasmAbi + 'static,
|
||||
{
|
||||
fn describe() {
|
||||
#[allow(non_snake_case)]
|
||||
unsafe extern "C" fn invoke<A: RefFromWasmAbi, R: ReturnWasmAbi>(
|
||||
a: usize,
|
||||
b: usize,
|
||||
arg: <A as RefFromWasmAbi>::Abi,
|
||||
) -> <R as ReturnWasmAbi>::Abi {
|
||||
if a == 0 {
|
||||
throw_str("closure invoked recursively or destroyed already");
|
||||
}
|
||||
// Make sure all stack variables are converted before we
|
||||
// convert `ret` as it may throw (for `Result`, for
|
||||
// example)
|
||||
let ret = {
|
||||
let f: *const Fn(&A) -> R =
|
||||
FatPtr { fields: (a, b) }.ptr;
|
||||
let mut _stack = GlobalStack::new();
|
||||
let arg = <A as RefFromWasmAbi>::ref_from_abi(arg, &mut _stack);
|
||||
(*f)(&*arg)
|
||||
};
|
||||
ret.return_abi(&mut GlobalStack::new())
|
||||
}
|
||||
|
||||
inform(invoke::<A, R> as u32);
|
||||
|
||||
unsafe extern fn destroy<A: RefFromWasmAbi, R: ReturnWasmAbi>(
|
||||
a: usize,
|
||||
b: usize,
|
||||
) {
|
||||
debug_assert!(a != 0, "should never destroy a Fn whose pointer is 0");
|
||||
drop(Box::from_raw(FatPtr::<Fn(&A) -> R> {
|
||||
fields: (a, b)
|
||||
}.ptr));
|
||||
}
|
||||
inform(destroy::<A, R> as u32);
|
||||
|
||||
<&Self>::describe();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A, R> WasmClosure for FnMut(&A) -> R
|
||||
where A: RefFromWasmAbi,
|
||||
R: ReturnWasmAbi + 'static,
|
||||
{
|
||||
fn describe() {
|
||||
#[allow(non_snake_case)]
|
||||
unsafe extern "C" fn invoke<A: RefFromWasmAbi, R: ReturnWasmAbi>(
|
||||
a: usize,
|
||||
b: usize,
|
||||
arg: <A as RefFromWasmAbi>::Abi,
|
||||
) -> <R as ReturnWasmAbi>::Abi {
|
||||
if a == 0 {
|
||||
throw_str("closure invoked recursively or destroyed already");
|
||||
}
|
||||
// Make sure all stack variables are converted before we
|
||||
// convert `ret` as it may throw (for `Result`, for
|
||||
// example)
|
||||
let ret = {
|
||||
let f: *const FnMut(&A) -> R =
|
||||
FatPtr { fields: (a, b) }.ptr;
|
||||
let f = f as *mut FnMut(&A) -> R;
|
||||
let mut _stack = GlobalStack::new();
|
||||
let arg = <A as RefFromWasmAbi>::ref_from_abi(arg, &mut _stack);
|
||||
(*f)(&*arg)
|
||||
};
|
||||
ret.return_abi(&mut GlobalStack::new())
|
||||
}
|
||||
|
||||
inform(invoke::<A, R> as u32);
|
||||
|
||||
unsafe extern fn destroy<A: RefFromWasmAbi, R: ReturnWasmAbi>(
|
||||
a: usize,
|
||||
b: usize,
|
||||
) {
|
||||
debug_assert!(a != 0, "should never destroy a FnMut whose pointer is 0");
|
||||
drop(Box::from_raw(FatPtr::<FnMut(&A) -> R> {
|
||||
fields: (a, b)
|
||||
}.ptr));
|
||||
}
|
||||
inform(destroy::<A, R> as u32);
|
||||
|
||||
<&mut Self>::describe();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl<T, A, R> WasmClosureFnOnce<(&A,), R> for T
|
||||
where T: 'static + FnOnce(&A) -> R,
|
||||
A: RefFromWasmAbi + 'static,
|
||||
R: ReturnWasmAbi + 'static
|
||||
{
|
||||
type FnMut = FnMut(&A) -> R;
|
||||
|
||||
fn into_fn_mut(self) -> Box<Self::FnMut> {
|
||||
let mut me = Some(self);
|
||||
Box::new(move |arg| {
|
||||
let me = me.take().expect_throw("FnOnce called more than once");
|
||||
me(arg)
|
||||
})
|
||||
}
|
||||
|
||||
fn into_js_function(self) -> JsValue {
|
||||
use std::rc::Rc;
|
||||
use crate::__rt::WasmRefCell;
|
||||
|
||||
let mut me = Some(self);
|
||||
|
||||
let rc1 = Rc::new(WasmRefCell::new(None));
|
||||
let rc2 = rc1.clone();
|
||||
|
||||
let closure = Closure::wrap(Box::new(move |arg: &A| {
|
||||
// Invoke ourself and get the result.
|
||||
let me = me.take().expect_throw("FnOnce called more than once");
|
||||
let result = me(arg);
|
||||
|
||||
// And then drop the `Rc` holding this function's `Closure`
|
||||
// alive.
|
||||
debug_assert_eq!(Rc::strong_count(&rc2), 1);
|
||||
let option_closure = rc2.borrow_mut().take();
|
||||
debug_assert!(option_closure.is_some());
|
||||
drop(option_closure);
|
||||
|
||||
result
|
||||
}) as Box<FnMut(&A) -> R>);
|
||||
|
||||
let js_val = closure.as_ref().clone();
|
||||
|
||||
*rc1.borrow_mut() = Some(closure);
|
||||
debug_assert_eq!(Rc::strong_count(&rc1), 2);
|
||||
drop(rc1);
|
||||
|
||||
js_val
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use core::mem;
|
||||
|
||||
use crate::convert::slices::WasmSlice;
|
||||
use crate::convert::{FromWasmAbi, GlobalStack, IntoWasmAbi, ReturnWasmAbi, Stack};
|
||||
use crate::convert::RefFromWasmAbi;
|
||||
use crate::describe::{inform, WasmDescribe, FUNCTION};
|
||||
use crate::throw_str;
|
||||
|
||||
@ -117,3 +118,97 @@ stack_closures! {
|
||||
(6 invoke6 invoke6_mut A B C D E F)
|
||||
(7 invoke7 invoke7_mut A B C D E F G)
|
||||
}
|
||||
|
||||
impl<'a, 'b, A, R> IntoWasmAbi for &'a (Fn(&A) -> R + 'b)
|
||||
where A: RefFromWasmAbi,
|
||||
R: ReturnWasmAbi
|
||||
{
|
||||
type Abi = WasmSlice;
|
||||
|
||||
fn into_abi(self, _extra: &mut Stack) -> WasmSlice {
|
||||
unsafe {
|
||||
let (a, b): (usize, usize) = mem::transmute(self);
|
||||
WasmSlice { ptr: a as u32, len: b as u32 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe extern "C" fn invoke1_ref<A: RefFromWasmAbi, R: ReturnWasmAbi>(
|
||||
a: usize,
|
||||
b: usize,
|
||||
arg: <A as RefFromWasmAbi>::Abi,
|
||||
) -> <R as ReturnWasmAbi>::Abi {
|
||||
if a == 0 {
|
||||
throw_str("closure invoked recursively or destroyed already");
|
||||
}
|
||||
// Scope all local variables before we call `return_abi` to
|
||||
// ensure they're all destroyed as `return_abi` may throw
|
||||
let ret = {
|
||||
let f: &Fn(&A) -> R = mem::transmute((a, b));
|
||||
let mut _stack = GlobalStack::new();
|
||||
let arg = <A as RefFromWasmAbi>::ref_from_abi(arg, &mut _stack);
|
||||
f(&*arg)
|
||||
};
|
||||
ret.return_abi(&mut GlobalStack::new())
|
||||
}
|
||||
|
||||
impl<'a, A, R> WasmDescribe for Fn(&A) -> R + 'a
|
||||
where A: RefFromWasmAbi,
|
||||
R: ReturnWasmAbi,
|
||||
{
|
||||
fn describe() {
|
||||
inform(FUNCTION);
|
||||
inform(invoke1_ref::<A, R> as u32);
|
||||
inform(1);
|
||||
<&A as WasmDescribe>::describe();
|
||||
<R as WasmDescribe>::describe();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, A, R> IntoWasmAbi for &'a mut (FnMut(&A) -> R + 'b)
|
||||
where A: RefFromWasmAbi,
|
||||
R: ReturnWasmAbi
|
||||
{
|
||||
type Abi = WasmSlice;
|
||||
|
||||
fn into_abi(self, _extra: &mut Stack) -> WasmSlice {
|
||||
unsafe {
|
||||
let (a, b): (usize, usize) = mem::transmute(self);
|
||||
WasmSlice { ptr: a as u32, len: b as u32 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe extern "C" fn invoke1_mut_ref<A: RefFromWasmAbi, R: ReturnWasmAbi>(
|
||||
a: usize,
|
||||
b: usize,
|
||||
arg: <A as RefFromWasmAbi>::Abi,
|
||||
) -> <R as ReturnWasmAbi>::Abi {
|
||||
if a == 0 {
|
||||
throw_str("closure invoked recursively or destroyed already");
|
||||
}
|
||||
// Scope all local variables before we call `return_abi` to
|
||||
// ensure they're all destroyed as `return_abi` may throw
|
||||
let ret = {
|
||||
let f: &mut FnMut(&A) -> R = mem::transmute((a, b));
|
||||
let mut _stack = GlobalStack::new();
|
||||
let arg = <A as RefFromWasmAbi>::ref_from_abi(arg, &mut _stack);
|
||||
f(&*arg)
|
||||
};
|
||||
ret.return_abi(&mut GlobalStack::new())
|
||||
}
|
||||
|
||||
impl<'a, A, R> WasmDescribe for FnMut(&A) -> R + 'a
|
||||
where A: RefFromWasmAbi,
|
||||
R: ReturnWasmAbi
|
||||
{
|
||||
fn describe() {
|
||||
inform(FUNCTION);
|
||||
inform(invoke1_mut_ref::<A, R> as u32);
|
||||
inform(1);
|
||||
<&A as WasmDescribe>::describe();
|
||||
<R as WasmDescribe>::describe();
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ macro_rules! vectors {
|
||||
}
|
||||
|
||||
vectors! {
|
||||
u8 i8 u16 i16 u32 i32 u64 i64 f32 f64
|
||||
u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64
|
||||
}
|
||||
|
||||
if_std! {
|
||||
|
17
src/lib.rs
17
src/lib.rs
@ -260,6 +260,16 @@ impl JsValue {
|
||||
///
|
||||
/// If this JS value is not an instance of a string or if it's not valid
|
||||
/// utf-8 then this returns `None`.
|
||||
///
|
||||
/// # UTF-16 vs UTF-8
|
||||
///
|
||||
/// JavaScript strings in general are encoded as UTF-16, but Rust strings
|
||||
/// are encoded as UTF-8. This can cause the Rust string to look a bit
|
||||
/// different than the JS string sometimes. For more details see the
|
||||
/// [documentation about the `str` type][caveats] which contains a few
|
||||
/// caveats about the encodings.
|
||||
///
|
||||
/// [caveats]: https://rustwasm.github.io/docs/wasm-bindgen/reference/types/str.html
|
||||
#[cfg(feature = "std")]
|
||||
pub fn as_string(&self) -> Option<String> {
|
||||
unsafe {
|
||||
@ -507,6 +517,7 @@ externs! {
|
||||
|
||||
fn __wbindgen_memory() -> u32;
|
||||
fn __wbindgen_module() -> u32;
|
||||
fn __wbindgen_function_table() -> u32;
|
||||
}
|
||||
}
|
||||
|
||||
@ -726,6 +737,12 @@ pub fn memory() -> JsValue {
|
||||
unsafe { JsValue::_new(__wbindgen_memory()) }
|
||||
}
|
||||
|
||||
/// Returns a handle to this wasm instance's `WebAssembly.Table` which is the
|
||||
/// indirect function table used by Rust
|
||||
pub fn function_table() -> JsValue {
|
||||
unsafe { JsValue::_new(__wbindgen_function_table()) }
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod __rt {
|
||||
use core::cell::{Cell, UnsafeCell};
|
||||
|
@ -55,3 +55,9 @@ exports.debug_values = () => ([
|
||||
() => (null),
|
||||
new Set(),
|
||||
]);
|
||||
|
||||
exports.assert_function_table = (x, i) => {
|
||||
const rawWasm = require('wasm-bindgen-test_bg.js');
|
||||
assert.ok(x instanceof WebAssembly.Table);
|
||||
assert.strictEqual(x.get(i), rawWasm.function_table_lookup);
|
||||
};
|
||||
|
@ -9,6 +9,7 @@ extern "C" {
|
||||
fn js_eq_works();
|
||||
fn assert_null(v: JsValue);
|
||||
fn debug_values() -> JsValue;
|
||||
fn assert_function_table(a: JsValue, b: usize);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
@ -171,3 +172,14 @@ fn debug_output() {
|
||||
assert_eq!(format!("{:?}", test.unwrap()), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn function_table_is() {
|
||||
assert_function_table(
|
||||
wasm_bindgen::function_table(),
|
||||
function_table_lookup as usize,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn function_table_lookup() {}
|
||||
|
@ -461,3 +461,21 @@ pub fn option_class_assert_none(x: Option<OptionClass>) {
|
||||
pub fn option_class_assert_some(x: Option<OptionClass>) {
|
||||
assert_eq!(x.unwrap().0, 3);
|
||||
}
|
||||
|
||||
mod works_in_module {
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct WorksInModule(u32);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl WorksInModule {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> WorksInModule {
|
||||
WorksInModule(1)
|
||||
}
|
||||
|
||||
pub fn foo(&self) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,3 +113,9 @@ exports.calling_it_throws = a => {
|
||||
};
|
||||
|
||||
exports.call_val = f => f();
|
||||
|
||||
exports.pass_reference_first_arg_twice = (a, b, c) => {
|
||||
b(a);
|
||||
c(a);
|
||||
a.free();
|
||||
};
|
||||
|
@ -90,6 +90,18 @@ extern "C" {
|
||||
|
||||
#[wasm_bindgen(js_name = calling_it_throws)]
|
||||
fn call_val_throws(f: &JsValue) -> bool;
|
||||
|
||||
fn pass_reference_first_arg_twice(
|
||||
a: RefFirstArgument,
|
||||
b: &Closure<FnMut(&RefFirstArgument)>,
|
||||
c: &Closure<FnMut(&RefFirstArgument)>,
|
||||
);
|
||||
#[wasm_bindgen(js_name = pass_reference_first_arg_twice)]
|
||||
fn pass_reference_first_arg_twice2(
|
||||
a: RefFirstArgument,
|
||||
b: &mut FnMut(&RefFirstArgument),
|
||||
c: &mut FnMut(&RefFirstArgument),
|
||||
);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
@ -439,3 +451,74 @@ fn test_closure_returner() {
|
||||
Ok(o)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RefFirstArgument {
|
||||
contents: u32,
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn reference_as_first_argument_builds_at_all() {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
fn ref_first_arg1(a: &Fn(&JsValue));
|
||||
fn ref_first_arg2(a: &mut FnMut(&JsValue));
|
||||
fn ref_first_arg3(a: &Closure<Fn(&JsValue)>);
|
||||
fn ref_first_arg4(a: &Closure<FnMut(&JsValue)>);
|
||||
fn ref_first_custom1(a: &Fn(&RefFirstArgument));
|
||||
fn ref_first_custom2(a: &mut FnMut(&RefFirstArgument));
|
||||
fn ref_first_custom3(a: &Closure<Fn(&RefFirstArgument)>);
|
||||
fn ref_first_custom4(a: &Closure<FnMut(&RefFirstArgument)>);
|
||||
}
|
||||
|
||||
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<Fn(&JsValue)>);
|
||||
Closure::wrap(Box::new(|_: &JsValue| ()) as Box<FnMut(&JsValue)>);
|
||||
Closure::once(|_: &JsValue| ());
|
||||
Closure::once_into_js(|_: &JsValue| ());
|
||||
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<Fn(&RefFirstArgument)>);
|
||||
Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box<FnMut(&RefFirstArgument)>);
|
||||
Closure::once(|_: &RefFirstArgument| ());
|
||||
Closure::once_into_js(|_: &RefFirstArgument| ());
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn reference_as_first_argument_works() {
|
||||
let a = Rc::new(Cell::new(0));
|
||||
let b = {
|
||||
let a = a.clone();
|
||||
Closure::once(move |x: &RefFirstArgument| {
|
||||
assert_eq!(a.get(), 0);
|
||||
assert_eq!(x.contents, 3);
|
||||
a.set(a.get() + 1);
|
||||
})
|
||||
};
|
||||
let c = {
|
||||
let a = a.clone();
|
||||
Closure::once(move |x: &RefFirstArgument| {
|
||||
assert_eq!(a.get(), 1);
|
||||
assert_eq!(x.contents, 3);
|
||||
a.set(a.get() + 1);
|
||||
})
|
||||
};
|
||||
pass_reference_first_arg_twice(RefFirstArgument { contents: 3 }, &b, &c);
|
||||
assert_eq!(a.get(), 2);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn reference_as_first_argument_works2() {
|
||||
let a = Cell::new(0);
|
||||
pass_reference_first_arg_twice2(
|
||||
RefFirstArgument { contents: 3 },
|
||||
&mut |x: &RefFirstArgument| {
|
||||
assert_eq!(a.get(), 0);
|
||||
assert_eq!(x.contents, 3);
|
||||
a.set(a.get() + 1);
|
||||
},
|
||||
&mut |x: &RefFirstArgument| {
|
||||
assert_eq!(a.get(), 1);
|
||||
assert_eq!(x.contents, 3);
|
||||
a.set(a.get() + 1);
|
||||
},
|
||||
);
|
||||
assert_eq!(a.get(), 2);
|
||||
}
|
||||
|
@ -24,10 +24,12 @@ exports.js_export = () => {
|
||||
i32[0] = 1;
|
||||
i32[1] = 2;
|
||||
assert.deepStrictEqual(wasm.export_i32(i32), i32);
|
||||
assert.deepStrictEqual(wasm.export_isize(i32), i32);
|
||||
const u32 = new Uint32Array(2);
|
||||
u32[0] = 1;
|
||||
u32[1] = 2;
|
||||
assert.deepStrictEqual(wasm.export_u32(u32), u32);
|
||||
assert.deepStrictEqual(wasm.export_usize(u32), u32);
|
||||
|
||||
const f32 = new Float32Array(2);
|
||||
f32[0] = 1;
|
||||
@ -73,6 +75,7 @@ exports.import_js_i32 = a => {
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
};
|
||||
exports.import_js_isize = exports.import_js_i32;
|
||||
|
||||
exports.import_js_u32 = a => {
|
||||
assert.strictEqual(a.length, 2);
|
||||
@ -80,6 +83,7 @@ exports.import_js_u32 = a => {
|
||||
assert.strictEqual(a[1], 2);
|
||||
return a;
|
||||
};
|
||||
exports.import_js_usize = exports.import_js_u32;
|
||||
|
||||
exports.import_js_f32 = a => {
|
||||
assert.strictEqual(a.length, 2);
|
||||
@ -118,10 +122,12 @@ exports.js_import = () => {
|
||||
i32[0] = 1;
|
||||
i32[1] = 2;
|
||||
assert.deepStrictEqual(wasm.import_rust_i32(i32), i32);
|
||||
assert.deepStrictEqual(wasm.import_rust_isize(i32), i32);
|
||||
const u32 = new Uint32Array(2);
|
||||
u32[0] = 1;
|
||||
u32[1] = 2;
|
||||
assert.deepStrictEqual(wasm.import_rust_u32(u32), u32);
|
||||
assert.deepStrictEqual(wasm.import_rust_usize(u32), u32);
|
||||
|
||||
const f32 = new Float32Array(2);
|
||||
f32[0] = 1;
|
||||
@ -140,6 +146,8 @@ exports.js_pass_array = () => {
|
||||
wasm.pass_array_rust_u16([1, 2]);
|
||||
wasm.pass_array_rust_i32([1, 2]);
|
||||
wasm.pass_array_rust_u32([1, 2]);
|
||||
wasm.pass_array_rust_isize([1, 2]);
|
||||
wasm.pass_array_rust_usize([1, 2]);
|
||||
wasm.pass_array_rust_f32([1, 2]);
|
||||
wasm.pass_array_rust_f64([1, 2]);
|
||||
};
|
||||
@ -158,6 +166,8 @@ exports.import_mut_js_i16 = import_mut_foo;
|
||||
exports.import_mut_js_u16 = import_mut_foo;
|
||||
exports.import_mut_js_i32 = import_mut_foo;
|
||||
exports.import_mut_js_u32 = import_mut_foo;
|
||||
exports.import_mut_js_isize = import_mut_foo;
|
||||
exports.import_mut_js_usize = import_mut_foo;
|
||||
exports.import_mut_js_f32 = import_mut_foo;
|
||||
exports.import_mut_js_f64 = import_mut_foo;
|
||||
|
||||
@ -182,6 +192,8 @@ exports.js_export_mut = () => {
|
||||
export_mut_run(new Uint16Array(3), wasm.export_mut_u16);
|
||||
export_mut_run(new Int32Array(3), wasm.export_mut_i32);
|
||||
export_mut_run(new Uint32Array(3), wasm.export_mut_u32);
|
||||
export_mut_run(new Int32Array(3), wasm.export_mut_isize);
|
||||
export_mut_run(new Uint32Array(3), wasm.export_mut_usize);
|
||||
export_mut_run(new Float32Array(3), wasm.export_mut_f32);
|
||||
export_mut_run(new Float64Array(3), wasm.export_mut_f64);
|
||||
};
|
||||
|
@ -40,6 +40,8 @@ export_macro! {
|
||||
(u16, export_u16)
|
||||
(i32, export_i32)
|
||||
(u32, export_u32)
|
||||
(isize, export_isize)
|
||||
(usize, export_usize)
|
||||
(f32, export_f32)
|
||||
(f64, export_f64)
|
||||
}
|
||||
@ -73,6 +75,8 @@ import_macro! {
|
||||
(import_rust_u16, import_js_u16, u16)
|
||||
(import_rust_i32, import_js_i32, i32)
|
||||
(import_rust_u32, import_js_u32, u32)
|
||||
(import_rust_isize, import_js_isize, isize)
|
||||
(import_rust_usize, import_js_usize, usize)
|
||||
(import_rust_f32, import_js_f32, f32)
|
||||
(import_rust_f64, import_js_f64, f64)
|
||||
}
|
||||
@ -100,6 +104,8 @@ pass_array_marco! {
|
||||
(pass_array_rust_u16, u16)
|
||||
(pass_array_rust_i32, i32)
|
||||
(pass_array_rust_u32, u32)
|
||||
(pass_array_rust_isize, isize)
|
||||
(pass_array_rust_usize, usize)
|
||||
(pass_array_rust_f32, f32)
|
||||
(pass_array_rust_f64, f64)
|
||||
}
|
||||
@ -169,6 +175,8 @@ export_mut_macro! {
|
||||
(u16, export_mut_u16)
|
||||
(i32, export_mut_i32)
|
||||
(u32, export_mut_u32)
|
||||
(isize, export_mut_isize)
|
||||
(usize, export_mut_usize)
|
||||
(f32, export_mut_f32)
|
||||
(f64, export_mut_f64)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user