494 lines
16 KiB
Rust
Raw Normal View History

#![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;
#[macro_use]
extern crate wasm_bindgen_shared as shared;
extern crate wasm_bindgen_gc as gc;
#[macro_use]
extern crate failure;
extern crate wasm_bindgen_threads_xform as threads_xform;
2018-11-27 12:07:59 -08:00
extern crate wasm_bindgen_wasm_interpreter as wasm_interpreter;
2017-12-14 19:31:01 -08:00
use std::collections::BTreeSet;
use std::env;
use std::fs;
use std::mem;
use std::path::{Path, PathBuf};
use std::str;
2017-12-14 19:31:01 -08:00
use failure::{Error, ResultExt};
2017-12-14 19:31:01 -08:00
use parity_wasm::elements::*;
mod decode;
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;
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
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 {
input: Input,
2017-12-14 21:55:21 -08:00
nodejs: bool,
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
nodejs_experimental_modules: bool,
browser: bool,
2018-04-11 13:59:58 +05:45
no_modules: bool,
no_modules_global: Option<String>,
debug: bool,
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
2018-01-29 21:20:38 -08:00
typescript: bool,
2018-04-11 11:43:18 -07:00
demangle: bool,
keep_debug: bool,
remove_name_section: bool,
// Experimental support for `WeakRefGroup`, an upcoming ECMAScript feature.
// Currently only enable-able through an env var.
weak_refs: bool,
// Experimental support for the wasm threads proposal, transforms the wasm
// module to be "ready to be instantiated on any thread"
threads: Option<threads_xform::Config>,
2017-12-14 19:31:01 -08:00
}
enum Input {
Path(PathBuf),
Module(Module, String),
None,
}
2017-12-14 19:31:01 -08:00
impl Bindgen {
pub fn new() -> Bindgen {
Bindgen {
input: Input::None,
2017-12-14 21:55:21 -08:00
nodejs: false,
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
nodejs_experimental_modules: false,
browser: false,
2018-04-11 13:59:58 +05:45
no_modules: false,
no_modules_global: None,
debug: false,
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
2018-01-29 21:20:38 -08:00
typescript: false,
2018-04-11 11:43:18 -07:00
demangle: true,
keep_debug: false,
remove_name_section: false,
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
threads: threads_config(),
2017-12-14 19:31:01 -08:00
}
}
pub fn input_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Bindgen {
self.input = Input::Path(path.as_ref().to_path_buf());
self
}
/// Explicitly specify the already parsed input module.
pub fn input_module(&mut self, name: &str, module: Module) -> &mut Bindgen {
let name = name.to_string();
self.input = Input::Module(module, name);
return self;
2017-12-14 19:31:01 -08:00
}
2017-12-14 21:55:21 -08:00
pub fn nodejs(&mut self, node: bool) -> &mut Bindgen {
self.nodejs = node;
self
}
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
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
}
pub fn browser(&mut self, browser: bool) -> &mut Bindgen {
self.browser = browser;
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
}
pub fn no_modules_global(&mut self, name: &str) -> &mut Bindgen {
self.no_modules_global = Some(name.to_string());
self
}
pub fn debug(&mut self, debug: bool) -> &mut Bindgen {
self.debug = debug;
self
}
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
2018-01-29 21:20:38 -08:00
pub fn typescript(&mut self, typescript: bool) -> &mut Bindgen {
self.typescript = typescript;
self
}
2018-04-11 11:43:18 -07:00
pub fn demangle(&mut self, demangle: bool) -> &mut Bindgen {
self.demangle = demangle;
self
}
pub fn keep_debug(&mut self, keep_debug: bool) -> &mut Bindgen {
self.keep_debug = keep_debug;
self
}
pub fn remove_name_section(&mut self, remove: bool) -> &mut Bindgen {
self.remove_name_section = remove;
self
}
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
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> {
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::Path(ref path) => {
let contents = fs::read(&path)
.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
};
let mut program_storage = Vec::new();
let programs = extract_programs(&mut module, &mut program_storage)
.with_context(|_| "failed to extract wasm-bindgen custom sections")?;
if let Some(cfg) = &self.threads {
cfg.run(&mut module)
.with_context(|_| "failed to prepare module for threading")?;
}
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.
let mut instance = wasm_interpreter::Interpreter::new(&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 (js, ts) = {
let mut cx = js::Context {
globals: String::new(),
imports: String::new(),
imports_post: String::new(),
footer: String::new(),
typescript: format!("/* tslint:disable */\n"),
exposed_globals: Default::default(),
required_internal_exports: Default::default(),
imported_names: Default::default(),
imported_identifiers: Default::default(),
exported_classes: Default::default(),
config: &self,
module: &mut module,
function_table_needed: false,
interpreter: &mut instance,
memory_init: None,
imported_functions: Default::default(),
imported_statics: Default::default(),
direct_imports: Default::default(),
};
for program in programs.iter() {
js::SubContext {
program,
cx: &mut cx,
vendor_prefixes: Default::default(),
2018-11-27 12:07:59 -08:00
}
.generate()?;
}
cx.finalize(stem)?
};
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
2018-01-29 21:20:38 -08:00
let extension = if self.nodejs_experimental_modules {
"mjs"
} else {
"js"
};
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
let js_path = out_dir.join(stem).with_extension(extension);
fs::write(&js_path, reset_indentation(&js))
.with_context(|_| format!("failed to write `{}`", js_path.display()))?;
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
2018-01-29 21:20:38 -08:00
if self.typescript {
let ts_path = js_path.with_extension("d.ts");
fs::write(&ts_path, ts)
.with_context(|_| format!("failed to write `{}`", ts_path.display()))?;
Rewrite wasm-bindgen with ES6 modules in mind This commit is a mostly-rewrite of the `wasm-bindgen` tool. After some recent discussions it's clear that the previous model wasn't quite going to cut it, and this iteration is one which primarily embraces ES6 modules and the idea that this is a polyfill for host bindings. The overall interface and functionality hasn't changed much but the underlying technology has now changed significantly. Previously `wasm-bindgen` would emit a JS file that acted as an ES6 module but had a bit of a wonky interface. It exposed an async function for instantiation of the wasm module, but that's the bundler's job, not ours! Instead this iteration views each input and output as a discrete ES6 module. The input wasm file is interpreted as "this *should* be an ES6 module with rich types" and the output is "well here's some ES6 modules that fulfill that contract". Notably the tool now replaces the original wasm ES6 module with a JS ES6 module that has the "rich interface". Additionally a second ES6 module is emitted (the actual wasm file) which imports and exports to the original ES6 module. This strategy is hoped to be much more amenable to bundlers and controlling how the wasm itself is instantiated. The emitted files files purely assume ES6 modules and should be able to work as-is once ES6 module integration for wasm is completed. Note that there aren't a ton of tools to pretend a wasm module is an ES6 module at the moment but those should be coming soon! In the meantime a local `wasm2es6js` hack was added to help make *something* work today. The README has also been updated with instructions for interacting with this model.
2018-01-29 21:20:38 -08:00
}
2017-12-14 19:31:01 -08:00
let wasm_path = out_dir.join(format!("{}_bg", stem)).with_extension("wasm");
if self.nodejs {
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
let js_path = wasm_path.with_extension(extension);
let shim = self.generate_node_wasm_import(&module, &wasm_path);
fs::write(&js_path, shim)
.with_context(|_| format!("failed to write `{}`", js_path.display()))?;
}
if self.typescript {
let ts_path = wasm_path.with_extension("d.ts");
let ts = wasm2es6js::typescript(&module);
fs::write(&ts_path, ts)
.with_context(|_| format!("failed to write `{}`", ts_path.display()))?;
}
let wasm_bytes = parity_wasm::serialize(module)?;
fs::write(&wasm_path, wasm_bytes)
.with_context(|_| format!("failed to write `{}`", wasm_path.display()))?;
2017-12-14 19:31:01 -08:00
Ok(())
}
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();
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
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));
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
}
// On windows skip the leading `/` which comes out when we parse a
// url to use `C:\...` instead of `\C:\...`
shim.push_str(&format!(
"
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
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()
));
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
} else {
shim.push_str(&format!(
"
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
const path = require('path').join(__dirname, '{}');
const bytes = require('fs').readFileSync(path);
",
path.file_name().unwrap().to_str().unwrap()
));
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
}
shim.push_str("let imports = {};\n");
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
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-06-27 22:42:34 -07:00
shim.push_str(&format!(
"
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
2018-07-04 22:37:09 -05:00
const wasmModule = new WebAssembly.Module(bytes);
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
",
2018-06-27 22:42:34 -07:00
));
Speed up Travis by running Webpack in fewer tests (#381) * Reorganize Travis configuration * Add a `JOB` env var descriptor to all matrix entries. Not used anywhere but is useful when viewing the whole build on Travis's web interface. * Reorganize where builds are located, moving slow builds first and fast ones last. * Change checking the CLI builds from `cargo build` to `cargo check` * Use YAML references to reduce some duplication * Print some more timing statistics for each test * Extract `Project` helper in tests to a module This'll help make it a bit more extensible over time. At the same time the methods are also slightly reorganized to read more clearly from top to bottom. * Migrate all tests away from Webpack Wepback can take a significant amount of time to execute and when it's multiplied by hundreds of tests that adds up really quickly! After investigating Node's `--experimental-modules` option it looks like it's suitable for our use so this switches all tests to using JS files (moving away from TypeScript as well) with `--experimental-modules` with Node. Tests will be selectively re-enabled with webpack and node.js specific output (that doesn't require `--experimental-modules`), coming in later commits. * Restore the node test for node.js output Ensures it's workable as-is * Only generate typescript with webpack * Only read wasm files for webpack * Skip package.json/node_modules for now * Only generate webpack config if needed * Start a dedicated test module for typescript Will hopefully verify the generated Typescript compiles OK. * Remove unneeded `node` method * Fixup some rebase conflicts * Don't run asmjs example on travis * Fixup generator tests * Attempt to fix windows * Comment windows fix * More test fixes * More exclusions * More test fixes * Relax eslint regex Catch mjs modules as well * Fix eslint * Speed up travis on examples slightly
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)
}
2017-12-14 19:31:01 -08:00
}
fn extract_programs<'a>(
module: &mut Module,
program_storage: &'a mut Vec<Vec<u8>>,
) -> Result<Vec<decode::Program<'a>>, Error> {
let my_version = shared::version();
let mut to_remove = Vec::new();
assert!(program_storage.is_empty());
2017-12-14 19:31:01 -08:00
for (i, s) in module.sections_mut().iter_mut().enumerate() {
let custom = match s {
Section::Custom(s) => s,
_ => continue,
};
if custom.name() != "__wasm_bindgen_unstable" {
2018-06-27 22:42:34 -07:00
continue;
}
to_remove.push(i);
program_storage.push(mem::replace(custom.payload_mut(), Vec::new()));
}
for i in to_remove.into_iter().rev() {
module.sections_mut().remove(i);
}
let mut ret = Vec::new();
for program in program_storage.iter() {
let mut payload = &program[..];
while let Some(data) = get_remaining(&mut payload) {
// Historical versions of wasm-bindgen have used JSON as the custom
// data section format. Newer versions, however, are using a custom
// serialization protocol that looks much more like the wasm spec.
//
// We, however, want a sanity check to ensure that if we're running
// against the wrong wasm-bindgen we get a nicer error than an
// internal decode error. To that end we continue to verify a tiny
// bit of json at the beginning of each blob before moving to the
// next blob. This should keep us compatible with older wasm-bindgen
// instances as well as forward-compatible for now.
//
// Note, though, that as `wasm-pack` picks up steam it's hoped we
// can just delete this entirely. The `wasm-pack` project already
// manages versions for us, so we in theory should need this check
// less and less over time.
if let Some(their_version) = verify_schema_matches(data)? {
2018-06-27 22:42:34 -07:00
bail!(
"
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
cargo install -f wasm-bindgen-cli
if this warning fails to go away though and you're not sure what to do feel free
to open an issue at https://github.com/rustwasm/wasm-bindgen/issues!
",
their_version,
my_version,
2018-06-27 22:42:34 -07:00
);
}
let next = get_remaining(&mut payload).unwrap();
ret.push(<decode::Program as decode::Decode>::decode_all(next));
}
}
Ok(ret)
}
fn get_remaining<'a>(data: &mut &'a [u8]) -> Option<&'a [u8]> {
if data.len() == 0 {
2018-11-27 12:07:59 -08:00
return None;
}
let len = ((data[0] as usize) << 0)
| ((data[1] as usize) << 8)
| ((data[2] as usize) << 16)
| ((data[3] as usize) << 24);
let (a, b) = data[4..].split_at(len);
*data = b;
Some(a)
}
2018-11-27 12:07:59 -08:00
fn verify_schema_matches<'a>(data: &'a [u8]) -> Result<Option<&'a str>, Error> {
macro_rules! bad {
2018-11-27 12:07:59 -08:00
() => {
bail!("failed to decode what looked like wasm-bindgen data")
};
}
let data = match str::from_utf8(data) {
Ok(s) => s,
Err(_) => bad!(),
};
if !data.starts_with("{") || !data.ends_with("}") {
bad!()
}
let needle = "\"schema_version\":\"";
let rest = match data.find(needle) {
Some(i) => &data[i + needle.len()..],
None => bad!(),
};
let their_schema_version = match rest.find("\"") {
Some(i) => &rest[..i],
None => bad!(),
};
if their_schema_version == shared::SCHEMA_VERSION {
2018-11-27 12:07:59 -08:00
return Ok(None);
}
let needle = "\"version\":\"";
let rest = match data.find(needle) {
Some(i) => &data[i + needle.len()..],
None => bad!(),
};
let their_version = match rest.find("\"") {
Some(i) => &rest[..i],
None => bad!(),
};
Ok(Some(their_version))
}
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-06-15 12:55:37 -05:00
fn reset_indentation(s: &str) -> String {
let mut indent: u32 = 0;
let mut dst = String::new();
2018-06-15 12:55:37 -05: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('*')) {
indent = indent.saturating_sub(1);
2018-06-15 12:55:37 -05:00
}
let extra = if line.starts_with(':') || line.starts_with('?') {
1
} else {
0
};
if !line.is_empty() {
for _ in 0..indent + extra {
dst.push_str(" ");
}
dst.push_str(line);
2018-06-15 12:55:37 -05:00
}
dst.push_str("\n");
if line.ends_with('{') {
indent += 1;
2018-06-15 12:55:37 -05:00
}
}
return dst;
2018-06-15 12:55:37 -05:00
}
// Eventually these will all be CLI options, but while they're unstable features
// they're left as environment variables. We don't guarantee anything about
// backwards-compatibility with these options.
fn threads_config() -> Option<threads_xform::Config> {
if env::var("WASM_BINDGEN_THREADS").is_err() {
2018-11-27 12:07:59 -08:00
return None;
}
let mut cfg = threads_xform::Config::new();
if let Ok(s) = env::var("WASM_BINDGEN_THREADS_MAX_MEMORY") {
cfg.maximum_memory(s.parse().unwrap());
}
if let Ok(s) = env::var("WASM_BINDGEN_THREADS_STACK_SIZE") {
cfg.thread_stack_size(s.parse().unwrap());
}
Some(cfg)
}