Skip to main content

wasm_bindgen_cli/
wasm2es6js.rs

1use anyhow::{bail, Context, Error};
2use clap::Parser;
3use std::ffi::OsString;
4use std::fs;
5use std::path::PathBuf;
6
7#[derive(Parser, Debug)]
8#[command(
9    name = "wasm2es6js",
10    version,
11    about,
12    long_about = None,
13    after_help = "Note that this is not intended to produce a production-ready output module but rather\n\
14                  is intended purely as a temporary \"hack\" until it's standard in\n\
15                  bundlers for working with wasm. Use this program with care!",
16)]
17struct Args {
18    #[arg(long, short, value_name = "FILE", help = "File to place output in")]
19    output: Option<PathBuf>,
20    #[arg(long, value_name = "DIR", help = "Directory to place output in")]
21    out_dir: Option<PathBuf>,
22    #[arg(long, help = "Output a `*.d.ts` file next to the JS output")]
23    typescript: bool,
24    #[arg(long, help = "Inline the Wasm module using base64 encoding")]
25    base64: bool,
26    #[arg(
27        long,
28        value_name = "PATH",
29        help = "Load module by passing the PATH argument to `fetch()`"
30    )]
31    fetch: Option<String>,
32    input: PathBuf,
33}
34
35pub fn run_cli_with_args<I, T>(args: I) -> anyhow::Result<()>
36where
37    I: IntoIterator<Item = T>,
38    T: Into<OsString> + Clone,
39{
40    let args = match Args::try_parse_from(args) {
41        Ok(a) => a,
42        Err(e) => match e.kind() {
43            // Passing --version and --help should not result in a failure.
44            clap::error::ErrorKind::DisplayHelp | clap::error::ErrorKind::DisplayVersion => {
45                print!("{e}");
46                return Ok(());
47            }
48            _ => bail!(e),
49        },
50    };
51    rmain(args)
52}
53
54fn rmain(args: Args) -> anyhow::Result<()> {
55    let wasm = fs::read(&args.input)
56        .with_context(|| format!("failed to read `{}`", args.input.display()))?;
57
58    let object = wasm_bindgen_cli_support::wasm2es6js::Config::new()
59        .base64(args.base64)
60        .fetch(args.fetch.clone())
61        .generate(&wasm)?;
62
63    if args.typescript {
64        let ts = object.typescript()?;
65        write(&args, "d.ts", ts.as_bytes(), false)?;
66    }
67
68    let (js, wasm) = object.js_and_wasm()?;
69
70    write(&args, "js", js.as_bytes(), false)?;
71    if let Some(wasm) = wasm {
72        write(&args, "wasm", &wasm, false)?;
73    }
74    Ok(())
75}
76
77fn write(args: &Args, extension: &str, contents: &[u8], print_fallback: bool) -> Result<(), Error> {
78    if let Some(p) = &args.output {
79        let dst = p.with_extension(extension);
80        fs::write(&dst, contents)
81            .with_context(|| format!("failed to write `{}`", dst.display()))?;
82    } else if let Some(p) = &args.out_dir {
83        let filename = args.input.file_name().unwrap();
84        let dst = p.join(filename).with_extension(extension);
85        fs::write(&dst, contents)
86            .with_context(|| format!("failed to write `{}`", dst.display()))?;
87    } else if print_fallback {
88        println!("{}", String::from_utf8_lossy(contents))
89    }
90
91    Ok(())
92}