mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-25 06:02: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)?;
|
||||
}
|
||||
|
||||
if !cx.start_found {
|
||||
cx.discover_main()?;
|
||||
}
|
||||
|
||||
if let Some(standard) = cx.module.customs.delete_typed::<ast::WebidlBindings>() {
|
||||
cx.standard(&standard)?;
|
||||
}
|
||||
@ -623,6 +627,44 @@ impl<'a> Context<'a> {
|
||||
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
|
||||
// `__wbindgen_init_anyref_table` function. This'll ensure that all
|
||||
// instances of this module have the initial slots of the anyref table
|
||||
|
@ -151,3 +151,49 @@ fn one_export_works() {
|
||||
.wasm_bindgen("");
|
||||
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