wasmtime_cli/commands/
wast.rs

1//! The module that implements the `wasmtime wast` command.
2
3use anyhow::{Context as _, Result};
4use clap::Parser;
5use std::path::PathBuf;
6use wasmtime::Engine;
7use wasmtime_cli_flags::CommonOptions;
8use wasmtime_wast::{SpectestConfig, WastContext};
9
10/// Runs a WebAssembly test script file
11#[derive(Parser)]
12pub struct WastCommand {
13    #[command(flatten)]
14    common: CommonOptions,
15
16    /// The path of the WebAssembly test script to run
17    #[arg(required = true, value_name = "SCRIPT_FILE")]
18    scripts: Vec<PathBuf>,
19
20    /// Whether or not to generate DWARF debugging information in text-to-binary
21    /// transformations to show line numbers in backtraces.
22    #[arg(long, require_equals = true, value_name = "true|false")]
23    generate_dwarf: Option<Option<bool>>,
24
25    /// Saves precompiled versions of modules to this path instead of running
26    /// tests.
27    #[arg(long)]
28    precompile_save: Option<PathBuf>,
29
30    /// Load precompiled modules from the specified directory instead of
31    /// compiling natively.
32    #[arg(long)]
33    precompile_load: Option<PathBuf>,
34}
35
36impl WastCommand {
37    /// Executes the command.
38    pub fn execute(mut self) -> Result<()> {
39        self.common.init_logging()?;
40
41        let mut config = self.common.config(None)?;
42        config.async_support(true);
43        let engine = Engine::new(&config)?;
44        let mut wast_context = WastContext::new(&engine, wasmtime_wast::Async::Yes, move |store| {
45            if let Some(fuel) = self.common.wasm.fuel {
46                store.set_fuel(fuel).unwrap();
47            }
48            if let Some(true) = self.common.wasm.epoch_interruption {
49                store.epoch_deadline_trap();
50                store.set_epoch_deadline(1);
51            }
52        });
53
54        wast_context.generate_dwarf(optional_flag_with_default(self.generate_dwarf, true));
55        wast_context
56            .register_spectest(&SpectestConfig {
57                use_shared_memory: true,
58                suppress_prints: false,
59            })
60            .expect("error instantiating \"spectest\"");
61
62        if let Some(path) = &self.precompile_save {
63            wast_context.precompile_save(path);
64        }
65        if let Some(path) = &self.precompile_load {
66            wast_context.precompile_load(path);
67        }
68
69        for script in self.scripts.iter() {
70            wast_context
71                .run_file(script)
72                .with_context(|| format!("failed to run script file '{}'", script.display()))?;
73        }
74
75        Ok(())
76    }
77}
78
79fn optional_flag_with_default(flag: Option<Option<bool>>, default: bool) -> bool {
80    match flag {
81        None => default,
82        Some(None) => true,
83        Some(Some(val)) => val,
84    }
85}