Skip to content

Commit

Permalink
Merge pull request #1725 from alexcrichton/real-webidl-section
Browse files Browse the repository at this point in the history
Add support for emitting a Wasm Interface Types section
  • Loading branch information
alexcrichton authored Aug 19, 2019
2 parents bd7c907 + c5dd572 commit 487289c
Show file tree
Hide file tree
Showing 6 changed files with 630 additions and 73 deletions.
32 changes: 19 additions & 13 deletions crates/cli-support/src/anyref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use walrus::Module;
use wasm_bindgen_anyref_xform::Context;
use wasm_webidl_bindings::ast;

pub fn process(module: &mut Module) -> Result<(), Error> {
pub fn process(module: &mut Module, wasm_interface_types: bool) -> Result<(), Error> {
let mut cfg = Context::default();
cfg.prepare(module)?;
let bindings = module
Expand Down Expand Up @@ -45,18 +45,24 @@ pub fn process(module: &mut Module) -> Result<(), Error> {

cfg.run(module)?;

// Make sure to export the `anyref` table for the JS bindings since it
// will need to be initialized. If it doesn't exist though then the
// module must not use it, so we skip it.
let table = module.tables.iter().find(|t| match t.kind {
walrus::TableKind::Anyref(_) => true,
_ => false,
});
let table = match table {
Some(t) => t.id(),
None => return Ok(()),
};
module.exports.add("__wbg_anyref_table", table);
// If our output is using WebAssembly interface types then our bindings will
// never use this table, so no need to export it. Otherwise it's highly
// likely in web/JS embeddings this will be used, so make sure we export it
// to avoid it getting gc'd accidentally.
if !wasm_interface_types {
// Make sure to export the `anyref` table for the JS bindings since it
// will need to be initialized. If it doesn't exist though then the
// module must not use it, so we skip it.
let table = module.tables.iter().find(|t| match t.kind {
walrus::TableKind::Anyref(_) => true,
_ => false,
});
let table = match table {
Some(t) => t.id(),
None => return Ok(()),
};
module.exports.add("__wbg_anyref_table", table);
}

// Clean up now-unused intrinsics and shims and such
walrus::passes::gc::run(module);
Expand Down
9 changes: 9 additions & 0 deletions crates/cli-support/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ macro_rules! intrinsics {
)*
}
}

/// Returns the symbol name of this intrinsic
pub fn name(&self) -> &'static str {
match self {
$(
Intrinsic::$name => $sym,
)*
}
}
}
};
}
Expand Down
2 changes: 2 additions & 0 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2081,11 +2081,13 @@ impl<'a> Context<'a> {
&binding.outgoing,
wasm_ty.params(),
&webidl.params,
self.config.wasm_interface_types,
)
&& webidl::incoming_do_not_require_glue(
&binding.incoming,
&webidl.result.into_iter().collect::<Vec<_>>(),
wasm_ty.results(),
self.config.wasm_interface_types,
)
}

Expand Down
43 changes: 32 additions & 11 deletions crates/cli-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub struct Bindgen {
// "ready to be instantiated on any thread"
threads: wasm_bindgen_threads_xform::Config,
anyref: bool,
wasm_interface_types: bool,
encode_into: EncodeInto,
}

Expand All @@ -49,6 +50,7 @@ pub struct Output {
snippets: HashMap<String, Vec<String>>,
local_modules: HashMap<String, String>,
npm_dependencies: HashMap<String, (PathBuf, String)>,
wasm_interface_types: bool,
}

#[derive(Clone)]
Expand All @@ -73,6 +75,8 @@ pub enum EncodeInto {

impl Bindgen {
pub fn new() -> Bindgen {
let anyref = env::var("WASM_BINDGEN_ANYREF").is_ok();
let wasm_interface_types = env::var("WASM_INTERFACE_TYPES").is_ok();
Bindgen {
input: Input::None,
out_name: None,
Expand All @@ -88,7 +92,8 @@ impl Bindgen {
emit_start: true,
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
threads: threads_config(),
anyref: env::var("WASM_BINDGEN_ANYREF").is_ok(),
anyref: anyref || wasm_interface_types,
wasm_interface_types,
encode_into: EncodeInto::Test,
}
}
Expand Down Expand Up @@ -315,15 +320,15 @@ impl Bindgen {
// the webidl bindings proposal) as well as an auxiliary section for all
// sorts of miscellaneous information and features #[wasm_bindgen]
// supports that aren't covered by WebIDL bindings.
webidl::process(&mut module, self.anyref, self.emit_start)?;
webidl::process(&mut module, self.anyref, self.wasm_interface_types, self.emit_start)?;

// Now that we've got type information from the webidl processing pass,
// touch up the output of rustc to insert anyref shims where necessary.
// This is only done if the anyref pass is enabled, which it's
// currently off-by-default since `anyref` is still in development in
// engines.
if self.anyref {
anyref::process(&mut module)?;
anyref::process(&mut module, self.wasm_interface_types)?;
}

let aux = module
Expand All @@ -344,6 +349,11 @@ impl Bindgen {
(npm_dependencies, cx.finalize(stem)?)
};

if self.wasm_interface_types {
webidl::standard::add_section(&mut module, &aux, &bindings)
.with_context(|_| "failed to generate a standard wasm bindings custom section")?;
}

Ok(Output {
module,
stem: stem.to_string(),
Expand All @@ -354,6 +364,7 @@ impl Bindgen {
ts,
mode: self.mode.clone(),
typescript: self.typescript,
wasm_interface_types: self.wasm_interface_types,
})
}

Expand Down Expand Up @@ -506,6 +517,7 @@ fn unexported_unused_lld_things(module: &mut Module) {

impl Output {
pub fn js(&self) -> &str {
assert!(!self.wasm_interface_types);
&self.js
}

Expand All @@ -518,6 +530,23 @@ impl Output {
}

fn _emit(&self, out_dir: &Path) -> Result<(), Error> {
let wasm_name = if self.wasm_interface_types {
self.stem.clone()
} else {
format!("{}_bg", self.stem)
};
let wasm_path = out_dir
.join(wasm_name)
.with_extension("wasm");
fs::create_dir_all(out_dir)?;
let wasm_bytes = self.module.emit_wasm()?;
fs::write(&wasm_path, wasm_bytes)
.with_context(|_| format!("failed to write `{}`", wasm_path.display()))?;

if self.wasm_interface_types {
return Ok(())
}

// Write out all local JS snippets to the final destination now that
// we've collected them from all the programs.
for (identifier, list) in self.snippets.iter() {
Expand Down Expand Up @@ -554,7 +583,6 @@ impl Output {
} else {
"js"
};
fs::create_dir_all(out_dir)?;
let js_path = out_dir.join(&self.stem).with_extension(extension);
fs::write(&js_path, reset_indentation(&self.js))
.with_context(|_| format!("failed to write `{}`", js_path.display()))?;
Expand All @@ -565,10 +593,6 @@ impl Output {
.with_context(|_| format!("failed to write `{}`", ts_path.display()))?;
}

let wasm_path = out_dir
.join(format!("{}_bg", self.stem))
.with_extension("wasm");

if self.mode.nodejs() {
let js_path = wasm_path.with_extension(extension);
let shim = self.generate_node_wasm_import(&self.module, &wasm_path);
Expand All @@ -583,9 +607,6 @@ impl Output {
.with_context(|_| format!("failed to write `{}`", ts_path.display()))?;
}

let wasm_bytes = self.module.emit_wasm()?;
fs::write(&wasm_path, wasm_bytes)
.with_context(|_| format!("failed to write `{}`", wasm_path.display()))?;
Ok(())
}

Expand Down
Loading

0 comments on commit 487289c

Please sign in to comment.