Component in wasmtime::component - Rust (original) (raw)

pub struct Component { /* private fields */ }

Available on crate features runtime and component-model only.

Expand description

A compiled WebAssembly Component.

This structure represents a compiled component that is ready to be instantiated. This owns a region of virtual memory which contains executable code compiled from a WebAssembly binary originally. This is the analog ofModule in the component embedding API.

A Component can be turned into anInstance through aLinker. Components are safe to share across threads. The compilation model of a component is the same as that ofa module which is to say:

§Components and Clone

Using clone on a Component is a cheap operation. It will not create an entirely new component, but rather just a new reference to the existing component. In other words it’s a shallow copy, not a deep copy.

§Examples

For example usage see the documentation of Module asComponent has the same high-level API.

Source§

Source

Available on crate features cranelift or winch only.

Compiles a new WebAssembly component from the in-memory list of bytes provided.

The bytes provided can either be the binary or text format of aWebAssembly component. Note that the text format requires the watfeature of this crate to be enabled. This API does not support streaming compilation.

This function will synchronously validate the entire component, including all core modules, and then compile all components, modules, etc., found within the provided bytes.

§Errors

This function may fail and return an error. Errors may include situations such as:

The error returned should contain full information about why compilation failed.

§Examples

The new function can be invoked with a in-memory array of bytes:

let component = Component::new(&engine, &wasm_bytes)?;

Or you can also pass in a string to be parsed as the wasm text format:

let component = Component::new(&engine, "(component (core module))")?;

Source

Available on crate feature std and (crate features cranelift or winch) only.

Compiles a new WebAssembly component from a wasm file on disk pointed to by file.

This is a convenience function for reading the contents of file on disk and then calling Component::new.

Source

Available on crate features cranelift or winch only.

Compiles a new WebAssembly component from the in-memory wasm image provided.

This function is the same as Component::new except that it does not accept the text format of WebAssembly. Even if the wat feature is enabled an error will be returned here if binary is the text format.

For more information on semantics and errors see Component::new.

Source

Source

Same as Module::deserialize_raw, but for components.

See Component::deserialize for additional information; this method works identically except that it will not create a copy of the provided memory but will use it directly.

§Unsafety

All of the safety notes from Component::deserialize apply here as well with the additional constraint that the code memory provide by memorylives for as long as the module and is nevery externally modified for the lifetime of the deserialized module.

Source

Available on crate feature std only.

Source

Returns the type of this component as a types::Component.

This method enables runtime introspection of the type of a component before instantiation, if necessary.

§Component types and Resources

An important point to note here is that the precise type of imports and exports of a component change when it is instantiated with respect to resources. For example a Component represents an un-instantiated component meaning that its imported resources are represented as abstract resource types. These abstract types are not equal to any other component’s types.

For example:

let a = Component::new(&engine, r#"
    (component (import "x" (type (sub resource))))
"#)?;
let b = Component::new(&engine, r#"
    (component (import "x" (type (sub resource))))
"#)?;

let (_, a_ty) = a.component_type().imports(&engine).next().unwrap();
let (_, b_ty) = b.component_type().imports(&engine).next().unwrap();

let a_ty = match a_ty {
    ComponentItem::Resource(ty) => ty,
    _ => unreachable!(),
};
let b_ty = match b_ty {
    ComponentItem::Resource(ty) => ty,
    _ => unreachable!(),
};
assert!(a_ty != b_ty);

Additionally, however, these abstract types are “substituted” during instantiation meaning that a component type will appear to have changed once it is instantiated.

// Here this component imports a resource and then exports it as-is
// which means that the export is equal to the import.
let a = Component::new(&engine, r#"
    (component
        (import "x" (type $x (sub resource)))
        (export "x" (type $x))
    )
"#)?;

let (_, import) = a.component_type().imports(&engine).next().unwrap();
let (_, export) = a.component_type().exports(&engine).next().unwrap();

let import = match import {
    ComponentItem::Resource(ty) => ty,
    _ => unreachable!(),
};
let export = match export {
    ComponentItem::Resource(ty) => ty,
    _ => unreachable!(),
};
assert_eq!(import, export);

// However after instantiation the resource type "changes"
let mut store = Store::new(&engine, ());
let mut linker = Linker::new(&engine);
linker.root().resource("x", ResourceType::host::<()>(), |_, _| Ok(()))?;
let instance = linker.instantiate(&mut store, &a)?;
let instance_ty = instance.get_resource(&mut store, "x").unwrap();

// Here `instance_ty` is not the same as either `import` or `export`,
// but it is equal to what we provided as an import.
assert!(instance_ty != import);
assert!(instance_ty != export);
assert!(instance_ty == ResourceType::host::<()>());

Finally, each instantiation of an exported resource from a component is considered “fresh” for all instantiations meaning that different instantiations will have different exported resource types:

let a = Component::new(&engine, r#"
    (component
        (type $x (resource (rep i32)))
        (export "x" (type $x))
    )
"#)?;

let mut store = Store::new(&engine, ());
let linker = Linker::new(&engine);
let instance1 = linker.instantiate(&mut store, &a)?;
let instance2 = linker.instantiate(&mut store, &a)?;

let x1 = instance1.get_resource(&mut store, "x").unwrap();
let x2 = instance2.get_resource(&mut store, "x").unwrap();

// Despite these two resources being the same export of the same
// component they come from two different instances meaning that their
// types will be unique.
assert!(x1 != x2);

Source

Source

Returns a summary of the resources required to instantiate thisComponent.

Note that when a component imports and instantiates another component or core module, we cannot determine ahead of time how many resources instantiating this component will require, and therefore this method will return None in these scenarios.

Potential uses of the returned information:

§Example
use wasmtime::{Config, Engine, component::Component};

let mut config = Config::new();
config.wasm_multi_memory(true);
config.wasm_component_model(true);
let engine = Engine::new(&config)?;

let component = Component::new(&engine, &r#"
    (component
        ;; Define a core module that uses two memories.
        (core module $m
            (memory 1)
            (memory 6)
        )

        ;; Instantiate that core module three times.
        (core instance <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mn>1</mn><mo stretchy="false">(</mo><mi>i</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi>i</mi><mi>a</mi><mi>t</mi><mi>e</mi><mo stretchy="false">(</mo><mi>m</mi><mi>o</mi><mi>d</mi><mi>u</mi><mi>l</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">i1 (instantiate (module </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mord">1</span><span class="mopen">(</span><span class="mord mathnormal">in</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord mathnormal">an</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span></span></span></span>m)))
        (core instance <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mn>2</mn><mo stretchy="false">(</mo><mi>i</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi>i</mi><mi>a</mi><mi>t</mi><mi>e</mi><mo stretchy="false">(</mo><mi>m</mi><mi>o</mi><mi>d</mi><mi>u</mi><mi>l</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">i2 (instantiate (module </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mord">2</span><span class="mopen">(</span><span class="mord mathnormal">in</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord mathnormal">an</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span></span></span></span>m)))
        (core instance <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mn>3</mn><mo stretchy="false">(</mo><mi>i</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi>i</mi><mi>a</mi><mi>t</mi><mi>e</mi><mo stretchy="false">(</mo><mi>m</mi><mi>o</mi><mi>d</mi><mi>u</mi><mi>l</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">i3 (instantiate (module </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mord">3</span><span class="mopen">(</span><span class="mord mathnormal">in</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord mathnormal">an</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span></span></span></span>m)))
    )
"#)?;

let resources = component.resources_required()
    .expect("this component does not import any core modules or instances");

// Instantiating the component will require allocating two memories per
// core instance, and there are three instances, so six total memories.
assert_eq!(resources.num_memories, 6);
assert_eq!(resources.max_initial_memory_size, Some(6));

// The component doesn't need any tables.
assert_eq!(resources.num_tables, 0);
assert_eq!(resources.max_initial_table_size, None);

Source

Returns the range, in the host’s address space, that this module’s compiled code resides at.

For more information seeModule::image_range.

Source

Force initialization of copy-on-write images to happen here-and-now instead of when they’re requested during first instantiation.

When copy-on-write memory initialization is enabled then Wasmtime will lazily create the initialization image for a component. This method can be used to explicitly dictate when this initialization happens.

Note that this largely only matters on Linux when memfd is used. Otherwise the copy-on-write image typically comes from disk and in that situation the creation of the image is trivial as the image is always sourced from disk. On Linux, though, when memfd is used a memfd is created and the initialization image is written to it.

Also note that this method is not required to be called, it’s available as a performance optimization if required but is otherwise handled automatically.

Source

Source

Looks up a specific export of this component by name optionally nested within the instance provided.

This method is primarily used to acquire a ComponentExportIndexwhich can be used with Instance when looking up exports. Export lookup with ComponentExportIndex can skip string lookups at runtime and instead use a more efficient index-based lookup.

This method takes a few arguments:

If the export is located then two values are returned: atypes::ComponentItem which enables introspection about the type of the export and a ComponentExportIndex. The index returned notably implements the InstanceExportLookup trait which enables using it with Instance::get_func for example.

The returned types::ComponentItem is more expensive to calculate than the ComponentExportIndex. If you only consume theComponentExportIndex, use the related methodSelf::get_export_index instead.

Instance has a corresponding methodInstance::get_export.

§Examples
use wasmtime::{Engine, Store};
use wasmtime::component::{Component, Linker};
use wasmtime::component::types::ComponentItem;

let engine = Engine::default();
let component = Component::new(
    &engine,
    r#"
        (component
            (core module $m
                (func (export "f"))
            )
            (core instance <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo stretchy="false">(</mo><mi>i</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>a</mi><mi>n</mi><mi>t</mi><mi>i</mi><mi>a</mi><mi>t</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">i (instantiate </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mopen">(</span><span class="mord mathnormal">in</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord mathnormal">an</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span></span></span></span>m))
            (func (export "f")
                (canon lift (core func $i "f")))
        )
    "#,
)?;

// Perform a lookup of the function "f" before instantiaton.
let (ty, export) = component.get_export(None, "f").unwrap();
assert!(matches!(ty, ComponentItem::ComponentFunc(_)));

// After instantiation use `export` to lookup the function in question
// which notably does not do a string lookup at runtime.
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(), ()>(&mut store, &export)?;
// ...

Source

§

§

§

§

§

§