rustwasm / wasm-bindgen Goto Github PK
View Code? Open in Web Editor NEWFacilitating high-level interactions between Wasm modules and JavaScript
Home Page: https://rustwasm.github.io/docs/wasm-bindgen/
License: Apache License 2.0
Facilitating high-level interactions between Wasm modules and JavaScript
Home Page: https://rustwasm.github.io/docs/wasm-bindgen/
License: Apache License 2.0
wasm_bindgen! {
pub fn parse_data(data: &[u8]) -> i32 {
data.len() as i32
}
}
Returns
unsupported reference type
I'm hoping that you'd be open to more borrowed types (specifically &[u8]
) in addition to BorrowedStr. This could be part of a larger issue to support Vec and other slices, but I figure &[u8]
might be easiest and would be implemented very closely to BorrowedStr.
Use case:
After I use a FileReader to read a binary file into an ArrayBuffer and create WebAssembly.Memory (I believe that flow is correct), I want to send the data to rust for parsing.
Hi @alexcrichton! It's quite exciting to be writing someone who is so prolific in the Rust community.
Thank you so much for wasm-bindgen
and thank you for your time.
Laying out my issue:
Host: nightly-x86_64-pc-windows-gnu
Version: rustc 1.26.0-nightly
Attempting to compile this library with cargo build --release --target wasm32-unknown-unknown
.
Receiving long error output all having to do with undeclared modules:
sys::try_lock_exclusive(self)
| ^^^ Use of undeclared type or module `sys`
error[E0433]: failed to resolve. Use of undeclared type or module `MmapInner`
--> C:\Users\guilf\.cargo\registry\src\github.com-1ecc6299db9ec823\memmap-0.5.2\src\lib.rs:130:9
|
130 | MmapInner::open(&file, prot, 0, len as usize).map(|inner| Mmap { inner: inner })
| ^^^^^^^^^ Use of undeclared type or module `MmapInner`
error[E0433]
Looking at memmap v0.5.2, I see the MmapInner
module declared here if Windows target family and also on line 12 if Linux target family condition is met.
Is this occurring because wasm32-unknown-unknown
is neither Windows nor Linux target family?
Things go wrong if the CLI and Cargo.toml versions don't match, so the CLI should check and complain loudly if there is a mismatch.
Currently you can't pass ownership of a rust struct from rust to JS through an import, like this:
#[wasm_bindgen]
struct Foo();
#[wasm_bindgen]
extern {
fn take_struct(foo: Foo);
}
but you can return it from an exported function:
#[wasm_bindgen]
fn create_foo() -> Foo {
Foo()
}
Is this a conscious style choice or is passing in structs by value just not implemented yet?
In both cases js takes ownership of the object and becomes responsible for freeing it if it's dropped. But I can see that being clearer when the object is a return from a rust export, than when receiving an object as an argument from rust.
rustc 1.25.0-nightly (4d2d3fc5d 2018-02-13) and
rustc 1.25.0-nightly (3ec5a99aa 2018-02-14)
command:
$ wasm-bindgen target/wasm32-unknown-unknown/release/bullet_wasm.wasm --out-dir .
custom: '\u{b2796}'
traceback:
11: <std::collections::hash::map::HashMap<K, V, S> as core::ops::index::Index<&'a Q>>::index
at /checkout/src/libstd/collections/hash/map.rs:1394
12: wasm_bindgen_cli_support::js::SubContext::generate_function
at crates/wasm-bindgen-cli-support/src/js.rs:840
13: wasm_bindgen_cli_support::js::SubContext::generate_export_for_class
at crates/wasm-bindgen-cli-support/src/js.rs:669
14: wasm_bindgen_cli_support::js::SubContext::generate_export
at crates/wasm-bindgen-cli-support/src/js.rs:653
15: wasm_bindgen_cli_support::js::SubContext::generate
at crates/wasm-bindgen-cli-support/src/js.rs:644
16: wasm_bindgen_cli_support::Bindgen::_generate
at crates/wasm-bindgen-cli-support/src/lib.rs:90
17: wasm_bindgen_cli_support::Bindgen::generate
at /home/sebk/Rust/wasm-bindgen/crates/wasm-bindgen-cli-support/src/lib.rs:58
18: wasm_bindgen::main
at crates/wasm-bindgen-cli/src/bin/wasm-bindgen.rs:51
source code:
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Context {}
#[wasm_bindgen]
impl Context {
pub fn parse(&self, expr: &str) -> Expr {
panic!()
}
pub fn eval(&self, expr: &Expr) -> f64 {
panic!()
}
pub fn set(&mut self, var: &str, val: f64) {
panic!()
}
}
#[wasm_bindgen]
pub struct Expr {}
#[wasm_bindgen]
#[no_mangle]
pub extern fn context() -> Context {
panic!()
}
Right now you can't write a function like:
#[wasm_bindgen]
#[no_mangle]
pub extern fn foo(a: &JsValue) -> &JsValue {
a
}
This is because JsValue
goes through all the same machinery as Foo
, but I think we want to add a specific trait for "can be returned as a reference" or maybe even just AsRef<JsValue>
as I think that's the only way this can work?
Enabling this would help avoid an unnecessary Clone
otherwise to extract data from wasm back into JS.
It would be neat if the developer could put a bindgen annotation on function imports that said "import the JS function found at "x.y.z" (i.e., a sequence of JS property accesses, explicitly starting at the JS global object). This could allow a dev to import, e.g. console.log
directly. Without this support, I think one would have to write a dummy ES Module that exports a function that calls console.log
. With this support, one could write a whole DOM-accessing app entirely in Rust.
the wasm part seems redundant. was just curious why it's named this way ;)
Heya! I just tried to run the hello_world example on my machine (rustc 1.26.0-nightly (9cb18a92a 2018-03-02), wasm-bindgen master today 98b9bee, Mac Chrome) and it throws the error:
RangeError: WebAssembly.Instance is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.instantiate.
which appears to directly result from the generated import * as wasm from './hello_world_wasm';
line. I found webpack/webpack#6475 implying this is a browser limitation of sync wasm instantiation and https://github.com/alexcrichton/wasm-bindgen/issues/39 where you briefly discuss this issue, but from your comments it sounds like async import causes this error, not the sync import which is what I'm seeing.
Any chance you can point me in the right direction? Not sure if it's user error. :)
When using wasm2es6js
or even looking at the generated raw wasm file, the generated module refers to a module called "env"
. This module I assume should resolve to the main .js
file generated by wasm-bindgen
since it expects it to contain __wbindgen_throw
according to the import table of the .wasm
file.
However it also expects the __web_on_grow
function which is not defined.
I'm attempting to integrate this tool with webpack. How should I map this "env"
module?
On js side, document
or rather window.document
provides the reference to the document
object contained in the current window. Is there any way I can access that document using wasm_bindgen? Or do I need to write a js file exposes the required functionality of the document API?
Supporting the full power of Rust enums is probably a lot of work, but C-Style enums seem more doable. Is this something worth while tackling? If so, I would volunteer to help out (although I might need a bit of coaching).
For example, I have this js module test.js
.
export function test(a) {
return a || 1
}
Now in js, I can call this function with or without an argument. Can I mimic the same thing on rust side with something like this?
#[wasm_bindgen(module = "./test")]
extern {
fn test(i: i32) -> i32;
#[wasm_bindgen(...some attr indicating its the same function on JS side)]
fn test_without_arg() -> i32;
}
Since webpack 4.0 beta released we can implicitly import wasm files.
ร try_gluon\src\client\gluon_wasm_wasm.js:2:38: Cannot resolve dependency 'env'
1 |
> 2 | import * as import_b from 'env';import * as import_c from './gluon_wasm';
After going through the steps in the README I am currently stuck at the above error. Apparently the code generated from wasm2es6js
expects an env
module but I don't get where that is supposed to come from?
Returning a JsValue
works and returning Vec
or String
works, but returning a Vec<JsValue>
does not, failing with: the trait wasm_bindgen::convert::WasmBoundary is not implemented for std::vec::Vec<wasm_bindgen::JsValue>
. I don't see a reason why returning a Vec<JsValue>
shouldn't work.
I would also be interested in implementing this, but I'm getting lost in the code generation.
I stepped on this while trying to add some webassembly to a Visual Studio Code extension.
Right now output.js
and output_wasm.js
both import each other and this doesn't work in VS Code because import_b
is empty when WebAssembly.instantiate
is called:
While the same file imported in the main module has everything in place:
Everything started working like a charm after I manually moved stuff required by wasm
into a separate file and imported it from both files.
You can see the example extension in https://github.com/gentoo90/vs-wasm
Uncomment line 24 in tasks.json and relaunch to see the error.
Emitting something like:
class Whatever {
...
async with(whateverInstance, f) {
try {
return await f(whateverInstance);
} finally {
whateverInstance.free();
}
}
}
Would ideally control with some kind of #[wasm_bindgen(...)]
attribute. Should be able to control whether async
or not or both versions.
Currently, the binding code is built as .ts (TypeScript). For non-ts enabled environments (Gecko) it would be nice to be able to get .js file there.
Right now there's no way to set a property on an imported JS object, and this should be added!
Current thinking of how to do this:
#[wasm_bindgen]
extern {
type Foo;
#[wasm_bindgen(getter)] // field inferred via method name, could also be explicit here
fn foo(this: &Foo) -> u32; // required to have only one `this` argument
#[wasm_bindgen(setter)]
fn set_foo(this: &Foo, val: u32); // no return type allowed
}
generating JS that looks like:
const foo_get = Object.getOwnPropertyDescriptor(Foo.prototype, 'foo').get;
export function foo_get_shim(idx) {
return foo_get.call(getObject(idx));
}
const foo_set = Object.getOwnPropertyDescriptor(Foo.prototype, 'foo').set;
export function foo_set_shim(idx, val) {
return foo_set.call(getObject(idx), val);
}
I'm not really sure how to model this in Rust's syntax well, but something like this is always an option
#[wasm_bindgen]
extern {
#[wasm_bindgen(properties(foo: u32, bar: String))]
type Foo;
#[wasm_bindgen(properties(foo(getter): String))] // no setter? .. needs better syntax
type Bar;
}
I am trying to reduce allocation overhead and avoid the use of Vec
, which leads me to a C-style interface like this
#[wasm-bindgen]
pub fn expensive_work(input: &[u8], output: &mut [u8]) {
// do expensive work
}
now currently this throws when trying to compile with a missmatched types error.
Would it be possible to support something like this?
This may be purely a case of naรฏvetรฉ on my part, I came across the Mozilla article that referenced your library and thought it would be a fun project to set up a rust-wasm bridge to this rust unrar
package โ that itself is a bridge to the C unrar โ and compare it in performance to a similar project created with emscripten. It's been years since I've touched a system-level language and have equally little knowledge about wasm
, but at the very least I can determine that the source of my headache is purely from including the unrar
library when compiling to wasm32-unknown-unknown
. The attached is the full output that I received when attempting to compile to that target with the following setup.
// src/lib.rs
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
# Cargo.toml
[package]
name = "wasm_test"
version = "0.1.0"
authors = ["Ben Teichman <[email protected]>"]
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.1"
unrar = "0.4.3"
This was the output I received when running it:
It seems that stdweb aims to do a lot of the same things wasm-bindgen does (and some more). How is this crate positioned against stdweb? Is it a strict competitor (i.e. more choice, the better) or does it aim to be something different?
@alexcrichton thanks for this tool, it looks amazing. I was trying to get it running from master and I am running into an unsafe call error. I tried wrapping the module in unsafe
but that didn't seem to work.
code
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
wasm_bindgen! {
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
}
error[E0133]: call to unsafe function requires unsafe function or block
--> /Users/charlesking/.cargo/git/checkouts/wasm-bindgen-aa905f4284ca7fbe/322f520/src/lib.rs:341:13
|
341 | self.value.into_inner()
| ^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
error: aborting due to previous error
error: Could not compile `wasm-bindgen`.
Seems to be related to changes made here - alexcrichton@c51a342. If I specify an earlier revision, it compiles without error.
Right now when you want to export a function to JS it looks like:
#[wasm_bindgen]
#[no_mangle]
pub extern fn foo() {
// ...
}
but should the #[no_mangle]
and extern
be required? The original thinking was that one day the #[wasm_bindgen]
attribute could be removed and this'd just reflect what rustc does under the hood already, but I'm getting less and less certain that'll be the case (aka custom types and &str
probably "won't ever work" in terms of being the right ABI).
It'd certainly be a little easier on the eyes to remove those two components!
Currently, the CLI-generated TS bindings export a single entry point, instantiate
. This internally calls WebAssembly.instantiate and then processes the returned WebAssembly.ResultObject
like
function xform(obj: WebAssembly.ResultObject): Exports {
let { module, instance } = obj;
// etc.
}
This is a great general starting point, but it has a couple limitations:
WebAssembly.Module
to instantiate
, since the overload of WebAssembly.instantiate
that takes a WebAssembly.Module
doesn't return a WebAssembly.ResultObject
but instead just a WebAssembly.Instance
. So the destructuring above will set both module
and instance
to undefined
.Would you support adding a lower-level JS API for these use cases? I'm imagining a pair of functions something like getImports(_imports : Imports)
and initWithInstance(instance : WebAssembly.Instance)
. It'd be up to consuming code to call WebAssembly.instantiate(Streaming)
, like
import { MyStruct, getImports, initWithInstance } from './cli-generated-bindings.ts';
WebAssembly.instantiateStreaming(fetch('my-wasm.wasm'), getImports({}))
.then(({ instance }) => initiWithInstance(instance))
.then(wasm => {
const myStruct = MyStruct.new();
wasm.my_rust_fn(myStruct);
// etc...
});
This would also support things like fetching and compiling the WASM once via WebAssembly.compile or WebAssembly.compileStreaming and then passing the compiled WebAssembly.Module
to multiple worker threads, each of which constructs its own WebAssembly.Instance
using the cli-generated bindings.
Hi.
I have a question.
I want to call a wasm(Rust) function, that uses a JS async function, from JS.
The wasm function should return a Promise because the function uses an async function.
So there seems be two challenges.
Is it possible by wasm-bindgen?
And if possible, I can use a syntax like futures-await in that case?
(Since I have relatively large amount of synchrous codes, I will be happy if I can use the syntax.)
Thanks!
When a struct is passed by value (i.e., moved) into a function that is being called by JS the generated JS code nulls out the pointer to that struct in the wrapping ES6 class. This makes total sense - the struct has been moved so the previous ref to it is now invalidated, but the error at run time is simply: Error: null pointer passed to rust
.
Would it make debugging easier if the class kept track of if it has been invalidated due to a move and throws a more descriptive error?
#[no_mangle]
#[wasm_bindgen]
pub extern fn optional() -> Option<i32> {
None
}
Ideally this would be returned as null
on the JS side
the trait `wasm_bindgen::convert::WasmBoundary` is not implemented for `std::option::Option<i32>`
(this seems like lower hanging fruit than Result
)
The good news is that I'm getting my head around WebAssembly so I may be able to help in the future ๐ค
Edit: Oof, maybe it's best to tackle the general generics problem before specializing for the Option
use case.
The #[wasm_bindgen]
attribute is pretty feature-ful right now and notably allows importing a class from JS and using it in Rust. Unfortunately though it's a pretty manual process to write this out for web apis, so it'd be great to do this automatically!
Thankfully there's this awesome thing called WebIDL which is a programmatic description of APIs available on the web. There's even two parsers on crates.io for WebIDL!
I think it'd be pretty neat if a WebIDL generator were added to this repo to automatically generate #[wasm_bindgen]
decorated bindings. In that sense I'd imagine that we could auto-generate a bunch of *-sys
crates which provide bindings for all the web-related functionality JS has to offer. At that point working with the DOM or other web APIs should be as simple as extern crate foo
!
An issue like this certainly has a lot of design questions to explore as I'm sure WebIDL is far richer than what #[wasm_bindgen]
supports today. We'll need to add features to #[wasm_bindgen]
along the way as well as probably developing idioms to map JS to Rust, but I think it'd be great to at least start out with some simple APIs to see how it goes.
For example the README has an example:
#[wasm_bindgen]
extern {
fn alert(s: &str);
}
but it'd be awesome if we could automatically generate this binding from a WebIDL file and place it in a crate to use. Once we have the "hello world" variants working we should hopefully have enough information to inform the next phase of design questions.
i may just not be fully understanding but i am curious as to why i need to add wasm-bindgen as a dep of my project as well as run cargo install
for it.
It could be nice to have an option where the generated JS does not depend on webpack. The primary issue is the import statement of the wasm file I think? Since this project implicitly targets browsers that support wasm, this mostly overlaps also with browsers that support native modules.
This is my first experience using Rust so I may be missing an obvious setup step.
I'm following along with the README and I get an error when I run the cargo build
command:
cargo build --release --target wasm32-unknown-unknown
Updating registry `https://github.com/rust-lang/crates.io-index`
Compiling itoa v0.3.4
Compiling dtoa v0.4.2
Compiling num-traits v0.2.1
Compiling fnv v1.0.6
Compiling wasm-bindgen-shared v0.1.1
Compiling serde v1.0.29
Compiling unicode-xid v0.1.0
Compiling proc-macro2 v0.2.3
Compiling quote v0.4.2
Compiling syn v0.12.14
Compiling serde_json v1.0.10
Compiling serde_derive_internals v0.20.0
Compiling serde_derive v1.0.29
Compiling wasm-bindgen-macro v0.1.1
Compiling wasm-bindgen v0.1.0
error[E0463]: can't find crate for `std`
|
= note: the `wasm32-unknown-unknown` target may not be installed
error: aborting due to previous error
If you want more information on this error, try using "rustc --explain E0463"
error: Could not compile `wasm-bindgen`.
To learn more, run the command again with --verbose.
This is the result of running rustup show
:
rustup show
Default host: x86_64-apple-darwin
installed toolchains
--------------------
stable-x86_64-apple-darwin
nightly-x86_64-apple-darwin (default)
installed targets for active toolchain
--------------------------------------
wasm32-unknown-emscripten
wasm32-unknown-unknown
x86_64-apple-darwin
active toolchain
----------------
nightly-x86_64-apple-darwin (default)
rustc 1.26.0-nightly (2789b067d 2018-03-06)
I'd be happy to provide additional debugging information if needed.
the final step for running wasm-bindgen is:
wasm-bindgen target/wasm32-unknown-unknown/release/<name of lib>.wasm \ --out-dir .
it would be easier to use this tool to automate if it automagically knew to look in that directory for a wasm file named with the same name as the crate.
i'm sure i don't know all the details but would that be possible?
I tried following the example, but I ran into this error:
cargo +nightly build --release --target wasm32-unknown-unknown
Updating git repository `https://github.com/alexcrichton/wasm-bindgen`
Updating registry `https://github.com/rust-lang/crates.io-index`
Updating git repository `https://github.com/dtolnay/quote`
Updating git repository `https://github.com/dtolnay/syn`
error: no matching package named `synom` found (required by `wasm-bindgen-macro`)
location searched: https://github.com/dtolnay/syn
version required: *
Seems like it was renamed or moved?
For example:
#[wasm_bindgen]
extern {
#[wasm_bindgen(static = WebAssembly.Module)]
type WebAssembly;
// ...
}
Of course this does not work for some types..
This might belong in another repo.
In order to just get .d.ts types for a rust file compiled to wasm, should I use this project or is there something more suitable?
Also, in my case, all <projectname>.js
does is reexport functions already exported in <projectname>_wasm.js
, and <projectname>.d.ts
is provided for that, meaining it doesn't export for example the memory
or even the booted
promise (how can I know when I can start using the module, do I need to import both, one for the promise the other for booted actions?)
I am looking for something that, based on a rust file, produces the definition of a custom ResultObject
where instance.exports
is statically typed.
Maybe the return of WebAssembly.Module.exports()
, but that's less significant.
You are calling this function located in index.js
from Rust:
export function bar_on_reset(s, token) {
console.log(token);
console.log(`this instance of bar was reset to ${s}`);
}
which would mean that the generated js module would have to import index.js
?
Currently something like:
#[wasm_bindgen]
extern {
type Node;
#[wasm_bindgen(method)]
fn contains(this: &Node, other: u32);
}
will generate a shim in js like:
export function shim(idx, other) {
return Node.prototype.contains.call(getObject(idx), other);
}
Instead, though, we should generate a shim like:
const __shim_function = Node.prototype.contains;
export function shim(idx, other) {
return __shim_function.call(getObject(idx), other);
}
and that way the JS engine will hopefully have fewer guards/property lookups to go through! (plus this more closely mirrors what wasm will eventually do natively)
This test should pass, but right now there aren't any default
bindings emitted for Tricycle
:
extern crate test_support;
#[test]
fn default() {
test_support::project()
.file("src/lib.rs", r#"
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
#[derive(Default)]
pub struct Tricycle {
uno: f64,
dos: f64,
tres: f64,
}
#[wasm_bindgen]
impl Tricycle {
pub fn uno(&self) -> f64 { self.uno }
pub fn dos(&self) -> f64 { self.dos }
pub fn tres(&self) -> f64 { self.tres }
}
"#)
.file("test.ts", r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
let tricycle = wasm.Tricycle.default();
assert.strictEqual(tricycle.uno(), 0);
assert.strictEqual(tricycle.dos(), 0);
assert.strictEqual(tricycle.tres(), 0);
}
"#)
.test();
}
I have a simple Rust program (compiled as wasm) that is attempting to interface with JS:
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct MyStruct {
my_property: usize
}
#[wasm_bindgen]
#[no_mangle]
pub extern fn my_function() -> MyStruct {
MyStruct { my_property: 1 }
}
I then run the following:
cargo build --release --target wasm32-unknown-unknown
wasm-bindgen target/wasm32-unknown-unknown/release/wasm_test.wasm --out-dir dist
And I get the following error:
thread 'main' panicked at 'no entry found for key', libcore/option.rs:917:5
This happens when the wasm-bindgen-cli tool is running.
I poked around and found that the panic comes from here after being called here. It seems that the custom_type_names
hash table is not populated. I then found the JSON that is being stored in the .wasm
file:
{"exports":[{"class":null,"method":false,"function":{"name":"my_function","arguments":[],"ret":"๒ท"}}],"imports":[],"custom_type_names":[]}
.
Two things that don't make sense to me:
"ret"
is actually \u{b77d2}
.custom_type_names
array is empty, but I'm guessing that should somehow reference the MyStruct
struct.I attempted to dive into the code-gen aspect of bindgen but I got lost. Any ideas?
Not sure what's up with this, but the options don't get printed:
$ wasm-bindgen --help
Invalid arguments.
Usage:
wasm-bindgen [options] <input>
$ wasm-bindgen
Invalid arguments.
Usage:
wasm-bindgen [options] <input>
There should be a section like this:
Options:
-h --help Show this screen.
--output-ts FILE Output TypeScript file
--output-wasm FILE Output WASM file
--nodejs Generate output for node.js, not the browser
--debug Include otherwise-extraneous debug checks in output
... but this section doesn't actually show up.
The general idea behind this tool is that source languages will encode data into a custom section of the wasm binary which the wasm-bindgen
tool will decode and remove, using it to generate appropriate JS bindings.
Currently, however, this isn't what happens! Instead we shove data into a static
as rustc doesn't expose a way to emit data into a custom section as-is. Additionally the static
is just a totally random encoding that I got working, it's not principled at all. We should fix that!
I think it's relatively uncontroversial to use a custom section to communicate this information, and we'll continue to work around rustc's lack of ability to emit a custom section in the meantime and will otherwise take advantage of the ability to do this in rustc as soon as it becomes available! In the meantime, though, I think it may be useful to discuss the custom format as well.
Right now the wasm-bindgen-cli-shared
crate shows off effectively what's encoded right now, the top-level entry being a Program
and a wasm binary has multiple Program
instances. That is, however, only what the bindgen tool currently uses and will likely change over time both in requirements and breadth. In that sense, does it makes sense to lock down a binary format just yet? Or maybe we can lock down an extensible format like JSON which you can easily add keys to over time?
One thing I definitely want to do in the near term is to version the wasm-bindgen information in the sense that if the CLI installed at a particular git rev finds information produced by a different git rev then it should immediately generate an error saying they're out of sync (as it's so unstable). Eventually this'll probably get removed and we'll want to have the producer and consumer versioned separately, but that may be awhile!
In any case, this is all just some off-the-cuff thinking, I'd love to hear others' thoughts on this too!
ERROR in ./src/main.rs
Module build failed: Error: Command failed: wasm2es6js target\wasm32-unknown-unknown\release\garuda-wasm-mdns_wasm.wasm -o target\wasm32-unknown-unknown\release\garuda-wasm-mdns_wasm.js --base64
thread 'main' panicked at 'failed to open input: Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }', libcore\result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
The wasm2es6js command is looking for garuda-wasm-mdns_wasm.wasm
which is non-existent. The file that does exist is garuda-wasm-mdns.wasm
. Somewhere there must be a descrepency between naming the release file and what wasm2es6js is looking for.
rustc 1.26.0-nightly (2789b067d 2018-03-06)
wasm-bindgen 0.1.1
Webpack config
rules: [
{
test: /\.rs$/,
use: [{
loader: 'wasm-loader',
}, {
loader: 'rust-native-wasm-loader',
options: {
release: true,
gc: true,
wasmBindgen: true,
wasm2es6js: true,
},
}],
}
],
If we wanted to pass a temporary reference to a struct defined in Rust to a js function, this should work.
The user defines Foo
like so:
#[wasm_bindgen]
pub struct Foo {
internal: i32,
}
#[wasm_bindgen]
impl Foo {
pub fn new(val: i32) -> Foo {
Foo { internal: val }
}
pub fn get(&self) -> i32 {
self.internal
}
pub fn set(&mut self, val: i32) {
self.internal = val;
}
}
And a js function that takes a &Foo
:
function bar(/*FooRef*/f)
{
console.log("Foo.get(): ", f.get());
}
Generated/hidden Rust:
#[wasm_bindgen(module = "./index")]
extern {
fn bar_js(ptr_to_foo: *const Foo);
}
fn bar(f: &Foo){
bar_js(f as *const Foo)
}
#[wasm_bindgen]
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn Foo_get(ptr_to_foo: *const Foo) -> i32 {
let f = unsafe{ptr_to_foo.as_ref()}.unwrap();
f.get()
}
#[wasm_bindgen]
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn Foo_set(ptr_to_foo: *mut Foo, val: i32) {
let f = unsafe{ptr_to_foo.as_mut()}.unwrap();
f.set(val);
}
Generated js:
export function bar_js(ptr_to_foo)
{
const f = new FooRef(ptr_to_foo);
bar(f);
f._ptr = 0;
}
class FooRef {
constructor(ptr){
this._ptr = ptr;
}
get(){
// call `get` on `Foo` referenced by `this`
return Foo_get(this._ptr);
}
}
class FooMutRef extends FooRef{
constructor(ptr){
super(ptr);
}
set(val){
// call `set` on `Foo` referenced by `this`
Foo_set(this._ptr, val);
}
}
(Instead of invalidating the this._ptr
immediately, we could wait for Foo
to drop. I don't know where this would be useful though.)
Example usage in Rust:
let f = Foo::new(42);
bar(&f); // call to js
Would there be any theoretical problems with this?
Why do we need wasm2es6js
here?
Couldn't we just as well use the fetch
function and instantiate a WebAssembly
with the response?
Would be good for JS programmers reading the generated JS to have documentation on
I mentioned here WebAssembly/design#1172 that we will be able to use the BigInt
proposal to represent the i64 values from WebAssembly.
Currently there is not support for BigInt in browsers (nor in Babel). So I believe we can use this kind of tools to allow it.
We use a 64 bit two's-complement (https://github.com/dcodeIO/long.js).
Have you considered to implement it?
Edit:
I just remembered that WebAssembly doesn't allow multiple results for a func, I'm not sure what's the best solution, maybe the linear memory?
When I said "we use" I meant in https://github.com/xtuc/webassemblyjs which is not the same use-case.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.