Implement the local JS snippets RFC

This commit is an implementation of [RFC 6] which enables crates to
inline local JS snippets into the final output artifact of
`wasm-bindgen`. This is accompanied with a few minor breaking changes
which are intended to be relatively minor in practice:

* The `module` attribute disallows paths starting with `./` and `../`.
  It requires paths starting with `/` to actually exist on the filesystem.
* The `--browser` flag no longer emits bundler-compatible code, but
  rather emits an ES module that can be natively loaded into a browser.

Otherwise be sure to check out [the RFC][RFC 6] for more details, and
otherwise this should implement at least the MVP version of the RFC!
Notably at this time JS snippets with `--nodejs` or `--no-modules` are
not supported and will unconditionally generate an error.

[RFC 6]: https://github.com/rustwasm/rfcs/pull/6

Closes #1311
This commit is contained in:
Alex Crichton
2019-02-25 11:11:30 -08:00
parent f161717afe
commit b762948456
32 changed files with 985 additions and 380 deletions

View File

@ -107,7 +107,8 @@ fn rmain() -> Result<(), Error> {
shell.status("Executing bindgen...");
let mut b = Bindgen::new();
b.debug(debug)
.nodejs(node)
.nodejs(node)?
.browser(!node)?
.input_module(module, wasm)
.keep_debug(false)
.emit_start(false)

View File

@ -5,7 +5,6 @@ use std::path::Path;
use failure::{format_err, Error, ResultExt};
use rouille::{Request, Response, Server};
use wasm_bindgen_cli_support::wasm2es6js::Config;
pub fn spawn(
addr: &SocketAddr,
@ -23,9 +22,9 @@ pub fn spawn(
__wbgtest_console_log,
__wbgtest_console_info,
__wbgtest_console_warn,
__wbgtest_console_error
__wbgtest_console_error,
default as init,
}} from './{0}';
import * as wasm from './{0}_bg';
// Now that we've gotten to the point where JS is executing, update our
// status text as at this point we should be asynchronously fetching the
@ -33,9 +32,7 @@ pub fn spawn(
document.getElementById('output').textContent = "Loading wasm module...";
async function main(test) {{
// this is a facet of using wasm2es6js, a hack until browsers have
// native ESM support for wasm modules.
await wasm.booted;
const wasm = await init('./{0}_bg.wasm');
const cx = new Context();
window.on_console_debug = __wbgtest_console_debug;
@ -65,25 +62,6 @@ pub fn spawn(
let js_path = tmpdir.join("run.js");
fs::write(&js_path, js_to_execute).context("failed to write JS file")?;
// No browser today supports a wasm file as ES modules natively, so we need
// to shim it. Use `wasm2es6js` here to fetch an appropriate URL and look
// like an ES module with the wasm module under the hood.
//
// TODO: don't reparse the wasm module here, should pass the
// `Module struct` directly from the output of
// `wasm-bindgen` previously here and avoid unnecessary
// parsing.
let wasm_name = format!("{}_bg.wasm", module);
let wasm = fs::read(tmpdir.join(&wasm_name))?;
let output = Config::new()
.fetch(Some(format!("/{}", wasm_name)))
.generate(&wasm)?;
let (js, wasm) = output.js_and_wasm()?;
let wasm = wasm.unwrap();
fs::write(tmpdir.join(format!("{}_bg.js", module)), js).context("failed to write JS file")?;
fs::write(tmpdir.join(format!("{}_bg.wasm", module)), wasm)
.context("failed to write wasm file")?;
// For now, always run forever on this port. We may update this later!
let tmpdir = tmpdir.to_path_buf();
let srv = Server::new(addr, move |request| {

View File

@ -88,9 +88,9 @@ fn rmain(args: &Args) -> Result<(), Error> {
let mut b = Bindgen::new();
b.input_path(input)
.nodejs(args.flag_nodejs)
.browser(args.flag_browser)
.no_modules(args.flag_no_modules)
.nodejs(args.flag_nodejs)?
.browser(args.flag_browser)?
.no_modules(args.flag_no_modules)?
.debug(args.flag_debug)
.demangle(!args.flag_no_demangle)
.keep_debug(args.flag_keep_debug)
@ -98,7 +98,7 @@ fn rmain(args: &Args) -> Result<(), Error> {
.remove_producers_section(args.flag_remove_producers_section)
.typescript(typescript);
if let Some(ref name) = args.flag_no_modules_global {
b.no_modules_global(name);
b.no_modules_global(name)?;
}
if let Some(ref name) = args.flag_out_name {
b.out_name(name);