mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-25 14:12:13 +00:00
Add first-class support for binary crates (#1843)
* autodiscover an exported `main` if possible this allows for first-class support of binary crates * wrap `main` to zero out arguments and suppress return value * add test for bin crate support * process only the export of the generated main wrapper * skip most of `export` since only one line of that is needed
This commit is contained in:
parent
b29c110d01
commit
79cf4f6198
@ -512,6 +512,10 @@ pub fn process(
|
|||||||
cx.program(program)?;
|
cx.program(program)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !cx.start_found {
|
||||||
|
cx.discover_main()?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(standard) = cx.module.customs.delete_typed::<ast::WebidlBindings>() {
|
if let Some(standard) = cx.module.customs.delete_typed::<ast::WebidlBindings>() {
|
||||||
cx.standard(&standard)?;
|
cx.standard(&standard)?;
|
||||||
}
|
}
|
||||||
@ -623,6 +627,44 @@ impl<'a> Context<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discover a function `main(i32, i32) -> i32` and, if it exists, make that function run at module start.
|
||||||
|
fn discover_main(&mut self) -> Result<(), Error> {
|
||||||
|
// find a `main(i32, i32) -> i32`
|
||||||
|
let main_id = self
|
||||||
|
.module
|
||||||
|
.functions()
|
||||||
|
.find(|x| {
|
||||||
|
use walrus::ValType::I32;
|
||||||
|
// name has to be `main`
|
||||||
|
let name_matches = x.name.as_ref().map_or(false, |x| x == "main");
|
||||||
|
// type has to be `(i32, i32) -> i32`
|
||||||
|
let ty = self.module.types.get(x.ty());
|
||||||
|
let type_matches = ty.params() == [I32, I32] && ty.results() == [I32];
|
||||||
|
name_matches && type_matches
|
||||||
|
})
|
||||||
|
.map(|x| x.id());
|
||||||
|
let main_id = match main_id {
|
||||||
|
Some(x) => x,
|
||||||
|
None => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// build a wrapper to zero out the arguments and ignore the return value
|
||||||
|
let mut wrapper = walrus::FunctionBuilder::new(&mut self.module.types, &[], &[]);
|
||||||
|
wrapper
|
||||||
|
.func_body()
|
||||||
|
.i32_const(0)
|
||||||
|
.i32_const(0)
|
||||||
|
.call(main_id)
|
||||||
|
.drop()
|
||||||
|
.return_();
|
||||||
|
let wrapper = wrapper.finish(vec![], &mut self.module.funcs);
|
||||||
|
|
||||||
|
// call that wrapper when the module starts
|
||||||
|
self.add_start_function(wrapper)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that the `start` function for this module calls the
|
// Ensure that the `start` function for this module calls the
|
||||||
// `__wbindgen_init_anyref_table` function. This'll ensure that all
|
// `__wbindgen_init_anyref_table` function. This'll ensure that all
|
||||||
// instances of this module have the initial slots of the anyref table
|
// instances of this module have the initial slots of the anyref table
|
||||||
|
@ -151,3 +151,49 @@ fn one_export_works() {
|
|||||||
.wasm_bindgen("");
|
.wasm_bindgen("");
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bin_crate_works() {
|
||||||
|
let (mut cmd, out_dir) = Project::new("bin_crate_works")
|
||||||
|
.file(
|
||||||
|
"src/main.rs",
|
||||||
|
r#"
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(js_namespace = console)]
|
||||||
|
fn log(data: &str);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
log("hello, world");
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
&format!(
|
||||||
|
"
|
||||||
|
[package]
|
||||||
|
name = \"bin_crate_works\"
|
||||||
|
authors = []
|
||||||
|
version = \"1.0.0\"
|
||||||
|
edition = '2018'
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasm-bindgen = {{ path = '{}' }}
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
",
|
||||||
|
repo_root().display(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.wasm_bindgen("--target nodejs");
|
||||||
|
cmd.assert().success();
|
||||||
|
Command::new("node")
|
||||||
|
.arg("bin_crate_works.js")
|
||||||
|
.current_dir(out_dir)
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("hello, world\n");
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user