Support parsing the text format in wasmtime crate (#813)

* Support parsing the text format in `wasmtime` crate

This commit adds support to the `wasmtime::Module` type to parse the
text format. This is often quite convenient to support in testing or
tinkering with the runtime. Additionally the `wat` parser is pretty
lightweight and easy to add to builds, so it's relatively easy for us to
support as well!

The exact manner that this is now supported comes with a few updates to
the existing API:

* A new optional feature of the `wasmtime` crate, `wat`, has been added.
  This is enabled by default.
* The `Module::new` API now takes `impl AsRef<[u8]>` instead of just
  `&[u8]`, and when the `wat` feature is enabled it will attempt to
  interpret it either as a wasm binary or as the text format. Note that
  this check is quite cheap since you just check the first byte.
* A `Module::from_file` API was added as a convenience to parse a file
  from disk, allowing error messages for `*.wat` files on disk to be a
  bit nicer.
* APIs like `Module::new_unchecked` and `Module::validate` remain
  unchanged, they require the binary format to be called.

The intention here is to make this as convenient as possible for new
developers of the `wasmtime` crate. By changing the default behavior
though this has ramifications such as, for example, supporting the text
format implicitly through the C API now.

* Handle review comments

* Update more tests to avoid usage of `wat` crate

* Go back to unchecked for now in wasm_module_new

Looks like C# tests rely on this?
This commit is contained in:
Alex Crichton
2020-01-24 14:20:51 -06:00
committed by GitHub
parent 47d6db0be8
commit 16804673a2
15 changed files with 185 additions and 168 deletions

View File

@@ -172,6 +172,12 @@ jobs:
- run: cargo fetch --locked - run: cargo fetch --locked
- run: cargo fetch --locked --manifest-path crates/test-programs/wasi-tests/Cargo.toml - run: cargo fetch --locked --manifest-path crates/test-programs/wasi-tests/Cargo.toml
# Build some various feature combinations
- run: cargo build --manifest-path crates/api/Cargo.toml --no-default-features
- run: cargo build --manifest-path crates/api/Cargo.toml --features wat
- run: cargo build --manifest-path crates/api/Cargo.toml --features lightbeam
if: matrix.rust == 'nightly'
# Build and test all features except for lightbeam # Build and test all features except for lightbeam
- run: cargo test --features test_programs --all --exclude lightbeam -- --nocapture - run: cargo test --features test_programs --all --exclude lightbeam -- --nocapture
env: env:

View File

@@ -21,6 +21,7 @@ cfg-if = "0.1.9"
backtrace = "0.3.42" backtrace = "0.3.42"
rustc-demangle = "0.1.16" rustc-demangle = "0.1.16"
lazy_static = "1.4" lazy_static = "1.4"
wat = { version = "1.0.7", optional = true }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3.7" winapi = "0.3.7"
@@ -37,6 +38,8 @@ wat = "1.0"
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }
[features] [features]
default = ['wat']
# Enables experimental support for the lightbeam codegen backend, an alternative # Enables experimental support for the lightbeam codegen backend, an alternative
# to cranelift. Requires Nightly Rust currently, and this is not enabled by # to cranelift. Requires Nightly Rust currently, and this is not enabled by
# default. # default.

View File

@@ -36,9 +36,8 @@ const WAT: &str = r#"
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
// Load our WebAssembly (parsed WAT in our case), and then load it into a // Load our WebAssembly (parsed WAT in our case), and then load it into a
// `Module` which is attached to a `Store` cache. // `Module` which is attached to a `Store` cache.
let wasm = wat::parse_str(WAT)?;
let store = Store::default(); let store = Store::default();
let module = Module::new(&store, &wasm)?; let module = Module::new(&store, WAT)?;
// Find index of the `gcd` export. // Find index of the `gcd` export.
let gcd_index = module let gcd_index = module

View File

@@ -21,21 +21,15 @@ fn main() -> Result<()> {
println!("Initializing..."); println!("Initializing...");
let store = Store::default(); let store = Store::default();
// Next upload the `*.wasm` binary file, which in this case we're going to // Compile the wasm binary into an in-memory instance of a `Module`.
// be parsing an inline text format into a binary. println!("Compiling module...");
println!("Loading binary..."); let wat = r#"
let binary = wat::parse_str(
r#"
(module (module
(func $hello (import "" "hello")) (func $hello (import "" "hello"))
(func (export "run") (call $hello)) (func (export "run") (call $hello))
) )
"#, "#;
)?; let module = Module::new(&store, wat).context("> Error compiling module!")?;
// Compiler the `*.wasm` binary into an in-memory instance of a `Module`.
println!("Compiling module...");
let module = Module::new(&store, &binary).context("> Error compiling module!")?;
// Here we handle the imports of the module, which in this case is our // Here we handle the imports of the module, which in this case is our
// `HelloCallback` type and its associated implementation of `Callback. // `HelloCallback` type and its associated implementation of `Callback.

View File

@@ -66,8 +66,7 @@ fn main() -> Result<(), Error> {
// Load binary. // Load binary.
println!("Loading binary..."); println!("Loading binary...");
let binary = wat::parse_str( let wat = r#"
r#"
(module (module
(memory (export "memory") 2 3) (memory (export "memory") 2 3)
@@ -81,12 +80,11 @@ fn main() -> Result<(), Error> {
(data (i32.const 0x1000) "\01\02\03\04") (data (i32.const 0x1000) "\01\02\03\04")
) )
"#, "#;
)?;
// Compile. // Compile.
println!("Compiling module..."); println!("Compiling module...");
let module = Module::new(&store, &binary).context("> Error compiling module!")?; let module = Module::new(&store, &wat).context("> Error compiling module!")?;
// Instantiate. // Instantiate.
println!("Instantiating module..."); println!("Instantiating module...");

View File

@@ -48,13 +48,9 @@ fn main() -> Result<()> {
let engine = Engine::new(Config::new().wasm_multi_value(true)); let engine = Engine::new(Config::new().wasm_multi_value(true));
let store = Store::new(&engine); let store = Store::new(&engine);
// Load binary.
println!("Loading binary...");
let binary = wat::parse_str(WAT)?;
// Compile. // Compile.
println!("Compiling module..."); println!("Compiling module...");
let module = Module::new(&store, &binary).context("Error compiling module!")?; let module = Module::new(&store, WAT).context("Error compiling module!")?;
// Create external print functions. // Create external print functions.
println!("Creating callback..."); println!("Creating callback...");

View File

@@ -30,7 +30,7 @@ use wasmtime_runtime::Export;
/// # fn main () -> Result<(), Box<dyn std::error::Error>> { /// # fn main () -> Result<(), Box<dyn std::error::Error>> {
/// // Simple module that imports our host function ("times_two") and re-exports /// // Simple module that imports our host function ("times_two") and re-exports
/// // it as "run". /// // it as "run".
/// let binary = wat::parse_str(r#" /// let wat = r#"
/// (module /// (module
/// (func $times_two (import "" "times_two") (param i32) (result i32)) /// (func $times_two (import "" "times_two") (param i32) (result i32))
/// (func /// (func
@@ -40,11 +40,11 @@ use wasmtime_runtime::Export;
/// (local.get 0) /// (local.get 0)
/// (call $times_two)) /// (call $times_two))
/// ) /// )
/// "#)?; /// "#;
/// ///
/// // Initialise environment and our module. /// // Initialise environment and our module.
/// let store = wasmtime::Store::default(); /// let store = wasmtime::Store::default();
/// let module = wasmtime::Module::new(&store, &binary)?; /// let module = wasmtime::Module::new(&store, wat)?;
/// ///
/// // Define the type of the function we're going to call. /// // Define the type of the function we're going to call.
/// let times_two_type = wasmtime::FuncType::new( /// let times_two_type = wasmtime::FuncType::new(

View File

@@ -7,6 +7,7 @@ use anyhow::{Error, Result};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::Path;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use wasmparser::{ use wasmparser::{
@@ -107,15 +108,22 @@ lazy_static! {
} }
impl Module { impl Module {
/// Creates a new WebAssembly `Module` from the given in-memory `binary` /// Creates a new WebAssembly `Module` from the given in-memory `bytes`.
/// data.
/// ///
/// The `binary` data provided must be a [binary-encoded][binary] /// The `bytes` provided must be in one of two formats:
/// WebAssembly module. This means that the data for the wasm module must be ///
/// loaded in-memory if it's present elsewhere, for example on disk. /// * It can be a [binary-encoded][binary] WebAssembly module. This
/// Additionally this requires that the entire binary is loaded into memory /// is always supported.
/// all at once, this API does not support streaming compilation of a /// * It may also be a [text-encoded][text] instance of the WebAssembly
/// module. /// text format. This is only supported when the `wat` feature of this
/// crate is enabled. If this is supplied then the text format will be
/// parsed before validation. Note that the `wat` feature is enabled by
/// default.
///
/// The data for the wasm module must be loaded in-memory if it's present
/// elsewhere, for example on disk. This requires that the entire binary is
/// loaded into memory all at once, this API does not support streaming
/// compilation of a module.
/// ///
/// The WebAssembly binary will be decoded and validated. It will also be /// The WebAssembly binary will be decoded and validated. It will also be
/// compiled according to the configuration of the provided `store` and /// compiled according to the configuration of the provided `store` and
@@ -137,34 +145,69 @@ impl Module {
/// example too many locals) /// example too many locals)
/// * The wasm binary may use features that are not enabled in the /// * The wasm binary may use features that are not enabled in the
/// configuration of `store` /// configuration of `store`
/// * If the `wat` feature is enabled and the input is text, then it may be
/// rejected if it fails to parse.
/// ///
/// The error returned should contain full information about why module /// The error returned should contain full information about why module
/// creation failed if one is returned. /// creation failed if one is returned.
/// ///
/// [binary]: https://webassembly.github.io/spec/core/binary/index.html /// [binary]: https://webassembly.github.io/spec/core/binary/index.html
pub fn new(store: &Store, binary: &[u8]) -> Result<Module> { /// [text]: https://webassembly.github.io/spec/core/text/index.html
Module::validate(store, binary)?; pub fn new(store: &Store, bytes: impl AsRef<[u8]>) -> Result<Module> {
unsafe { Module::new_unchecked(store, binary) } #[cfg(feature = "wat")]
let bytes = wat::parse_bytes(bytes.as_ref())?;
Module::from_binary(store, bytes.as_ref())
} }
/// Creates a new WebAssembly `Module` from the given in-memory `binary` /// Creates a new WebAssembly `Module` from the given in-memory `binary`
/// data. The provided `name` will be used in traps/backtrace details. /// data. The provided `name` will be used in traps/backtrace details.
/// ///
/// See [`Module::new`] for other details. /// See [`Module::new`] for other details.
pub fn new_with_name(store: &Store, binary: &[u8], name: &str) -> Result<Module> { pub fn new_with_name(store: &Store, bytes: impl AsRef<[u8]>, name: &str) -> Result<Module> {
let mut module = Module::new(store, binary)?; let mut module = Module::new(store, bytes.as_ref())?;
let inner = Rc::get_mut(&mut module.inner).unwrap(); let inner = Rc::get_mut(&mut module.inner).unwrap();
Arc::get_mut(&mut inner.names).unwrap().module_name = Some(name.to_string()); Arc::get_mut(&mut inner.names).unwrap().module_name = Some(name.to_string());
Ok(module) Ok(module)
} }
/// Creates a new WebAssembly `Module` from the contents of the given
/// `file` on disk.
///
/// This is a convenience function that will read the `file` provided and
/// pass the bytes to the [`Module::new`] function. For more information
/// see [`Module::new`]
pub fn from_file(store: &Store, file: impl AsRef<Path>) -> Result<Module> {
#[cfg(feature = "wat")]
let wasm = wat::parse_file(file)?;
#[cfg(not(feature = "wat"))]
let wasm = std::fs::read(file)?;
Module::new(store, &wasm)
}
/// Creates a new WebAssembly `Module` from the given in-memory `binary`
/// data.
///
/// This is similar to [`Module::new`] except that it requires that the
/// `binary` input is a WebAssembly binary, the text format is not supported
/// by this function. It's generally recommended to use [`Module::new`],
/// but if it's required to not support the text format this function can be
/// used instead.
pub fn from_binary(store: &Store, binary: &[u8]) -> Result<Module> {
Module::validate(store, binary)?;
// Note that the call to `validate` here should be ok because we
// previously validated the binary, meaning we're guaranteed to pass a
// valid binary for `store`.
unsafe { Module::from_binary_unchecked(store, binary) }
}
/// Creates a new WebAssembly `Module` from the given in-memory `binary` /// Creates a new WebAssembly `Module` from the given in-memory `binary`
/// data, skipping validation and asserting that `binary` is a valid /// data, skipping validation and asserting that `binary` is a valid
/// WebAssembly module. /// WebAssembly module.
/// ///
/// This function is the same as [`Module::new`] except that it skips the /// This function is the same as [`Module::new`] except that it skips the
/// call to [`Module::validate`]. This means that the WebAssembly binary is /// call to [`Module::validate`] and it does not support the text format of
/// not validated for correctness and it is simply assumed as valid. /// WebAssembly. The WebAssembly binary is not validated for
/// correctness and it is simply assumed as valid.
/// ///
/// For more information about creation of a module and the `store` argument /// For more information about creation of a module and the `store` argument
/// see the documentation of [`Module::new`]. /// see the documentation of [`Module::new`].
@@ -184,7 +227,7 @@ impl Module {
/// While this assumes that the binary is valid it still needs to actually /// While this assumes that the binary is valid it still needs to actually
/// be somewhat valid for decoding purposes, and the basics of decoding can /// be somewhat valid for decoding purposes, and the basics of decoding can
/// still fail. /// still fail.
pub unsafe fn new_unchecked(store: &Store, binary: &[u8]) -> Result<Module> { pub unsafe fn from_binary_unchecked(store: &Store, binary: &[u8]) -> Result<Module> {
let mut ret = Module::compile(store, binary)?; let mut ret = Module::compile(store, binary)?;
ret.read_imports_and_exports(binary)?; ret.read_imports_and_exports(binary)?;
Ok(ret) Ok(ret)
@@ -194,10 +237,11 @@ impl Module {
/// configuration in `store`. /// configuration in `store`.
/// ///
/// This function will perform a speedy validation of the `binary` input /// This function will perform a speedy validation of the `binary` input
/// WebAssembly module (which is in [binary form][binary]) and return either /// WebAssembly module (which is in [binary form][binary], the text format
/// `Ok` or `Err` depending on the results of validation. The `store` /// is not accepted by this function) and return either `Ok` or `Err`
/// argument indicates configuration for WebAssembly features, for example, /// depending on the results of validation. The `store` argument indicates
/// which are used to indicate what should be valid and what shouldn't be. /// configuration for WebAssembly features, for example, which are used to
/// indicate what should be valid and what shouldn't be.
/// ///
/// Validation automatically happens as part of [`Module::new`], but is a /// Validation automatically happens as part of [`Module::new`], but is a
/// requirement for [`Module::new_unchecked`] to be safe. /// requirement for [`Module::new_unchecked`] to be safe.

View File

@@ -38,8 +38,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> {
} }
let store = Store::default(); let store = Store::default();
let wasm = wat::parse_str(WAT)?; let module = Module::new(&store, WAT)?;
let module = Module::new(&store, &wasm)?;
let imports = [ let imports = [
Func::new( Func::new(

View File

@@ -32,8 +32,7 @@ fn test_import_calling_export() {
} }
let store = Store::default(); let store = Store::default();
let wasm = wat::parse_str(WAT).unwrap(); let module = Module::new(&store, WAT).expect("failed to create module");
let module = Module::new(&store, &wasm).expect("failed to create module");
let callback = Rc::new(Callback { let callback = Rc::new(Callback {
other: RefCell::new(None), other: RefCell::new(None),

View File

@@ -5,17 +5,15 @@ use wasmtime::*;
fn test_invoke_func_via_table() -> Result<()> { fn test_invoke_func_via_table() -> Result<()> {
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module (module
(func $f (result i64) (i64.const 42)) (func $f (result i64) (i64.const 42))
(table (export "table") 1 1 anyfunc) (table (export "table") 1 1 anyfunc)
(elem (i32.const 0) $f) (elem (i32.const 0) $f)
) )
"#, "#;
)?; let module = Module::new(&store, wat).context("> Error compiling module!")?;
let module = Module::new(&store, &binary).context("> Error compiling module!")?;
let instance = Instance::new(&module, &[]).context("> Error instantiating module!")?; let instance = Instance::new(&module, &[]).context("> Error instantiating module!")?;
let f = instance let f = instance

View File

@@ -3,15 +3,13 @@ use wasmtime::*;
#[test] #[test]
fn test_module_no_name() -> anyhow::Result<()> { fn test_module_no_name() -> anyhow::Result<()> {
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module (module
(func (export "run") (nop)) (func (export "run") (nop))
) )
"#, "#;
)?;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
assert_eq!(module.name(), None); assert_eq!(module.name(), None);
Ok(()) Ok(())
@@ -20,18 +18,16 @@ fn test_module_no_name() -> anyhow::Result<()> {
#[test] #[test]
fn test_module_name() -> anyhow::Result<()> { fn test_module_name() -> anyhow::Result<()> {
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module $from_name_section (module $from_name_section
(func (export "run") (nop)) (func (export "run") (nop))
) )
"#, "#;
)?;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
assert_eq!(module.name(), Some("from_name_section")); assert_eq!(module.name(), Some("from_name_section"));
let module = Module::new_with_name(&store, &binary, "override")?; let module = Module::new_with_name(&store, wat, "override")?;
assert_eq!(module.name(), Some("override")); assert_eq!(module.name(), Some("override"));
Ok(()) Ok(())

View File

@@ -13,16 +13,14 @@ fn test_trap_return() -> Result<()> {
} }
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module (module
(func $hello (import "" "hello")) (func $hello (import "" "hello"))
(func (export "run") (call $hello)) (func (export "run") (call $hello))
) )
"#, "#;
)?;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
let hello_type = FuncType::new(Box::new([]), Box::new([])); let hello_type = FuncType::new(Box::new([]), Box::new([]));
let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback)); let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback));
@@ -41,16 +39,14 @@ fn test_trap_return() -> Result<()> {
#[test] #[test]
fn test_trap_trace() -> Result<()> { fn test_trap_trace() -> Result<()> {
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module $hello_mod (module $hello_mod
(func (export "run") (call $hello)) (func (export "run") (call $hello))
(func $hello (unreachable)) (func $hello (unreachable))
) )
"#, "#;
)?;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?; let instance = Instance::new(&module, &[])?;
let run_func = instance.exports()[0] let run_func = instance.exports()[0]
.func() .func()
@@ -82,20 +78,18 @@ fn test_trap_trace_cb() -> Result<()> {
} }
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module $hello_mod (module $hello_mod
(import "" "throw" (func $throw)) (import "" "throw" (func $throw))
(func (export "run") (call $hello)) (func (export "run") (call $hello))
(func $hello (call $throw)) (func $hello (call $throw))
) )
"#, "#;
)?;
let fn_type = FuncType::new(Box::new([]), Box::new([])); let fn_type = FuncType::new(Box::new([]), Box::new([]));
let fn_func = Func::new(&store, fn_type, Rc::new(ThrowCallback)); let fn_func = Func::new(&store, fn_type, Rc::new(ThrowCallback));
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[fn_func.into()])?; let instance = Instance::new(&module, &[fn_func.into()])?;
let run_func = instance.exports()[0] let run_func = instance.exports()[0]
.func() .func()
@@ -117,15 +111,13 @@ fn test_trap_trace_cb() -> Result<()> {
#[test] #[test]
fn test_trap_stack_overflow() -> Result<()> { fn test_trap_stack_overflow() -> Result<()> {
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module $rec_mod (module $rec_mod
(func $run (export "run") (call $run)) (func $run (export "run") (call $run))
) )
"#, "#;
)?;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?; let instance = Instance::new(&module, &[])?;
let run_func = instance.exports()[0] let run_func = instance.exports()[0]
.func() .func()
@@ -148,18 +140,16 @@ fn test_trap_stack_overflow() -> Result<()> {
#[test] #[test]
fn trap_display_pretty() -> Result<()> { fn trap_display_pretty() -> Result<()> {
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module $m (module $m
(func $die unreachable) (func $die unreachable)
(func call $die) (func call $die)
(func $foo call 1) (func $foo call 1)
(func (export "bar") call $foo) (func (export "bar") call $foo)
) )
"#, "#;
)?;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?; let instance = Instance::new(&module, &[])?;
let run_func = instance.exports()[0] let run_func = instance.exports()[0]
.func() .func()
@@ -183,31 +173,27 @@ wasm backtrace:
#[test] #[test]
fn trap_display_multi_module() -> Result<()> { fn trap_display_multi_module() -> Result<()> {
let store = Store::default(); let store = Store::default();
let binary = wat::parse_str( let wat = r#"
r#"
(module $a (module $a
(func $die unreachable) (func $die unreachable)
(func call $die) (func call $die)
(func $foo call 1) (func $foo call 1)
(func (export "bar") call $foo) (func (export "bar") call $foo)
) )
"#, "#;
)?;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?; let instance = Instance::new(&module, &[])?;
let bar = instance.exports()[0].clone(); let bar = instance.exports()[0].clone();
let binary = wat::parse_str( let wat = r#"
r#"
(module $b (module $b
(import "" "" (func $bar)) (import "" "" (func $bar))
(func $middle call $bar) (func $middle call $bar)
(func (export "bar2") call $middle) (func (export "bar2") call $middle)
) )
"#, "#;
)?; let module = Module::new(&store, wat)?;
let module = Module::new(&store, &binary)?;
let instance = Instance::new(&module, &[bar])?; let instance = Instance::new(&module, &[bar])?;
let bar2 = instance.exports()[0] let bar2 = instance.exports()[0]
.func() .func()

View File

@@ -787,7 +787,10 @@ pub unsafe extern "C" fn wasm_module_new(
) -> *mut wasm_module_t { ) -> *mut wasm_module_t {
let binary = (*binary).as_slice(); let binary = (*binary).as_slice();
let store = &(*store).store.borrow(); let store = &(*store).store.borrow();
let module = Module::new_unchecked(store, binary).expect("module"); let module = match Module::from_binary_unchecked(store, binary) {
Ok(module) => module,
Err(_) => return ptr::null_mut(),
};
let imports = module let imports = module
.imports() .imports()
.iter() .iter()

View File

@@ -107,8 +107,7 @@ mod tests {
fn test_custom_signal_handler_single_instance() -> Result<()> { fn test_custom_signal_handler_single_instance() -> Result<()> {
let engine = Engine::new(&Config::default()); let engine = Engine::new(&Config::default());
let store = Store::new(&engine); let store = Store::new(&engine);
let data = wat::parse_str(WAT1)?; let module = Module::new(&store, WAT1)?;
let module = Module::new(&store, &data)?;
let instance = Instance::new(&module, &[])?; let instance = Instance::new(&module, &[])?;
let (base, length) = set_up_memory(&instance); let (base, length) = set_up_memory(&instance);
@@ -166,8 +165,7 @@ mod tests {
fn test_custom_signal_handler_multiple_instances() -> Result<()> { fn test_custom_signal_handler_multiple_instances() -> Result<()> {
let engine = Engine::new(&Config::default()); let engine = Engine::new(&Config::default());
let store = Store::new(&engine); let store = Store::new(&engine);
let data = wat::parse_str(WAT1)?; let module = Module::new(&store, WAT1)?;
let module = Module::new(&store, &data)?;
// Set up multiple instances // Set up multiple instances
@@ -261,8 +259,7 @@ mod tests {
let store = Store::new(&engine); let store = Store::new(&engine);
// instance1 which defines 'read' // instance1 which defines 'read'
let data1 = wat::parse_str(WAT1)?; let module1 = Module::new(&store, WAT1)?;
let module1 = Module::new(&store, &data1)?;
let instance1 = Instance::new(&module1, &[])?; let instance1 = Instance::new(&module1, &[])?;
let (base1, length1) = set_up_memory(&instance1); let (base1, length1) = set_up_memory(&instance1);
unsafe { unsafe {
@@ -277,8 +274,7 @@ mod tests {
let instance1_read = instance1_exports[0].clone(); let instance1_read = instance1_exports[0].clone();
// instance2 wich calls 'instance1.read' // instance2 wich calls 'instance1.read'
let data2 = wat::parse_str(WAT2)?; let module2 = Module::new(&store, WAT2)?;
let module2 = Module::new(&store, &data2)?;
let instance2 = Instance::new(&module2, &[instance1_read])?; let instance2 = Instance::new(&module2, &[instance1_read])?;
// since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle // since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle
// SIGSEGV originating from within the memory of instance1 // SIGSEGV originating from within the memory of instance1