2018-07-19 14:57:04 -05:00
|
|
|
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-cli-support/0.2")]
|
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
extern crate parity_wasm;
|
|
|
|
extern crate wasm_bindgen_shared as shared;
|
2018-04-25 07:26:33 -07:00
|
|
|
#[macro_use]
|
|
|
|
extern crate serde_derive;
|
2017-12-14 19:31:01 -08:00
|
|
|
extern crate serde_json;
|
2018-02-06 08:58:15 -08:00
|
|
|
extern crate wasm_gc;
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
extern crate wasmi;
|
2018-04-25 11:42:22 -07:00
|
|
|
#[macro_use]
|
|
|
|
extern crate failure;
|
2017-12-14 19:31:01 -08:00
|
|
|
|
2018-07-25 15:49:50 -07:00
|
|
|
use std::any::Any;
|
2018-03-29 01:47:44 -07:00
|
|
|
use std::collections::BTreeSet;
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
use std::fmt;
|
2018-07-25 16:06:47 -07:00
|
|
|
use std::fs;
|
2018-07-25 15:49:50 -07:00
|
|
|
use std::mem;
|
2017-12-24 15:32:40 -08:00
|
|
|
use std::path::{Path, PathBuf};
|
2017-12-14 19:31:01 -08:00
|
|
|
|
2018-04-25 11:42:22 -07:00
|
|
|
use failure::{Error, ResultExt};
|
2017-12-14 19:31:01 -08:00
|
|
|
use parity_wasm::elements::*;
|
|
|
|
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
mod descriptor;
|
2018-06-27 22:42:34 -07:00
|
|
|
mod js;
|
2018-01-29 21:20:38 -08:00
|
|
|
pub mod wasm2es6js;
|
2017-12-18 12:39:14 -08:00
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
pub struct Bindgen {
|
2018-07-25 15:49:50 -07:00
|
|
|
input: Input,
|
2017-12-14 21:55:21 -08:00
|
|
|
nodejs: bool,
|
2018-07-04 22:37:09 -05:00
|
|
|
nodejs_experimental_modules: bool,
|
2018-03-28 07:37:56 -07:00
|
|
|
browser: bool,
|
2018-04-11 13:59:58 +05:45
|
|
|
no_modules: bool,
|
2018-04-19 13:33:58 -07:00
|
|
|
no_modules_global: Option<String>,
|
2017-12-19 09:25:41 -08:00
|
|
|
debug: bool,
|
2018-01-29 21:20:38 -08:00
|
|
|
typescript: bool,
|
2018-04-11 11:43:18 -07:00
|
|
|
demangle: bool,
|
2018-07-13 08:10:51 -07:00
|
|
|
keep_debug: bool,
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2018-07-25 15:49:50 -07:00
|
|
|
enum Input {
|
|
|
|
Path(PathBuf),
|
|
|
|
Bytes(Vec<u8>, String),
|
|
|
|
Module(Module, String),
|
|
|
|
None,
|
|
|
|
}
|
|
|
|
|
2017-12-14 19:31:01 -08:00
|
|
|
impl Bindgen {
|
|
|
|
pub fn new() -> Bindgen {
|
|
|
|
Bindgen {
|
2018-07-25 15:49:50 -07:00
|
|
|
input: Input::None,
|
2017-12-14 21:55:21 -08:00
|
|
|
nodejs: false,
|
2018-07-04 22:37:09 -05:00
|
|
|
nodejs_experimental_modules: false,
|
2018-03-28 07:37:56 -07:00
|
|
|
browser: false,
|
2018-04-11 13:59:58 +05:45
|
|
|
no_modules: false,
|
2018-04-19 13:33:58 -07:00
|
|
|
no_modules_global: None,
|
2017-12-19 09:25:41 -08:00
|
|
|
debug: false,
|
2018-01-29 21:20:38 -08:00
|
|
|
typescript: false,
|
2018-04-11 11:43:18 -07:00
|
|
|
demangle: true,
|
2018-07-13 08:10:51 -07:00
|
|
|
keep_debug: false,
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn input_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Bindgen {
|
2018-07-25 15:49:50 -07:00
|
|
|
self.input = Input::Path(path.as_ref().to_path_buf());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Explicitly specify the already parsed input module.
|
|
|
|
///
|
|
|
|
/// Note that this API is a little wonky to avoid tying itself with a public
|
|
|
|
/// dependency on the `parity-wasm` crate, what we currently use to parse
|
|
|
|
/// wasm mdoules.
|
|
|
|
///
|
|
|
|
/// If the `module` argument is a `parity_wasm::Module` then it will be used
|
|
|
|
/// directly. Otherwise it will be passed to `into_bytes` to serialize the
|
|
|
|
/// module to a vector of bytes, and this will deserialize the module later.
|
|
|
|
///
|
|
|
|
/// Note that even if the argument passed in is a `parity_wasm::Module` it
|
|
|
|
/// doesn't mean that this won't invoke `into_bytes`, if the `parity_wasm`
|
|
|
|
/// crate versions are different we'll have to go through serialization.
|
|
|
|
pub fn input_module<T: Any>(
|
|
|
|
&mut self,
|
|
|
|
name: &str,
|
|
|
|
mut module: T,
|
|
|
|
into_bytes: impl FnOnce(T) -> Vec<u8>,
|
|
|
|
) -> &mut Bindgen {
|
|
|
|
let name = name.to_string();
|
|
|
|
if let Some(module) = (&mut module as &mut Any).downcast_mut::<Module>() {
|
|
|
|
let blank = Module::new(Vec::new());
|
|
|
|
self.input = Input::Module(mem::replace(module, blank), name);
|
|
|
|
return self
|
|
|
|
}
|
|
|
|
|
|
|
|
self.input = Input::Bytes(into_bytes(module), name);
|
2017-12-14 19:31:01 -08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-12-14 21:55:21 -08:00
|
|
|
pub fn nodejs(&mut self, node: bool) -> &mut Bindgen {
|
|
|
|
self.nodejs = node;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-07-04 22:37:09 -05:00
|
|
|
pub fn nodejs_experimental_modules(&mut self, node: bool) -> &mut Bindgen {
|
|
|
|
self.nodejs_experimental_modules = node;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-03-28 07:37:56 -07:00
|
|
|
pub fn browser(&mut self, browser: bool) -> &mut Bindgen {
|
|
|
|
self.browser = browser;
|
2018-03-07 08:50:56 -08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-04-11 13:59:58 +05:45
|
|
|
pub fn no_modules(&mut self, no_modules: bool) -> &mut Bindgen {
|
|
|
|
self.no_modules = no_modules;
|
2018-04-04 20:06:53 +05:45
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-04-19 13:33:58 -07:00
|
|
|
pub fn no_modules_global(&mut self, name: &str) -> &mut Bindgen {
|
|
|
|
self.no_modules_global = Some(name.to_string());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2017-12-19 09:25:41 -08:00
|
|
|
pub fn debug(&mut self, debug: bool) -> &mut Bindgen {
|
|
|
|
self.debug = debug;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-01-29 21:20:38 -08:00
|
|
|
pub fn typescript(&mut self, typescript: bool) -> &mut Bindgen {
|
|
|
|
self.typescript = typescript;
|
2017-12-24 15:32:40 -08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-04-11 11:43:18 -07:00
|
|
|
pub fn demangle(&mut self, demangle: bool) -> &mut Bindgen {
|
|
|
|
self.demangle = demangle;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-07-13 08:10:51 -07:00
|
|
|
pub fn keep_debug(&mut self, keep_debug: bool) -> &mut Bindgen {
|
|
|
|
self.keep_debug = keep_debug;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-01-29 21:20:38 -08:00
|
|
|
pub fn generate<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error> {
|
|
|
|
self._generate(path.as_ref())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn _generate(&mut self, out_dir: &Path) -> Result<(), Error> {
|
2018-07-25 15:49:50 -07:00
|
|
|
let (mut module, stem) = match self.input {
|
|
|
|
Input::None => bail!("must have an input by now"),
|
|
|
|
Input::Module(ref mut m, ref name) => {
|
|
|
|
let blank_module = Module::new(Vec::new());
|
|
|
|
(mem::replace(m, blank_module), &name[..])
|
|
|
|
}
|
|
|
|
Input::Bytes(ref b, ref name) => {
|
|
|
|
let module = parity_wasm::deserialize_buffer::<Module>(&b)
|
|
|
|
.context("failed to parse input file as wasm")?;
|
|
|
|
(module, &name[..])
|
|
|
|
}
|
|
|
|
Input::Path(ref path) => {
|
2018-07-25 16:06:47 -07:00
|
|
|
let contents = fs::read(&path)
|
2018-07-25 15:49:50 -07:00
|
|
|
.with_context(|_| format!("failed to read `{}`", path.display()))?;
|
|
|
|
let module = parity_wasm::deserialize_buffer::<Module>(&contents)
|
|
|
|
.context("failed to parse input file as wasm")?;
|
|
|
|
let stem = path.file_stem().unwrap().to_str().unwrap();
|
|
|
|
(module, stem)
|
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
};
|
2018-04-25 11:42:22 -07:00
|
|
|
let programs = extract_programs(&mut module)
|
|
|
|
.with_context(|_| "failed to extract wasm-bindgen custom sections")?;
|
2018-02-06 15:52:44 -08:00
|
|
|
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
// Here we're actually instantiating the module we've parsed above for
|
|
|
|
// execution. Why, you might be asking, are we executing wasm code? A
|
|
|
|
// good question!
|
|
|
|
//
|
|
|
|
// Transmitting information from `#[wasm_bindgen]` here to the CLI tool
|
|
|
|
// is pretty tricky. Specifically information about the types involved
|
|
|
|
// with a function signature (especially generic ones) can be hefty to
|
|
|
|
// translate over. As a result, the macro emits a bunch of shims which,
|
|
|
|
// when executed, will describe to us what the types look like.
|
|
|
|
//
|
|
|
|
// This means that whenever we encounter an import or export we'll
|
|
|
|
// execute a shim function which informs us about its type so we can
|
|
|
|
// then generate the appropriate bindings.
|
2018-07-25 15:42:44 -07:00
|
|
|
//
|
|
|
|
// TODO: avoid a `clone` here of the module if we can
|
|
|
|
let instance = wasmi::Module::from_parity_wasm_module(module.clone())
|
2018-04-25 11:42:22 -07:00
|
|
|
.with_context(|_| "failed to create wasmi module")?;
|
|
|
|
let instance = wasmi::ModuleInstance::new(&instance, &MyResolver)
|
|
|
|
.with_context(|_| "failed to instantiate wasm module")?;
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
let instance = instance.not_started_instance();
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
let (js, ts) = {
|
|
|
|
let mut cx = js::Context {
|
|
|
|
globals: String::new(),
|
|
|
|
imports: String::new(),
|
2018-03-29 01:47:44 -07:00
|
|
|
footer: String::new(),
|
2018-02-06 15:52:44 -08:00
|
|
|
typescript: format!("/* tslint:disable */\n"),
|
|
|
|
exposed_globals: Default::default(),
|
|
|
|
required_internal_exports: Default::default(),
|
2018-02-07 16:41:33 -08:00
|
|
|
imported_names: Default::default(),
|
|
|
|
exported_classes: Default::default(),
|
2018-02-06 15:52:44 -08:00
|
|
|
config: &self,
|
|
|
|
module: &mut module,
|
2018-04-04 08:24:19 -07:00
|
|
|
function_table_needed: false,
|
2018-04-25 07:26:33 -07:00
|
|
|
module_versions: Default::default(),
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
run_descriptor: &|name| {
|
|
|
|
let mut v = MyExternals(Vec::new());
|
2018-06-18 13:48:57 -07:00
|
|
|
match instance.invoke_export(name, &[], &mut v) {
|
|
|
|
Ok(None) => Some(v.0),
|
2018-06-27 22:42:34 -07:00
|
|
|
Ok(Some(_)) => unreachable!(
|
|
|
|
"there is only one export, and we only return None from it"
|
|
|
|
),
|
2018-06-18 13:48:57 -07:00
|
|
|
// Allow missing exported describe functions. This can
|
|
|
|
// happen when a nested dependency crate exports things
|
|
|
|
// but the root crate doesn't use them.
|
|
|
|
Err(wasmi::Error::Function(_)) => None,
|
|
|
|
Err(e) => panic!("unexpected error running descriptor: {}", e),
|
|
|
|
}
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
},
|
2018-02-06 15:52:44 -08:00
|
|
|
};
|
|
|
|
for program in programs.iter() {
|
|
|
|
js::SubContext {
|
|
|
|
program,
|
|
|
|
cx: &mut cx,
|
2018-04-25 11:42:22 -07:00
|
|
|
}.generate()?;
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-04-25 11:42:22 -07:00
|
|
|
cx.finalize(stem)?
|
2018-02-06 15:52:44 -08:00
|
|
|
};
|
2018-01-29 21:20:38 -08:00
|
|
|
|
2018-07-04 22:37:09 -05:00
|
|
|
let extension = if self.nodejs_experimental_modules { "mjs" } else { "js" };
|
|
|
|
let js_path = out_dir.join(stem).with_extension(extension);
|
2018-07-25 16:06:47 -07:00
|
|
|
fs::write(&js_path, reset_indentation(&js))
|
2018-04-25 11:42:22 -07:00
|
|
|
.with_context(|_| format!("failed to write `{}`", js_path.display()))?;
|
2018-01-29 21:20:38 -08:00
|
|
|
|
|
|
|
if self.typescript {
|
|
|
|
let ts_path = out_dir.join(stem).with_extension("d.ts");
|
2018-07-25 16:06:47 -07:00
|
|
|
fs::write(&ts_path, ts)
|
2018-04-25 11:42:22 -07:00
|
|
|
.with_context(|_| format!("failed to write `{}`", ts_path.display()))?;
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
|
2018-03-05 22:25:14 +01:00
|
|
|
let wasm_path = out_dir.join(format!("{}_bg", stem)).with_extension("wasm");
|
2018-03-29 01:47:44 -07:00
|
|
|
|
|
|
|
if self.nodejs {
|
2018-07-04 22:37:09 -05:00
|
|
|
let js_path = wasm_path.with_extension(extension);
|
2018-03-29 01:47:44 -07:00
|
|
|
let shim = self.generate_node_wasm_import(&module, &wasm_path);
|
2018-07-25 16:06:47 -07:00
|
|
|
fs::write(&js_path, shim)
|
2018-04-25 11:42:22 -07:00
|
|
|
.with_context(|_| format!("failed to write `{}`", js_path.display()))?;
|
2018-03-29 01:47:44 -07:00
|
|
|
}
|
|
|
|
|
2018-04-25 11:42:22 -07:00
|
|
|
let wasm_bytes = parity_wasm::serialize(module)?;
|
2018-07-25 16:06:47 -07:00
|
|
|
fs::write(&wasm_path, wasm_bytes)
|
2018-04-25 11:42:22 -07:00
|
|
|
.with_context(|_| format!("failed to write `{}`", wasm_path.display()))?;
|
2017-12-14 19:31:01 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
2018-03-29 01:47:44 -07:00
|
|
|
|
|
|
|
fn generate_node_wasm_import(&self, m: &Module, path: &Path) -> String {
|
|
|
|
let mut imports = BTreeSet::new();
|
|
|
|
if let Some(i) = m.import_section() {
|
|
|
|
for i in i.entries() {
|
|
|
|
imports.insert(i.module());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut shim = String::new();
|
2018-07-04 22:37:09 -05:00
|
|
|
|
|
|
|
if self.nodejs_experimental_modules {
|
|
|
|
for (i, module) in imports.iter().enumerate() {
|
|
|
|
shim.push_str(&format!("import * as import{} from '{}';\n",
|
|
|
|
i, module));
|
|
|
|
}
|
|
|
|
// On windows skip the leading `/` which comes out when we parse a
|
|
|
|
// url to use `C:\...` instead of `\C:\...`
|
|
|
|
shim.push_str(&format!("
|
|
|
|
import * as path from 'path';
|
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as url from 'url';
|
|
|
|
import * as process from 'process';
|
|
|
|
|
|
|
|
let file = path.dirname(url.parse(import.meta.url).pathname);
|
|
|
|
if (process.platform === 'win32') {{
|
|
|
|
file = file.substring(1);
|
|
|
|
}}
|
|
|
|
const bytes = fs.readFileSync(path.join(file, '{}'));
|
|
|
|
", path.file_name().unwrap().to_str().unwrap()));
|
|
|
|
} else {
|
|
|
|
shim.push_str(&format!("
|
|
|
|
const path = require('path').join(__dirname, '{}');
|
|
|
|
const bytes = require('fs').readFileSync(path);
|
|
|
|
", path.file_name().unwrap().to_str().unwrap()));
|
|
|
|
}
|
2018-03-29 01:47:44 -07:00
|
|
|
shim.push_str("let imports = {};\n");
|
2018-07-04 22:37:09 -05:00
|
|
|
for (i, module) in imports.iter().enumerate() {
|
|
|
|
if self.nodejs_experimental_modules {
|
|
|
|
shim.push_str(&format!("imports['{}'] = import{};\n", module, i));
|
|
|
|
} else {
|
|
|
|
shim.push_str(&format!("imports['{0}'] = require('{0}');\n", module));
|
|
|
|
}
|
2018-03-29 01:47:44 -07:00
|
|
|
}
|
|
|
|
|
2018-06-27 22:42:34 -07:00
|
|
|
shim.push_str(&format!(
|
|
|
|
"
|
2018-07-04 22:37:09 -05:00
|
|
|
const wasmModule = new WebAssembly.Module(bytes);
|
|
|
|
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2018-06-27 22:42:34 -07:00
|
|
|
));
|
2018-03-29 01:47:44 -07:00
|
|
|
|
2018-07-04 22:37:09 -05:00
|
|
|
if self.nodejs_experimental_modules {
|
|
|
|
if let Some(e) = m.export_section() {
|
|
|
|
for name in e.entries().iter().map(|e| e.field()) {
|
|
|
|
shim.push_str("export const ");
|
|
|
|
shim.push_str(name);
|
|
|
|
shim.push_str(" = wasmInstance.exports.");
|
|
|
|
shim.push_str(name);
|
|
|
|
shim.push_str(";\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shim.push_str("module.exports = wasmInstance.exports;\n");
|
|
|
|
}
|
|
|
|
|
2018-06-15 12:55:37 -05:00
|
|
|
reset_indentation(&shim)
|
2018-03-29 01:47:44 -07:00
|
|
|
}
|
2017-12-14 19:31:01 -08:00
|
|
|
}
|
|
|
|
|
2018-04-25 11:42:22 -07:00
|
|
|
fn extract_programs(module: &mut Module) -> Result<Vec<shared::Program>, Error> {
|
2018-03-01 19:32:05 -08:00
|
|
|
let version = shared::version();
|
2018-02-06 15:52:44 -08:00
|
|
|
let mut ret = Vec::new();
|
2018-04-25 11:42:22 -07:00
|
|
|
let mut to_remove = Vec::new();
|
2017-12-14 19:31:01 -08:00
|
|
|
|
2018-04-25 11:42:22 -07:00
|
|
|
for (i, s) in module.sections().iter().enumerate() {
|
2018-03-14 14:33:53 -07:00
|
|
|
let custom = match *s {
|
|
|
|
Section::Custom(ref s) => s,
|
2018-04-25 11:42:22 -07:00
|
|
|
_ => continue,
|
2018-03-14 14:33:53 -07:00
|
|
|
};
|
2018-07-25 16:56:27 -05:00
|
|
|
if custom.name() != "__wasm_bindgen_unstable" {
|
2018-06-27 22:42:34 -07:00
|
|
|
continue;
|
2018-03-14 14:33:53 -07:00
|
|
|
}
|
2018-04-25 11:42:22 -07:00
|
|
|
to_remove.push(i);
|
2018-03-14 14:33:53 -07:00
|
|
|
|
2018-03-31 07:57:47 -07:00
|
|
|
let mut payload = custom.payload();
|
2018-07-16 13:44:41 -07:00
|
|
|
let mut added_programs = Vec::new();
|
2018-03-14 14:33:53 -07:00
|
|
|
while payload.len() > 0 {
|
2018-06-27 22:42:34 -07:00
|
|
|
let len = ((payload[0] as usize) << 0)
|
|
|
|
| ((payload[1] as usize) << 8)
|
|
|
|
| ((payload[2] as usize) << 16)
|
|
|
|
| ((payload[3] as usize) << 24);
|
2018-03-31 07:57:47 -07:00
|
|
|
let (a, b) = payload[4..].split_at(len as usize);
|
2018-03-14 14:33:53 -07:00
|
|
|
payload = b;
|
2018-07-16 13:44:41 -07:00
|
|
|
|
|
|
|
// Due to a nasty LLVM bug it's currently possible for LLVM to
|
|
|
|
// duplicate custom section directives in intermediate object files.
|
|
|
|
// This means that we could see multiple program directives when in
|
|
|
|
// fact we were originally only meant to see one!
|
|
|
|
//
|
|
|
|
// Work around the issue here until the upstream bug,
|
|
|
|
// https://bugs.llvm.org/show_bug.cgi?id=38184, is hopefully fixed
|
|
|
|
// via some other means.
|
|
|
|
if added_programs.iter().any(|p| a == *p) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
added_programs.push(a);
|
|
|
|
|
2018-04-19 13:36:59 -07:00
|
|
|
let p: shared::ProgramOnlySchema = match serde_json::from_slice(&a) {
|
2017-12-14 19:31:01 -08:00
|
|
|
Ok(f) => f,
|
2018-06-27 22:42:34 -07:00
|
|
|
Err(e) => bail!("failed to decode what looked like wasm-bindgen data: {}", e),
|
2017-12-14 19:31:01 -08:00
|
|
|
};
|
2018-03-05 20:05:44 -08:00
|
|
|
if p.schema_version != shared::SCHEMA_VERSION {
|
2018-06-27 22:42:34 -07:00
|
|
|
bail!(
|
|
|
|
"
|
2018-03-01 19:32:05 -08:00
|
|
|
|
|
|
|
it looks like the Rust project used to create this wasm file was linked against
|
|
|
|
a different version of wasm-bindgen than this binary:
|
|
|
|
|
|
|
|
rust wasm file: {}
|
|
|
|
this binary: {}
|
|
|
|
|
|
|
|
Currently the bindgen format is unstable enough that these two version must
|
|
|
|
exactly match, so it's required that these two version are kept in sync by
|
|
|
|
either updating the wasm-bindgen dependency or this binary. You should be able
|
|
|
|
to update the wasm-bindgen dependency with:
|
|
|
|
|
|
|
|
cargo update -p wasm-bindgen
|
|
|
|
|
|
|
|
or you can update the binary with
|
|
|
|
|
2018-04-20 19:07:56 -07:00
|
|
|
cargo install -f wasm-bindgen-cli
|
2018-03-01 19:32:05 -08:00
|
|
|
|
|
|
|
if this warning fails to go away though and you're not sure what to do feel free
|
2018-07-19 14:57:04 -05:00
|
|
|
to open an issue at https://github.com/rustwasm/wasm-bindgen/issues!
|
2018-03-01 19:32:05 -08:00
|
|
|
",
|
2018-06-27 22:42:34 -07:00
|
|
|
p.version,
|
|
|
|
version
|
|
|
|
);
|
2018-03-01 19:32:05 -08:00
|
|
|
}
|
2018-04-19 13:36:59 -07:00
|
|
|
let p: shared::Program = match serde_json::from_slice(&a) {
|
|
|
|
Ok(f) => f,
|
2018-06-27 22:42:34 -07:00
|
|
|
Err(e) => bail!("failed to decode what looked like wasm-bindgen data: {}", e),
|
2018-04-19 13:36:59 -07:00
|
|
|
};
|
2018-02-06 15:52:44 -08:00
|
|
|
ret.push(p);
|
2018-03-09 16:09:07 -08:00
|
|
|
}
|
2018-04-25 11:42:22 -07:00
|
|
|
}
|
2018-03-14 10:50:12 -07:00
|
|
|
|
2018-04-25 11:42:22 -07:00
|
|
|
for i in to_remove.into_iter().rev() {
|
|
|
|
module.sections_mut().remove(i);
|
|
|
|
}
|
|
|
|
Ok(ret)
|
2018-02-06 16:06:21 -08:00
|
|
|
}
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
|
|
|
|
struct MyResolver;
|
|
|
|
|
|
|
|
impl wasmi::ImportResolver for MyResolver {
|
|
|
|
fn resolve_func(
|
|
|
|
&self,
|
|
|
|
module_name: &str,
|
|
|
|
field_name: &str,
|
2018-06-27 22:42:34 -07:00
|
|
|
signature: &wasmi::Signature,
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
) -> Result<wasmi::FuncRef, wasmi::Error> {
|
|
|
|
// Route our special "describe" export to 1 and everything else to 0.
|
|
|
|
// That way whenever the function 1 is invoked we know what to do and
|
|
|
|
// when 0 is invoked (by accident) we'll trap and produce an error.
|
2018-06-27 22:42:34 -07:00
|
|
|
let idx = (module_name == "__wbindgen_placeholder__" && field_name == "__wbindgen_describe")
|
|
|
|
as usize;
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
Ok(wasmi::FuncInstance::alloc_host(signature.clone(), idx))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_global(
|
|
|
|
&self,
|
|
|
|
_module_name: &str,
|
|
|
|
_field_name: &str,
|
2018-06-27 22:42:34 -07:00
|
|
|
descriptor: &wasmi::GlobalDescriptor,
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
) -> Result<wasmi::GlobalRef, wasmi::Error> {
|
|
|
|
// dummy implementation to ensure instantiation succeeds
|
|
|
|
let val = match descriptor.value_type() {
|
|
|
|
wasmi::ValueType::I32 => wasmi::RuntimeValue::I32(0),
|
|
|
|
wasmi::ValueType::I64 => wasmi::RuntimeValue::I64(0),
|
2018-04-26 18:39:08 -07:00
|
|
|
wasmi::ValueType::F32 => wasmi::RuntimeValue::F32(0.0.into()),
|
|
|
|
wasmi::ValueType::F64 => wasmi::RuntimeValue::F64(0.0.into()),
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
};
|
|
|
|
Ok(wasmi::GlobalInstance::alloc(val, descriptor.is_mutable()))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_memory(
|
|
|
|
&self,
|
|
|
|
_module_name: &str,
|
|
|
|
_field_name: &str,
|
|
|
|
descriptor: &wasmi::MemoryDescriptor,
|
|
|
|
) -> Result<wasmi::MemoryRef, wasmi::Error> {
|
|
|
|
// dummy implementation to ensure instantiation succeeds
|
|
|
|
use wasmi::memory_units::Pages;
|
|
|
|
let initial = Pages(descriptor.initial() as usize);
|
|
|
|
let maximum = descriptor.maximum().map(|i| Pages(i as usize));
|
|
|
|
wasmi::MemoryInstance::alloc(initial, maximum)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_table(
|
|
|
|
&self,
|
|
|
|
_module_name: &str,
|
|
|
|
_field_name: &str,
|
2018-06-27 22:42:34 -07:00
|
|
|
descriptor: &wasmi::TableDescriptor,
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
) -> Result<wasmi::TableRef, wasmi::Error> {
|
|
|
|
// dummy implementation to ensure instantiation succeeds
|
|
|
|
let initial = descriptor.initial();
|
|
|
|
let maximum = descriptor.maximum();
|
|
|
|
wasmi::TableInstance::alloc(initial, maximum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct MyExternals(Vec<u32>);
|
2018-06-18 13:48:57 -07:00
|
|
|
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct MyError(String);
|
|
|
|
|
|
|
|
impl wasmi::Externals for MyExternals {
|
|
|
|
fn invoke_index(
|
|
|
|
&mut self,
|
|
|
|
index: usize,
|
2018-06-27 22:42:34 -07:00
|
|
|
args: wasmi::RuntimeArgs,
|
Overhaul how type information gets to the CLI
This commit is a complete overhaul of how the `#[wasm_bindgen]` macro
communicates type information to the CLI tool, and it's done in a somewhat...
unconventional fashion.
Today we've got a problem where the generated JS needs to understand the types
of each function exported or imported. This understanding is what enables it to
generate the appropriate JS wrappers and such. We want to, however, be quite
flexible and extensible in types that are supported across the boundary, which
means that internally we rely on the trait system to resolve what's what.
Communicating the type information historically was done by creating a four byte
"descriptor" and using associated type projections to communicate that to the
CLI tool. Unfortunately four bytes isn't a lot of space to cram information like
arguments to a generic function, tuple types, etc. In general this just wasn't
flexible enough and the way custom references were treated was also already a
bit of a hack.
This commit takes a radical step of creating a **descriptor function** for each
function imported/exported. The really crazy part is that the `wasm-bindgen` CLI
tool now embeds a wasm interpreter and executes these functions when the CLI
tool is invoked. By allowing arbitrary functions to get executed it's now *much*
easier to inform `wasm-bindgen` about complicated structures of types. Rest
assured though that all these descriptor functions are automatically unexported
and gc'd away, so this should not have any impact on binary sizes
A new internal trait, `WasmDescribe`, is added to represent a description of all
types, sort of like a serialization of the structure of a type that
`wasm-bindgen` can understand. This works by calling a special exported function
with a `u32` value a bunch of times. This means that when we run a descriptor we
effectively get a `Vec<u32>` in the `wasm-bindgen` CLI tool. This list of
integers can then be parsed into a rich `enum` for the JS generation to work
with.
This commit currently only retains feature parity with the previous
implementation. I hope to soon solve issues like #123, #104, and #111 with this
support.
2018-04-13 07:33:46 -07:00
|
|
|
) -> Result<Option<wasmi::RuntimeValue>, wasmi::Trap> {
|
|
|
|
macro_rules! bail {
|
|
|
|
($($t:tt)*) => ({
|
|
|
|
let s = MyError(format!($($t)*));
|
|
|
|
return Err(wasmi::Trap::new(wasmi::TrapKind::Host(Box::new(s))))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
// We only recognize one function here which was mapped to the index 1
|
|
|
|
// by the resolver above.
|
|
|
|
if index != 1 {
|
|
|
|
bail!("only __wbindgen_describe can be run at this time")
|
|
|
|
}
|
|
|
|
if args.len() != 1 {
|
|
|
|
bail!("must have exactly one argument");
|
|
|
|
}
|
|
|
|
match args.nth_value_checked(0)? {
|
|
|
|
wasmi::RuntimeValue::I32(i) => self.0.push(i as u32),
|
|
|
|
_ => bail!("expected one argument of i32 type"),
|
|
|
|
}
|
|
|
|
Ok(None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl wasmi::HostError for MyError {}
|
|
|
|
|
|
|
|
impl fmt::Display for MyError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
self.0.fmt(f)
|
|
|
|
}
|
|
|
|
}
|
2018-06-15 12:55:37 -05:00
|
|
|
|
|
|
|
fn reset_indentation(s: &str) -> String {
|
2018-07-09 07:44:41 -07:00
|
|
|
let mut indent: u32 = 0;
|
|
|
|
let mut dst = String::new();
|
2018-06-15 12:55:37 -05:00
|
|
|
|
2018-07-09 07:44:41 -07:00
|
|
|
for line in s.lines() {
|
|
|
|
let line = line.trim();
|
2018-07-09 14:55:25 -05:00
|
|
|
if line.starts_with('}') || (line.ends_with('}') && !line.starts_with('*')) {
|
2018-07-09 07:44:41 -07:00
|
|
|
indent = indent.saturating_sub(1);
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|
2018-07-09 07:44:41 -07:00
|
|
|
let extra = if line.starts_with(':') || line.starts_with('?') { 1 } else { 0 };
|
|
|
|
for _ in 0..indent + extra {
|
|
|
|
dst.push_str(" ");
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|
2018-07-09 07:44:41 -07:00
|
|
|
dst.push_str(line);
|
|
|
|
dst.push_str("\n");
|
|
|
|
if line.ends_with('{') {
|
|
|
|
indent += 1;
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|
|
|
|
}
|
2018-07-09 07:44:41 -07:00
|
|
|
return dst
|
2018-06-15 12:55:37 -05:00
|
|
|
}
|