liveBook · Manning

Wasm Component Model

As explained in Server-Side WebAssembly

The WebAssembly component model is a specification for composing WebAssembly components through typed interfaces, imports, exports, and resource interactions.

The Wasm Component Model wraps WebAssembly modules in a typed composition layer. WIT defines higher-level interfaces so guest and host applications can exchange strings, options, and other structured values without manually agreeing on linear-memory layouts. section 3.0

A component-based application separates responsibilities across several runtime pieces:

  • A WIT world describes the application interface, including imports and callable functions. section 3.0
  • The host implements imported functionality, such as a key-value store with get and set operations. section 3.4.2
  • Wasmtime configures and executes the component through an engine, store, component loader, and linker. section 3.4.2
  • The linker connects host implementations to guest imports, allowing the guest component to call host functionality. section 3.4.2

SmartCMS host

A Rust SmartCMS host generates bindings from smart_cms.wit, implements the kvstore interface over a HashMap, enables Wasmtime's wasm_component_model feature, creates runtime state, loads guest.wasm, links the key-value implementation, and invokes the guest's run function. section 3.4.2

Listing 3.6 The full main.rs file for our SmartCMS host
wasmtime::component::bindgen!({  #1
    path: "./smart_cms.wit",
    world: "app",
});

struct KeyValue {  #2
    mem: std::collections::HashMap<String, String>,   #2
}

impl component::smartcms::kvstore::Host for KeyValue {
    fn get(&mut self, key: String) -> 
    ➥Option<String> {  #3
        self.mem.get(&key).cloned()
    }

    fn set(&mut self, key: String, value: String) {
        self.mem.insert(key, value);
    }
}

struct State {  #4
    key_value: KeyValue,
}

fn main() {
    let mut config = wasmtime::Config::default();
    config.wasm_component_model(true);  #5

    let engine = wasmtime::Engine::new(&config).unwrap();

    let mut store = wasmtime::Store::new
    ➥(&engine, State { key_value: KeyValue { mem:
    ➥ std::collections::HashMap::new() } });  #6

    let component = wasmtime::component::
    ➥Component::from_file(&engine, "guest.wasm").unwrap();

    let mut linker = wasmtime::component::Linker::new(&engine);
    component::smartcms::kvstore::
    ➥add_to_linker(&mut linker, |state: &mut State| &mut
    ➥ state.key_value).unwrap();  #7

    let app = App::instantiate(&mut store, 
    ➥&component, &linker).unwrap();  #8

    println!("{:?}", app.call_run(&mut store)
    ➥.unwrap());  #9
}

The complete Rust host listing shows how generated bindings, host state, Wasmtime configuration, component loading, linking, and guest invocation fit together. section 3.4.2

How Server-Side WebAssembly covers it

How deep it goes
Builds from WIT's motivation to a working Wasmtime host, stopping short of broader component composition details.
Examples
Uses a SmartCMS key-value interface and a Rust host that loads guest.wasm and calls its run function.
What it assumes
Assumes familiarity with a basic Wasm module, then introduces higher-level types and host-guest wiring through WIT and Rust.
What you can do after
Build it from scratch by defining WIT interfaces, implementing host functions, configuring Wasmtime, linking components, and invoking guest code.
How it connects
Connects WIT, Wasm modules, host and guest applications, imports, generated bindings, Wasmtime, stores, engines, and linkers.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Server-Side WebAssembly. The section links point to the parts of the book it draws on.