From 76849ef1fd9783904a8976c60b804462ec8ab745 Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 28 Aug 2024 12:32:58 -0500 Subject: [PATCH 1/4] Consistent note format --- .../src/creating-and-consuming/composing.md | 4 +- .../src/creating-and-consuming/running.md | 2 +- component-model/src/design/wit.md | 50 ++- component-model/src/language-support.md | 10 +- component-model/src/language-support/c.md | 2 +- .../src/language-support/python.md | 4 +- component-model/src/language-support/rust.md | 284 +++++++++--------- component-model/src/runtimes/wasmtime.md | 2 +- component-model/src/tutorial.md | 58 ++-- 9 files changed, 208 insertions(+), 208 deletions(-) diff --git a/component-model/src/creating-and-consuming/composing.md b/component-model/src/creating-and-consuming/composing.md index 5d7365a..e9f8c2d 100644 --- a/component-model/src/creating-and-consuming/composing.md +++ b/component-model/src/creating-and-consuming/composing.md @@ -2,7 +2,7 @@ Because the WebAssembly component model packages code in a portable binary format, and provides machine-readable interfaces in [WIT](../design/wit.md) with a standardised ABI (Application Binary Interface), it enables applications and components to work together, no matter what languages they were originally written in. In the same way that, for example, a Rust package (crate) can be compiled together with other Rust code to create a higher-level library or an application, a Wasm component can be linked with other components. -> Component model interoperation is more convenient and expressive than language-specific foreign function interfaces. A typical C FFI involves language-specific types, so it is not possible to link between arbitrary languages without at least some C-language wrapping or conversion. The component model, by contrast, provides a common way of expressing interfaces, and a standard binary representation of those interfaces. So if an import and an export have the same shape, they fit together directly. +> ⓘ Component model interoperation is more convenient and expressive than language-specific foreign function interfaces. A typical C FFI involves language-specific types, so it is not possible to link between arbitrary languages without at least some C-language wrapping or conversion. The component model, by contrast, provides a common way of expressing interfaces, and a standard binary representation of those interfaces. So if an import and an export have the same shape, they fit together directly. ## What is composition? @@ -61,7 +61,7 @@ wasm-tools compose path/to/component.wasm -d path/to/dep1.wasm -d path/to/dep2.w Here `component.wasm` is the component that imports interfaces from `dep1.wasm` and `dep2.wasm`, which export them. The composed component, with those dependencies satisfied and tucked away inside it, is saved to `composed.wasm`. -> This syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'll need to use a [configuration file](https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wasm-compose/CONFIG.md). (Or you can compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. This doesn't scale to lots of transitive dependencies though!) +> ⓘ This syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'll need to use a [configuration file](https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wasm-compose/CONFIG.md). (Or you can compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. This doesn't scale to lots of transitive dependencies though!) For full information about `wasm-tools compose` including how to configure more advanced scenarios, see [the `wasm-tools compose` documentation](https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-compose). diff --git a/component-model/src/creating-and-consuming/running.md b/component-model/src/creating-and-consuming/running.md index eb27bda..97b6171 100644 --- a/component-model/src/creating-and-consuming/running.md +++ b/component-model/src/creating-and-consuming/running.md @@ -2,7 +2,7 @@ You can "run" a component by calling one of its exports. In some cases, this requires a custom host. For "command" components, though, you can use the `wasmtime` command line. This can be a convenient tool for testing components and exploring the component model. Other runtimes are also available - see the "Runtimes" section of the sidebar for more info. -> A "command" component is one that exports the `wasi:cli/run` interface, and imports only interfaces listed in the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit). +> ⓘ A "command" component is one that exports the `wasi:cli/run` interface, and imports only interfaces listed in the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit). You must use a recent version of `wasmtime` ([`v14.0.0` or greater](https://github.com/bytecodealliance/wasmtime/releases)), as earlier releases of the `wasmtime` command line do not include component model support. diff --git a/component-model/src/design/wit.md b/component-model/src/design/wit.md index 7cfd35e..c349e7d 100644 --- a/component-model/src/design/wit.md +++ b/component-model/src/design/wit.md @@ -33,7 +33,7 @@ The WIT (Wasm Interface Type) language is used to define Component Model [interf A WIT file contains one or more **interfaces** or **worlds**. An interface or world can define **types** and/or **functions**. -> Types and functions can't be defined outside of interfaces or worlds. +> ⓘ Types and functions can't be defined outside of interfaces or worlds. A file may optionally start with a **package** declaration. @@ -91,18 +91,18 @@ WIT defines the following primitive types: | Identifier | Description | |----------------------------|-------------| -| `bool` | Boolean value - true or false. | -| `s8`, `s16`, `s32`, `s64` | Signed integers of the appropriate width. For example, `s32` is a 32-bit integer. | -| `u8`, `u16`, `u32`, `u64` | Unsigned integers of the appropriate width. For example, `u32` is a 32-bit integer. | -| `f32`, `f64` | Floating-point numbers of the appropriate width. For example, `f64` is a 64-bit (double precision) floating-point number. See the note on NaNs below. | +| `bool` | Boolean value `true` or `false`. | +| `s8`, `s16`, `s32`, `s64` | Signed integers of the appropriate width. For example, `s32` is a signed 32-bit integer. | +| `u8`, `u16`, `u32`, `u64` | Unsigned integers of the appropriate width. For example, `u32` is an unsigned 32-bit integer. | +| `f32`, `f64` | Floating-point numbers of the appropriate width. For example, `f64` is a 64-bit (double precision) floating-point number. See the note on `NaN`s below. | | `char` | Unicode character. (Specifically, a [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value).) | | `string` | A Unicode string - that is, a finite sequence of characters. | -The `f32` and `f64` types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a single NaN value. The exact bit-level representation of a NaN is not guaranteed to be preserved when values pass through WIT interfaces. +> ⓘ The `f32` and `f64` types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a single `nan` value. The exact bit-level representation of an IEEE 754 `NaN` is not guaranteed to be preserved when values pass through WIT interfaces as the singular WIT `nan` value. ### Lists -`list` for any type T denotes an ordered sequence of values of type T. T can be any type, built-in or user-defined: +`list` for any type `T` denotes an ordered sequence of values of type `T`. `T` can be any type, built-in or user-defined: ```wit list // byte buffer @@ -113,7 +113,7 @@ This is similar to Rust `Vec`, or Java `List`. ### Options -`option` for any type T may contain a value of type T, or may contain no value. T can be any type, built-in or user-defined. For example, a lookup function might return an option, allowing for the possibility that the lookup key wasn't found: +`option` for any type `T` may contain a value of type `T`, or may contain no value. `T` can be any type, built-in or user-defined. For example, a lookup function might return an option, allowing for the possibility that the lookup key wasn't found: ```wit option @@ -121,11 +121,11 @@ option This is similar to Rust `Option`, C++ `std::optional`, or Haskell `Maybe`. -> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every value type, and to enable it to be mapped idiomatically into languages with option types. +> ⓘ This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every value type, and to enable it to be mapped idiomatically into languages with option types. ### Results -`result` for any types T and E may contain a value of type T _or_ a value of type E (but not both). This is typically used for "value or error" situations; for example, a HTTP request function might return a result, with the success case (the T type) representing a HTTP response, and the error case (the E type) representing the various kinds of error that might occur: +`result` for any types `T` and `E `may contain a value of type `T` _or_ a value of type `E` (but not both). This is typically used for "value or error" situations; for example, a HTTP request function might return a result, with the success case (the `T` type) representing a HTTP response, and the error case (the `E` type) representing the various kinds of error that might occur: ```wit result @@ -133,7 +133,7 @@ result This is similar to Rust `Result`, or Haskell `Either`. -> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every combination of value and error types, and to enable it to be mapped idiomatically into languages with result or "either" types. +> ⓘ This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every combination of value and error types, and to enable it to be mapped idiomatically into languages with result or "either" types. Sometimes there is no data associated with one or both of the cases. For example, a `print` function could return an error code if it fails, but has nothing to return if it succeeds. In this case, you can omit the corresponding type as follows: @@ -145,7 +145,7 @@ result // no data associated with either case ### Tuples -A tuple type is an ordered _fixed length_ sequence of values of specified types. It is similar to a [_record_](#records), except that the fields are identified by their order instead of by names. +A `tuple` type is an ordered _fixed length_ sequence of values of specified types. It is similar to a [_record_](#records), except that the fields are identified by their order instead of by names. ```wit tuple // An integer and a string @@ -160,7 +160,7 @@ You can define your own types within an `interface` or `world`. WIT offers sever ### Records -A record type declares a set of named fields, each of the form `name: type`, separated by commas. A record instance contains a value for every field. Field types can be built-in or user-defined. The syntax is as follows: +A `record` type declares a set of named fields, each of the form `name: type`, separated by commas. A record instance contains a value for every field. Field types can be built-in or user-defined. The syntax is as follows: ```wit record customer { @@ -173,11 +173,11 @@ record customer { Records are similar to C or Rust `struct`s. -> User-defined records can't be generic (that is, parameterised by type). Only built-in types can be generic. +> ⓘ User-defined records can't be generic (that is, parameterised by type). Only built-in types can be generic. ### Variants -A variant type declares one or more cases. Each case has a name and, optionally, a type of data associated with that case. A variant instance contains exactly one case. Cases are separated by commas. The syntax is as follows: +A `variant` type declares one or more cases. Each case has a name and, optionally, a type of data associated with that case. A variant instance contains exactly one case. Cases are separated by commas. The syntax is as follows: ```wit variant allowed-destinations { @@ -189,11 +189,11 @@ variant allowed-destinations { Variants are similar to Rust `enum`s or OCaml discriminated unions. The closest C equivalent is a tagged union, but WIT both takes care of the "tag" (the case) and enforces the correct data shape for each tag. -> User-defined variants can't be generic (that is, parameterised by type). Only built-in types can be generic. +> ⓘ User-defined variants can't be generic (that is, parameterised by type). Only built-in types can be generic. ### Enums -An enum type is a variant type where none of the cases have associated data: +An `enum` type is a variant type where none of the cases have associated data: ```wit enum color { @@ -203,7 +203,7 @@ enum color { } ``` -This can provide a simpler representation in languages without discriminated unions. For example, a WIT enum can translate directly to a C++ `enum`. +This can provide a simpler representation in languages without discriminated unions. For example, a WIT `enum` can translate directly to a C++ `enum`. ### Resources @@ -248,18 +248,16 @@ blob-read: func(self: borrow, n: u32) -> list; blob-merge: static func(lhs: blob, rhs: blob) -> blob; ``` -When a resource type name is wrapped with `borrow<...>`, it stands for a +When a `resource` type name is wrapped with `borrow<...>`, it stands for a "borrowed" resource. A borrowed resource represents a temporary loan of a resource from the caller to the callee for the duration of the call. In contrast, when the owner of an owned resource drops that resource, the resource is destroyed. -> Note: more precisely, these are borrowed or owned `handles` of the resource. -> Learn more about `handles` in the [upstream component model -> specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#handles). +> ⓘ More precisely, these are borrowed or owned `handles` of the resource. Learn more about `handles` in the [upstream component model specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#handles). ### Flags -A flags type is a set of named booleans. In an instance of the type, each flag will be either true or false. +A `flags` type is a set of named `boolean`. In an instance of the type, each flag will be either `true` or `false`. ```wit flags allowed-methods { @@ -270,7 +268,7 @@ flags allowed-methods { } ``` -> A flags type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. +> ⓘ A `flags` type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. ### Type aliases @@ -347,7 +345,7 @@ interface canvas { } ``` -> Even if you are only using one type, it must still be enclosed in braces. For example, `use types.{dimension}` is legal but `use types.dimension` is not. +> ⓘ Even if you are only using one type, it must still be enclosed in braces. For example, `use types.{dimension}` is legal but `use types.dimension` is not. This works across files as long as the files are in the same package (effectively, in the same directory). For information about using definitions from other packages, see [the specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#interfaces-worlds-and-use). @@ -385,7 +383,7 @@ world http-proxy { } ``` -> As this example shows, import and export apply at the interface level, not the package level. You can import one interface defined in a package, while exporting another interface defined in the same package. Packages group definitions; they don't represent behaviour. +> ⓘ As this example shows, import and export apply at the interface level, not the package level. You can import one interface defined in a package, while exporting another interface defined in the same package. Packages group definitions; they don't represent behaviour. WIT does not define how packages are resolved - different tools may resolve them in different ways. diff --git a/component-model/src/language-support.md b/component-model/src/language-support.md index 0153021..3b82b73 100644 --- a/component-model/src/language-support.md +++ b/component-model/src/language-support.md @@ -3,9 +3,10 @@ WebAssembly can be targeted by the majority of top programming languages; however, the level of support varies. This document details the subset of languages that target WASI and support -components. This is a living document, so if you are aware of advancements in a toolchain, please do -not hesitate to [contribute documentation](https://github.com/bytecodealliance/component-docs/blob/main/CONTRIBUTING.md). You can find more information about the development of support for specific languages [here](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-guest-languages/proposal.md). Each section covers how to build and -run components for a given toolchain. +components. + +> ⓘ This is a living document, so if you are aware of advancements in a toolchain, please do +not hesitate to [contribute documentation](https://github.com/bytecodealliance/component-docs/blob/main/CONTRIBUTING.md). You can find more information about the development of support for specific languages in the [Guest Languages Special Interest Group Proposal](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-guest-languages/proposal.md) document. One of the benefits of components is their portability across host runtimes. The runtime only needs to know what world the component is targeting in order to import or execute the component. This @@ -16,6 +17,9 @@ toolchain section walks through creating a component of this world, which can be example host or from an application of that toolchain. This aims to provide a full story for using components within and among toolchains. +Each section covers how to build and +run components for a given toolchain: + - [Wasm Language Support](#wasm-language-support) - [Language Agnostic Tooling](#language-agnostic-tooling) - [Building a Component with `wasm-tools`](#building-a-component-with-wasm-tools) diff --git a/component-model/src/language-support/c.md b/component-model/src/language-support/c.md index 9f24ffe..1eba37b 100644 --- a/component-model/src/language-support/c.md +++ b/component-model/src/language-support/c.md @@ -35,7 +35,7 @@ Now, you can compile the function into a Wasm module via clang: clang add.c example.c example_component_type.o -o add-core.wasm -mexec-model=reactor ``` -> Note: Use the `clang` included in the WASI SDK installation, for example at `/bin/clang`. +> ⓘ Use the `clang` included in the WASI SDK installation, for example at `/bin/clang`. Next, you need to transform the module into a component. For this example, you can use `wasm-tools component new`: ```sh diff --git a/component-model/src/language-support/python.md b/component-model/src/language-support/python.md index 40006f8..1366a0b 100644 --- a/component-model/src/language-support/python.md +++ b/component-model/src/language-support/python.md @@ -28,7 +28,7 @@ If you want to generate bindings produced for the WIT world (for an IDE or typec $ componentize-py --wit-path /path/to/examples/example-host/add.wit --world example bindings . ``` -> Note: you do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component. +> ⓘ You do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component. You can see that bindings were created in an `example` package which contains an `Example` protocol with an `add` method that we can implement: @@ -100,7 +100,7 @@ Component built successfully Wasm components can also be invoked from Python applications. This walks through using tooling to call the [`app.wasm` component from the examples](../../examples/example-host/add.wasm). -> Note: `wasmtime-py` does not currently support running components build with `componentize-py`. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), which components built with `componentize-py` always use, since `componentize-py` unconditionally imports most of the `wasi:cli` world. +> ⓘ `wasmtime-py` does not currently support running components build with `componentize-py`. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), which components built with `componentize-py` always use, since `componentize-py` unconditionally imports most of the `wasi:cli` world. First, install [Python 3.11 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them. Then, install [`wasmtime-py`](https://github.com/bytecodealliance/wasmtime-py): diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index ac77a5c..0f5f537 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -11,7 +11,7 @@ To install `cargo component`, run: cargo install cargo-component ``` -> You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). +> ⓘ You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). ## Building a Component with `cargo component` @@ -115,7 +115,7 @@ impl Guest for Component { The world file (`wit/world.wit`) generated for you by `cargo component new --lib` doesn't specify any imports. -> `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. +> ⓘ `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. If your component consumes other components, you can edit the `world.wit` file to import their interfaces. @@ -210,7 +210,7 @@ Unlike library components, this does _not_ have the `--lib` flag. You will see t You can write Rust in this project, just as you normally would, including importing your own or third-party crates. -> All the crates that make up your project are linked together at build time, and compiled to a _single_ Wasm component. In this case, all the linking is happening at the Rust level: no WITs or component composition is involved. Only if you import Wasm interfaces do WIT and composition come into play. +> ⓘ All the crates that make up your project are linked together at build time, and compiled to a _single_ Wasm component. In this case, all the linking is happening at the Rust level: no WITs or component composition is involved. Only if you import Wasm interfaces do WIT and composition come into play. To run your command component: @@ -219,7 +219,7 @@ cargo component build wasmtime run ./target/wasm32-wasi/debug/.wasm ``` -> **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. +> ⓘ **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. ### Importing an interface into a command component @@ -227,54 +227,54 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co 1. Add a `wit/world.wit` to your project, and write a WIT world that imports the interface(s) you want to use. For example: -```wit -package docs:app; + ```wit + package docs:app; -world app { - import docs:calculator/calculate@0.1.0; -} -``` + world app { + import docs:calculator/calculate@0.1.0; + } + ``` -> `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. + > ⓘ `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. 2. Edit `Cargo.toml` to tell `cargo component` about the new WIT file: -```toml -[package.metadata.component.target] -path = "wit" -``` + ```toml + [package.metadata.component.target] + path = "wit" + ``` -(This entry is created automatically for library components but not for command components.) + (This entry is created automatically for library components but not for command components.) 3. Edit `Cargo.toml` to tell `cargo component` where to find external package WITs: -```toml -[package.metadata.component.target.dependencies] -"docs:calculator" = { path = "../calculator/wit" } -"docs:adder" = { path = "../adder/wit" } -``` + ```toml + [package.metadata.component.target.dependencies] + "docs:calculator" = { path = "../calculator/wit" } + "docs:adder" = { path = "../adder/wit" } + ``` -> If the external package refers to other packages, you need to provide the paths to them as well. + > ⓘ If the external package refers to other packages, you need to provide the paths to them as well. 4. Use the imported interface in your Rust code: -```rust -use bindings::docs::calculator::calculate::eval_expression; + ```rust + use bindings::docs::calculator::calculate::eval_expression; -fn main() { - let result = eval_expression("1 + 1"); - println!("1 + 1 = {result}"); -} -``` + fn main() { + let result = eval_expression("1 + 1"); + println!("1 + 1 = {result}"); + } + ``` 5. [Compose the command component with the `.wasm` components that implement the imports.](../creating-and-consuming/composing.md) 6. Run the composed component: -```sh -$ wasmtime run ./my-composed-command.wasm -1 + 1 = 579 # might need to go back and do some work on the calculator implementation -``` + ```sh + $ wasmtime run ./my-composed-command.wasm + 1 + 1 = 579 # might need to go back and do some work on the calculator implementation + ``` ## Using user-defined types @@ -367,61 +367,61 @@ To implement the calculator using `cargo component`: 2. Define a Rust `struct` to represent the calculator state: -```rust -use std::cell::RefCell; + ```rust + use std::cell::RefCell; -struct CalcEngine { - stack: RefCell>, -} -``` + struct CalcEngine { + stack: RefCell>, + } + ``` -> Why is the stack wrapped in a `RefCell`? As we will see, the generated Rust trait for the calculator engine has _immutable_ references to `self`. But our implementation of that trait will need to mutate the stack. So we need a type that allows for interior mutability, such as `RefCell` or `Arc>`. + > ⓘ Why is the stack wrapped in a `RefCell`? As we will see, the generated Rust trait for the calculator engine has _immutable_ references to `self`. But our implementation of that trait will need to mutate the stack. So we need a type that allows for interior mutability, such as `RefCell` or `Arc>`. 3. The generated bindings (`bindings.rs`) for an exported resource include a trait named `GuestX`, where `X` is the resource name. (You may need to run `cargo component build` to regenerate the bindings after updating the WIT.) For the calculator `engine` resource, the trait is `GuestEngine`. Implement this trait on the `struct` from step 2: -```rust -use bindings::exports::docs::rpn::types::{GuestEngine, Operation}; + ```rust + use bindings::exports::docs::rpn::types::{GuestEngine, Operation}; -impl GuestEngine for CalcEngine { - fn new() -> Self { - CalcEngine { - stack: RefCell::new(vec![]) + impl GuestEngine for CalcEngine { + fn new() -> Self { + CalcEngine { + stack: RefCell::new(vec![]) + } } - } - fn push_operand(&self, operand: u32) { - self.stack.borrow_mut().push(operand); - } + fn push_operand(&self, operand: u32) { + self.stack.borrow_mut().push(operand); + } - fn push_operation(&self, operation: Operation) { - let mut stack = self.stack.borrow_mut(); - let right = stack.pop().unwrap(); // TODO: error handling! - let left = stack.pop().unwrap(); - let result = match operation { - Operation::Add => left + right, - Operation::Sub => left - right, - Operation::Mul => left * right, - Operation::Div => left / right, - }; - stack.push(result); - } + fn push_operation(&self, operation: Operation) { + let mut stack = self.stack.borrow_mut(); + let right = stack.pop().unwrap(); // TODO: error handling! + let left = stack.pop().unwrap(); + let result = match operation { + Operation::Add => left + right, + Operation::Sub => left - right, + Operation::Mul => left * right, + Operation::Div => left / right, + }; + stack.push(result); + } - fn execute(&self) -> u32 { - self.stack.borrow_mut().pop().unwrap() // TODO: error handling! + fn execute(&self) -> u32 { + self.stack.borrow_mut().pop().unwrap() // TODO: error handling! + } } -} -``` + ``` 4. We now have a working calculator type which implements the `engine` contract, but we must still connect that type to the `engine` resource type. This is done by implementing the generated `Guest` trait. For this WIT, the `Guest` trait contains nothing except an associated type. You can use an empty `struct` to implement the `Guest` trait on. Set the associated type for the resource - in our case, `Engine` - to the type which implements the resource trait - in our case, the `CalcEngine` `struct` which implements `GuestEngine`. Then use the `export!` macro to export the mapping: -```rust -struct Implementation; -impl Guest for Implementation { - type Engine = CalcEngine; -} + ```rust + struct Implementation; + impl Guest for Implementation { + type Engine = CalcEngine; + } -bindings::export!(Implementation with_types_in bindings); -``` + bindings::export!(Implementation with_types_in bindings); + ``` This completes the implementation of the calculator `engine` resource. Run `cargo component build` to create a component `.wasm` file. @@ -433,43 +433,43 @@ To use the calculator engine in another component, that component must import th 2. Add a `wit/world.wit` to your project, and write a WIT world that imports the RPN calculator types: -```wit -package docs:rpn-cmd; + ```wit + package docs:rpn-cmd; -world app { - import docs:rpn/types@0.1.0; -} -``` + world app { + import docs:rpn/types@0.1.0; + } + ``` 3. Edit `Cargo.toml` to tell `cargo component` about the new WIT file and the external RPN package file: -```toml -[package.metadata.component] -package = "docs:rpn-cmd" + ```toml + [package.metadata.component] + package = "docs:rpn-cmd" -[package.metadata.component.target] -path = "wit" + [package.metadata.component.target] + path = "wit" -[package.metadata.component.target.dependencies] -"docs:rpn" = { path = "../wit" } # or wherever your resource WIT is -``` + [package.metadata.component.target.dependencies] + "docs:rpn" = { path = "../wit" } # or wherever your resource WIT is + ``` 4. The resource now appears in the generated bindings as a `struct`, with appropriate associated functions. Use these to construct a test app: -```rust -#[allow(warnings)] -mod bindings; -use bindings::docs::rpn::types::{Engine, Operation}; - -fn main() { - let calc = Engine::new(); - calc.push_operand(1); - calc.push_operand(2); - calc.push_operation(Operation::Add); - let sum = calc.execute(); - println!("{sum}"); -} -``` + ```rust + #[allow(warnings)] + mod bindings; + use bindings::docs::rpn::types::{Engine, Operation}; + + fn main() { + let calc = Engine::new(); + calc.push_operand(1); + calc.push_operand(2); + calc.push_operation(Operation::Add); + let sum = calc.execute(); + println!("{sum}"); + } + ``` You can now build the command component and [compose it with the `.wasm` component that implements the resource.](../creating-and-consuming/composing.md). You can then run the composed command with `wasmtime run`. @@ -479,62 +479,62 @@ If you are hosting a Wasm runtime, you can export a resource from your host for 1. Use `wasmtime::component::bindgen!` to specify the WIT you are a host for: -```rust -wasmtime::component::bindgen!({ - path: "../wit" -}); -``` + ```rust + wasmtime::component::bindgen!({ + path: "../wit" + }); + ``` 2. Tell `bindgen!` how you will represent the resource in the host via the `with` field. This can be any Rust type. For example, the RPN engine could be represented by a `CalcEngine` struct: -```rust -wasmtime::component::bindgen!({ - path: "../wit", - with: { - "docs:rpn/types/engine": CalcEngine, - } -}); -``` + ```rust + wasmtime::component::bindgen!({ + path: "../wit", + with: { + "docs:rpn/types/engine": CalcEngine, + } + }); + ``` -> If you don't specify the host representation for a resource, it defaults to an empty enum. This is rarely useful as resources are usually stateful. + > ⓘ If you don't specify the host representation for a resource, it defaults to an empty enum. This is rarely useful as resources are usually stateful. 3. If the representation type isn't a built-in type, define it: -```rust -struct CalcEngine { /* ... */ } -``` + ```rust + struct CalcEngine { /* ... */ } + ``` 4. As a host, you will already be implementing a `Host` trait. You will now need to implement a `HostX` trait (where `X` is the resource name) _on the same type_ as the `Host` trait: -```rust -impl docs::rpn::types::HostEngine for MyHost { - fn new(&mut self) -> wasmtime::component::Resource { /* ... */ } - fn push_operand(&mut self, self_: wasmtime::component::Resource) { /* ... */ } - // etc. -} -``` + ```rust + impl docs::rpn::types::HostEngine for MyHost { + fn new(&mut self) -> wasmtime::component::Resource { /* ... */ } + fn push_operand(&mut self, self_: wasmtime::component::Resource) { /* ... */ } + // etc. + } + ``` -**Important:** You implement this on the 'overall' host type, *not* on the resource representation! Therefore, the `self` reference in these functions is to the 'overall' host type. For instance methods of the resource, the instance is identified by a second parameter (`self_`), of type `wasmtime::component::Resource`. + > ⓘ **Important:** You implement this on the 'overall' host type, *not* on the resource representation! Therefore, the `self` reference in these functions is to the 'overall' host type. For instance methods of the resource, the instance is identified by a second parameter (`self_`), of type `wasmtime::component::Resource`. 5. Add a `wasmtime::component::ResourceTable` to the host: -```rust -struct MyHost { - calcs: wasmtime::component::ResourceTable, -} -``` + ```rust + struct MyHost { + calcs: wasmtime::component::ResourceTable, + } + ``` 6. In your resource method implementations, use this table to store and access instances of the resource representation: -```rust -impl docs::rpn::types::HostEngine for MyHost { - fn new(&mut self) -> wasmtime::component::Resource { - self.calcs.push(CalcEngine::new()).unwrap() // TODO: error handling - } - fn push_operand(&mut self, self_: wasmtime::component::Resource) { - let calc_engine = self.calcs.get(&self_).unwrap(); - // calc_engine is a CalcEngine - call its functions + ```rust + impl docs::rpn::types::HostEngine for MyHost { + fn new(&mut self) -> wasmtime::component::Resource { + self.calcs.push(CalcEngine::new()).unwrap() // TODO: error handling + } + fn push_operand(&mut self, self_: wasmtime::component::Resource) { + let calc_engine = self.calcs.get(&self_).unwrap(); + // calc_engine is a CalcEngine - call its functions + } + // etc. } - // etc. -} -``` + ``` diff --git a/component-model/src/runtimes/wasmtime.md b/component-model/src/runtimes/wasmtime.md index d0a3b47..1841ee2 100644 --- a/component-model/src/runtimes/wasmtime.md +++ b/component-model/src/runtimes/wasmtime.md @@ -9,7 +9,7 @@ To run a command component with Wasmtime, execute: wasmtime run ``` -> If you are using an older version of `wasmtime`, you may need to add the `--wasm component-model` flag to specify that you are running a component rather than a core module. +> ⓘ If you are using an older version of `wasmtime`, you may need to add the `--wasm component-model` flag to specify that you are running a component rather than a core module. By default, Wasmtime denies the component access to all system resources. For example, the component cannot access the file system or environment variables. See the [Wasmtime guide](https://docs.wasmtime.dev/) for information on granting access, and for other Wasmtime features. diff --git a/component-model/src/tutorial.md b/component-model/src/tutorial.md index 68dc04b..c586121 100644 --- a/component-model/src/tutorial.md +++ b/component-model/src/tutorial.md @@ -21,18 +21,18 @@ These files can be found in the component book repository in the [`wit` director * A world describing an world that exports the "add" interface. Again, components such as the calculator can call it when they need to add numbers. -```wit -// wit/adder/world.wit -package docs:adder@0.1.0; + ```wit + // wit/adder/world.wit + package docs:adder@0.1.0; -interface add { - add: func(a: u32, b: u32) -> u32; -} + interface add { + add: func(a: u32, b: u32) -> u32; + } -world adder { - export add; -} -``` + world adder { + export add; + } + ``` * An interface for the calculator itself. We'll use this later to carry out calculations. It contains an evaluate function, and an enum that delineates the operations that can be involved in @@ -48,27 +48,27 @@ world adder { of the calculator component. -```wit -// wit/calculator/world.wit -package docs:calculator@0.1.0; + ```wit + // wit/calculator/world.wit + package docs:calculator@0.1.0; -interface calculate { - enum op { - add, - } - eval-expression: func(op: op, x: u32, y: u32) -> u32; -} + interface calculate { + enum op { + add, + } + eval-expression: func(op: op, x: u32, y: u32) -> u32; + } -world calculator { - export calculate; - import docs:adder/add@0.1.0; -} + world calculator { + export calculate; + import docs:adder/add@0.1.0; + } -world app { - import calculate; -} + world app { + import calculate; + } -``` + ``` ## Create an `add` component @@ -134,9 +134,7 @@ wasm-tools compose calculator.wasm -d adder.wasm -o composed.wasm wasm-tools compose command.wasm -d composed.wasm -o final.wasm ``` -> If you'd prefer to take a more visual approach to composing components, see the [documentation on -> composing components with -> wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). +> ⓘ If you'd prefer to take a more visual approach to composing components, see the [documentation on composing components with wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). ## Running the calculator From ea964f48b0c1951ff273ea6e030b3d99720660cc Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 28 Aug 2024 15:01:45 -0500 Subject: [PATCH 2/4] =?UTF-8?q?Remove=20=E2=93=98=20from=20note=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component-model/src/advanced/canonical-abi.md | 2 +- .../src/creating-and-consuming/composing.md | 4 ++-- .../src/creating-and-consuming/running.md | 2 +- component-model/src/design/components.md | 2 +- component-model/src/design/interfaces.md | 2 +- component-model/src/design/packages.md | 2 +- .../src/design/why-component-model.md | 2 +- component-model/src/design/wit.md | 22 +++++++++---------- component-model/src/design/worlds.md | 2 +- component-model/src/introduction.md | 2 +- component-model/src/language-support.md | 2 +- component-model/src/language-support/c.md | 2 +- .../src/language-support/python.md | 4 ++-- component-model/src/language-support/rust.md | 18 +++++++-------- component-model/src/runtimes/wasmtime.md | 2 +- component-model/src/tutorial.md | 2 +- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/component-model/src/advanced/canonical-abi.md b/component-model/src/advanced/canonical-abi.md index df895b1..75378c0 100644 --- a/component-model/src/advanced/canonical-abi.md +++ b/component-model/src/advanced/canonical-abi.md @@ -4,4 +4,4 @@ An ABI is an **application binary interface** - an agreement on how to pass data The component model defines a **canonical ABI** - an ABI to which all [components](../design/components.md) adhere. This guarantees that components can talk to each other without confusion, even if they are built in different languages. Internally, a C component might represent strings in a quite different way from a Rust component, but the canonical ABI provides a format for them to pass strings across the boundary between them. -> ⓘ For a more formal definition of what the Canonical ABI is, take a look at the [Canonical ABI explainer](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md). +> For a more formal definition of what the Canonical ABI is, take a look at the [Canonical ABI explainer](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md). diff --git a/component-model/src/creating-and-consuming/composing.md b/component-model/src/creating-and-consuming/composing.md index e9f8c2d..c68d515 100644 --- a/component-model/src/creating-and-consuming/composing.md +++ b/component-model/src/creating-and-consuming/composing.md @@ -2,7 +2,7 @@ Because the WebAssembly component model packages code in a portable binary format, and provides machine-readable interfaces in [WIT](../design/wit.md) with a standardised ABI (Application Binary Interface), it enables applications and components to work together, no matter what languages they were originally written in. In the same way that, for example, a Rust package (crate) can be compiled together with other Rust code to create a higher-level library or an application, a Wasm component can be linked with other components. -> ⓘ Component model interoperation is more convenient and expressive than language-specific foreign function interfaces. A typical C FFI involves language-specific types, so it is not possible to link between arbitrary languages without at least some C-language wrapping or conversion. The component model, by contrast, provides a common way of expressing interfaces, and a standard binary representation of those interfaces. So if an import and an export have the same shape, they fit together directly. +> Component model interoperation is more convenient and expressive than language-specific foreign function interfaces. A typical C FFI involves language-specific types, so it is not possible to link between arbitrary languages without at least some C-language wrapping or conversion. The component model, by contrast, provides a common way of expressing interfaces, and a standard binary representation of those interfaces. So if an import and an export have the same shape, they fit together directly. ## What is composition? @@ -61,7 +61,7 @@ wasm-tools compose path/to/component.wasm -d path/to/dep1.wasm -d path/to/dep2.w Here `component.wasm` is the component that imports interfaces from `dep1.wasm` and `dep2.wasm`, which export them. The composed component, with those dependencies satisfied and tucked away inside it, is saved to `composed.wasm`. -> ⓘ This syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'll need to use a [configuration file](https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wasm-compose/CONFIG.md). (Or you can compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. This doesn't scale to lots of transitive dependencies though!) +> This syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'll need to use a [configuration file](https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wasm-compose/CONFIG.md). (Or you can compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. This doesn't scale to lots of transitive dependencies though!) For full information about `wasm-tools compose` including how to configure more advanced scenarios, see [the `wasm-tools compose` documentation](https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-compose). diff --git a/component-model/src/creating-and-consuming/running.md b/component-model/src/creating-and-consuming/running.md index 97b6171..9a61121 100644 --- a/component-model/src/creating-and-consuming/running.md +++ b/component-model/src/creating-and-consuming/running.md @@ -2,7 +2,7 @@ You can "run" a component by calling one of its exports. In some cases, this requires a custom host. For "command" components, though, you can use the `wasmtime` command line. This can be a convenient tool for testing components and exploring the component model. Other runtimes are also available - see the "Runtimes" section of the sidebar for more info. -> ⓘ A "command" component is one that exports the `wasi:cli/run` interface, and imports only interfaces listed in the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit). +> A "command" component is one that exports the `wasi:cli/run` interface, and imports only interfaces listed in the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit). You must use a recent version of `wasmtime` ([`v14.0.0` or greater](https://github.com/bytecodealliance/wasmtime/releases)), as earlier releases of the `wasmtime` command line do not include component model support. diff --git a/component-model/src/design/components.md b/component-model/src/design/components.md index c3dd542..879d50e 100644 --- a/component-model/src/design/components.md +++ b/component-model/src/design/components.md @@ -6,4 +6,4 @@ The external interface of a component - its imports and exports - corresponds to a [world](./worlds.md). The component, however, internally defines how that world is implemented. -> ⓘ For a more formal definition of what a component is, take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). +> For a more formal definition of what a component is, take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). diff --git a/component-model/src/design/interfaces.md b/component-model/src/design/interfaces.md index eac851c..5d0f571 100644 --- a/component-model/src/design/interfaces.md +++ b/component-model/src/design/interfaces.md @@ -7,4 +7,4 @@ An **interface** describes a single-focus, composable contract, through which co Interfaces are defined using [the WIT language](./wit.md). -> ⓘ For a more formal definition of what an interface is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of what an interface is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/packages.md b/component-model/src/design/packages.md index 3a9a4a3..3fb1439 100644 --- a/component-model/src/design/packages.md +++ b/component-model/src/design/packages.md @@ -6,4 +6,4 @@ A WIT package is not a [world](./worlds.md). It's a way of grouping related inte * The WebAssembly System Interface (WASI) defines a number of packages, including one named `wasi:clocks`. Our HTTP proxy world could import the `wall-clock` interface from the `wasi:clocks` package, rather than having to define a custom clock interface. -> ⓘ For a more formal definition of what a WIT package is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of what a WIT package is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/why-component-model.md b/component-model/src/design/why-component-model.md index b68d9d9..a463b7f 100644 --- a/component-model/src/design/why-component-model.md +++ b/component-model/src/design/why-component-model.md @@ -16,4 +16,4 @@ Moreover, a component interacts with a runtime or other components _only_ by cal Now that you have a better idea about how the component model can help you, take a look at [how to build components](../language-support.md) in your favorite language! -> ⓘ For more background on why the component model was created, take a look at the specification's [goals](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Goals.md), [use cases](https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md) and [design choices](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Choices.md). +> For more background on why the component model was created, take a look at the specification's [goals](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Goals.md), [use cases](https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md) and [design choices](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Choices.md). diff --git a/component-model/src/design/wit.md b/component-model/src/design/wit.md index c349e7d..83687d3 100644 --- a/component-model/src/design/wit.md +++ b/component-model/src/design/wit.md @@ -33,7 +33,7 @@ The WIT (Wasm Interface Type) language is used to define Component Model [interf A WIT file contains one or more **interfaces** or **worlds**. An interface or world can define **types** and/or **functions**. -> ⓘ Types and functions can't be defined outside of interfaces or worlds. +> Types and functions can't be defined outside of interfaces or worlds. A file may optionally start with a **package** declaration. @@ -98,7 +98,7 @@ WIT defines the following primitive types: | `char` | Unicode character. (Specifically, a [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value).) | | `string` | A Unicode string - that is, a finite sequence of characters. | -> ⓘ The `f32` and `f64` types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a single `nan` value. The exact bit-level representation of an IEEE 754 `NaN` is not guaranteed to be preserved when values pass through WIT interfaces as the singular WIT `nan` value. +> The `f32` and `f64` types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a single `nan` value. The exact bit-level representation of an IEEE 754 `NaN` is not guaranteed to be preserved when values pass through WIT interfaces as the singular WIT `nan` value. ### Lists @@ -121,7 +121,7 @@ option This is similar to Rust `Option`, C++ `std::optional`, or Haskell `Maybe`. -> ⓘ This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every value type, and to enable it to be mapped idiomatically into languages with option types. +> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every value type, and to enable it to be mapped idiomatically into languages with option types. ### Results @@ -133,7 +133,7 @@ result This is similar to Rust `Result`, or Haskell `Either`. -> ⓘ This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every combination of value and error types, and to enable it to be mapped idiomatically into languages with result or "either" types. +> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every combination of value and error types, and to enable it to be mapped idiomatically into languages with result or "either" types. Sometimes there is no data associated with one or both of the cases. For example, a `print` function could return an error code if it fails, but has nothing to return if it succeeds. In this case, you can omit the corresponding type as follows: @@ -173,7 +173,7 @@ record customer { Records are similar to C or Rust `struct`s. -> ⓘ User-defined records can't be generic (that is, parameterised by type). Only built-in types can be generic. +> User-defined records can't be generic (that is, parameterised by type). Only built-in types can be generic. ### Variants @@ -189,7 +189,7 @@ variant allowed-destinations { Variants are similar to Rust `enum`s or OCaml discriminated unions. The closest C equivalent is a tagged union, but WIT both takes care of the "tag" (the case) and enforces the correct data shape for each tag. -> ⓘ User-defined variants can't be generic (that is, parameterised by type). Only built-in types can be generic. +> User-defined variants can't be generic (that is, parameterised by type). Only built-in types can be generic. ### Enums @@ -253,7 +253,7 @@ When a `resource` type name is wrapped with `borrow<...>`, it stands for a caller to the callee for the duration of the call. In contrast, when the owner of an owned resource drops that resource, the resource is destroyed. -> ⓘ More precisely, these are borrowed or owned `handles` of the resource. Learn more about `handles` in the [upstream component model specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#handles). +> More precisely, these are borrowed or owned `handles` of the resource. Learn more about `handles` in the [upstream component model specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#handles). ### Flags @@ -268,7 +268,7 @@ flags allowed-methods { } ``` -> ⓘ A `flags` type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. +> A `flags` type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. ### Type aliases @@ -345,7 +345,7 @@ interface canvas { } ``` -> ⓘ Even if you are only using one type, it must still be enclosed in braces. For example, `use types.{dimension}` is legal but `use types.dimension` is not. +> Even if you are only using one type, it must still be enclosed in braces. For example, `use types.{dimension}` is legal but `use types.dimension` is not. This works across files as long as the files are in the same package (effectively, in the same directory). For information about using definitions from other packages, see [the specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#interfaces-worlds-and-use). @@ -383,7 +383,7 @@ world http-proxy { } ``` -> ⓘ As this example shows, import and export apply at the interface level, not the package level. You can import one interface defined in a package, while exporting another interface defined in the same package. Packages group definitions; they don't represent behaviour. +> As this example shows, import and export apply at the interface level, not the package level. You can import one interface defined in a package, while exporting another interface defined in the same package. Packages group definitions; they don't represent behaviour. WIT does not define how packages are resolved - different tools may resolve them in different ways. @@ -453,4 +453,4 @@ world proxy { } ``` -> ⓘ For a more formal definition of the WIT language, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of the WIT language, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/worlds.md b/component-model/src/design/worlds.md index 13ed3f0..37fd23c 100644 --- a/component-model/src/design/worlds.md +++ b/component-model/src/design/worlds.md @@ -17,4 +17,4 @@ For a component to run, its imports must be fulfilled, by a host or by other com * A (trivial) "HTTP proxy" world would export a "handle HTTP requests" interface, and import a "send HTTP requests" interface. A host, or another component, would call the exported "handle" interface, passing an HTTP request; the component would forward it on via the imported "send" interface. To be a _useful_ proxy, the component may also need to import interfaces such as I/O and clock time - without those imports the component could not perform, for example, on-disk caching. * A "regex parser" world would export a "parse regex" function, and would import nothing. This declares not only that the component implementing this world can parse regular expressions, but also that it calls no other APIs. A user of such a parser could know, without looking at the implementation, that is does not access the file system, or send the user's regexes to a network service. -> ⓘ For a more formal definition of what a WIT world is, take a look at the [WIT world specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#wit-worlds). +> For a more formal definition of what a WIT world is, take a look at the [WIT world specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#wit-worlds). diff --git a/component-model/src/introduction.md b/component-model/src/introduction.md index 5b5729d..1fe39f4 100644 --- a/component-model/src/introduction.md +++ b/component-model/src/introduction.md @@ -25,7 +25,7 @@ The WebAssembly Component Model is a broad-reaching architecture for building in [Running]: ./creating-and-consuming/running.md [Distributing]: ./creating-and-consuming/distributing.md -> ⓘ This documentation is aimed at _users_ of the component model: developers of libraries and applications. _Compiler and Wasm runtime developers_ can take a look at the [Component Model specification](https://github.com/WebAssembly/component-model) to see how to add support for the component model to their project. +> This documentation is aimed at _users_ of the component model: developers of libraries and applications. _Compiler and Wasm runtime developers_ can take a look at the [Component Model specification](https://github.com/WebAssembly/component-model) to see how to add support for the component model to their project. ## Status diff --git a/component-model/src/language-support.md b/component-model/src/language-support.md index 3b82b73..6257d11 100644 --- a/component-model/src/language-support.md +++ b/component-model/src/language-support.md @@ -5,7 +5,7 @@ languages; however, the level of support varies. This document details the subset of languages that target WASI and support components. -> ⓘ This is a living document, so if you are aware of advancements in a toolchain, please do +> This is a living document, so if you are aware of advancements in a toolchain, please do not hesitate to [contribute documentation](https://github.com/bytecodealliance/component-docs/blob/main/CONTRIBUTING.md). You can find more information about the development of support for specific languages in the [Guest Languages Special Interest Group Proposal](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-guest-languages/proposal.md) document. One of the benefits of components is their portability across host runtimes. The runtime only needs diff --git a/component-model/src/language-support/c.md b/component-model/src/language-support/c.md index 1eba37b..c50a9e9 100644 --- a/component-model/src/language-support/c.md +++ b/component-model/src/language-support/c.md @@ -35,7 +35,7 @@ Now, you can compile the function into a Wasm module via clang: clang add.c example.c example_component_type.o -o add-core.wasm -mexec-model=reactor ``` -> ⓘ Use the `clang` included in the WASI SDK installation, for example at `/bin/clang`. +> Use the `clang` included in the WASI SDK installation, for example at `/bin/clang`. Next, you need to transform the module into a component. For this example, you can use `wasm-tools component new`: ```sh diff --git a/component-model/src/language-support/python.md b/component-model/src/language-support/python.md index 1366a0b..2487d5e 100644 --- a/component-model/src/language-support/python.md +++ b/component-model/src/language-support/python.md @@ -28,7 +28,7 @@ If you want to generate bindings produced for the WIT world (for an IDE or typec $ componentize-py --wit-path /path/to/examples/example-host/add.wit --world example bindings . ``` -> ⓘ You do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component. +> You do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component. You can see that bindings were created in an `example` package which contains an `Example` protocol with an `add` method that we can implement: @@ -100,7 +100,7 @@ Component built successfully Wasm components can also be invoked from Python applications. This walks through using tooling to call the [`app.wasm` component from the examples](../../examples/example-host/add.wasm). -> ⓘ `wasmtime-py` does not currently support running components build with `componentize-py`. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), which components built with `componentize-py` always use, since `componentize-py` unconditionally imports most of the `wasi:cli` world. +> `wasmtime-py` does not currently support running components build with `componentize-py`. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), which components built with `componentize-py` always use, since `componentize-py` unconditionally imports most of the `wasi:cli` world. First, install [Python 3.11 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them. Then, install [`wasmtime-py`](https://github.com/bytecodealliance/wasmtime-py): diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 0f5f537..c81722d 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -11,7 +11,7 @@ To install `cargo component`, run: cargo install cargo-component ``` -> ⓘ You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). +> You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). ## Building a Component with `cargo component` @@ -115,7 +115,7 @@ impl Guest for Component { The world file (`wit/world.wit`) generated for you by `cargo component new --lib` doesn't specify any imports. -> ⓘ `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. +> `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. If your component consumes other components, you can edit the `world.wit` file to import their interfaces. @@ -210,7 +210,7 @@ Unlike library components, this does _not_ have the `--lib` flag. You will see t You can write Rust in this project, just as you normally would, including importing your own or third-party crates. -> ⓘ All the crates that make up your project are linked together at build time, and compiled to a _single_ Wasm component. In this case, all the linking is happening at the Rust level: no WITs or component composition is involved. Only if you import Wasm interfaces do WIT and composition come into play. +> All the crates that make up your project are linked together at build time, and compiled to a _single_ Wasm component. In this case, all the linking is happening at the Rust level: no WITs or component composition is involved. Only if you import Wasm interfaces do WIT and composition come into play. To run your command component: @@ -219,7 +219,7 @@ cargo component build wasmtime run ./target/wasm32-wasi/debug/.wasm ``` -> ⓘ **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. +> **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. ### Importing an interface into a command component @@ -235,7 +235,7 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co } ``` - > ⓘ `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. + > `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. 2. Edit `Cargo.toml` to tell `cargo component` about the new WIT file: @@ -254,7 +254,7 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co "docs:adder" = { path = "../adder/wit" } ``` - > ⓘ If the external package refers to other packages, you need to provide the paths to them as well. + > If the external package refers to other packages, you need to provide the paths to them as well. 4. Use the imported interface in your Rust code: @@ -375,7 +375,7 @@ To implement the calculator using `cargo component`: } ``` - > ⓘ Why is the stack wrapped in a `RefCell`? As we will see, the generated Rust trait for the calculator engine has _immutable_ references to `self`. But our implementation of that trait will need to mutate the stack. So we need a type that allows for interior mutability, such as `RefCell` or `Arc>`. + > Why is the stack wrapped in a `RefCell`? As we will see, the generated Rust trait for the calculator engine has _immutable_ references to `self`. But our implementation of that trait will need to mutate the stack. So we need a type that allows for interior mutability, such as `RefCell` or `Arc>`. 3. The generated bindings (`bindings.rs`) for an exported resource include a trait named `GuestX`, where `X` is the resource name. (You may need to run `cargo component build` to regenerate the bindings after updating the WIT.) For the calculator `engine` resource, the trait is `GuestEngine`. Implement this trait on the `struct` from step 2: @@ -496,7 +496,7 @@ If you are hosting a Wasm runtime, you can export a resource from your host for }); ``` - > ⓘ If you don't specify the host representation for a resource, it defaults to an empty enum. This is rarely useful as resources are usually stateful. + > If you don't specify the host representation for a resource, it defaults to an empty enum. This is rarely useful as resources are usually stateful. 3. If the representation type isn't a built-in type, define it: @@ -514,7 +514,7 @@ If you are hosting a Wasm runtime, you can export a resource from your host for } ``` - > ⓘ **Important:** You implement this on the 'overall' host type, *not* on the resource representation! Therefore, the `self` reference in these functions is to the 'overall' host type. For instance methods of the resource, the instance is identified by a second parameter (`self_`), of type `wasmtime::component::Resource`. + > **Important:** You implement this on the 'overall' host type, *not* on the resource representation! Therefore, the `self` reference in these functions is to the 'overall' host type. For instance methods of the resource, the instance is identified by a second parameter (`self_`), of type `wasmtime::component::Resource`. 5. Add a `wasmtime::component::ResourceTable` to the host: diff --git a/component-model/src/runtimes/wasmtime.md b/component-model/src/runtimes/wasmtime.md index 1841ee2..0e266af 100644 --- a/component-model/src/runtimes/wasmtime.md +++ b/component-model/src/runtimes/wasmtime.md @@ -9,7 +9,7 @@ To run a command component with Wasmtime, execute: wasmtime run ``` -> ⓘ If you are using an older version of `wasmtime`, you may need to add the `--wasm component-model` flag to specify that you are running a component rather than a core module. +> If you are using an older version of `wasmtime`, you may need to add the `--wasm component-model` flag to specify that you are running a component rather than a core module. By default, Wasmtime denies the component access to all system resources. For example, the component cannot access the file system or environment variables. See the [Wasmtime guide](https://docs.wasmtime.dev/) for information on granting access, and for other Wasmtime features. diff --git a/component-model/src/tutorial.md b/component-model/src/tutorial.md index c586121..69226ee 100644 --- a/component-model/src/tutorial.md +++ b/component-model/src/tutorial.md @@ -134,7 +134,7 @@ wasm-tools compose calculator.wasm -d adder.wasm -o composed.wasm wasm-tools compose command.wasm -d composed.wasm -o final.wasm ``` -> ⓘ If you'd prefer to take a more visual approach to composing components, see the [documentation on composing components with wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). +> If you'd prefer to take a more visual approach to composing components, see the [documentation on composing components with wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). ## Running the calculator From d84da463152ccc7b1b87e9e717d8e9b83af0e26d Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 28 Aug 2024 15:07:31 -0500 Subject: [PATCH 3/4] Remove extra whitespace --- component-model/src/advanced/canonical-abi.md | 2 +- .../src/creating-and-consuming/composing.md | 4 +-- .../src/creating-and-consuming/running.md | 2 +- component-model/src/design/components.md | 2 +- component-model/src/design/interfaces.md | 2 +- component-model/src/design/packages.md | 2 +- .../src/design/why-component-model.md | 2 +- component-model/src/design/wit.md | 34 +++++++++---------- component-model/src/design/worlds.md | 2 +- component-model/src/introduction.md | 2 +- component-model/src/language-support.md | 2 +- component-model/src/language-support/c.md | 2 +- .../src/language-support/python.md | 4 +-- component-model/src/language-support/rust.md | 18 +++++----- component-model/src/runtimes/wasmtime.md | 2 +- component-model/src/tutorial.md | 2 +- 16 files changed, 42 insertions(+), 42 deletions(-) diff --git a/component-model/src/advanced/canonical-abi.md b/component-model/src/advanced/canonical-abi.md index 75378c0..2a5a0e3 100644 --- a/component-model/src/advanced/canonical-abi.md +++ b/component-model/src/advanced/canonical-abi.md @@ -4,4 +4,4 @@ An ABI is an **application binary interface** - an agreement on how to pass data The component model defines a **canonical ABI** - an ABI to which all [components](../design/components.md) adhere. This guarantees that components can talk to each other without confusion, even if they are built in different languages. Internally, a C component might represent strings in a quite different way from a Rust component, but the canonical ABI provides a format for them to pass strings across the boundary between them. -> For a more formal definition of what the Canonical ABI is, take a look at the [Canonical ABI explainer](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md). +> For a more formal definition of what the Canonical ABI is, take a look at the [Canonical ABI explainer](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md). diff --git a/component-model/src/creating-and-consuming/composing.md b/component-model/src/creating-and-consuming/composing.md index c68d515..5d7365a 100644 --- a/component-model/src/creating-and-consuming/composing.md +++ b/component-model/src/creating-and-consuming/composing.md @@ -2,7 +2,7 @@ Because the WebAssembly component model packages code in a portable binary format, and provides machine-readable interfaces in [WIT](../design/wit.md) with a standardised ABI (Application Binary Interface), it enables applications and components to work together, no matter what languages they were originally written in. In the same way that, for example, a Rust package (crate) can be compiled together with other Rust code to create a higher-level library or an application, a Wasm component can be linked with other components. -> Component model interoperation is more convenient and expressive than language-specific foreign function interfaces. A typical C FFI involves language-specific types, so it is not possible to link between arbitrary languages without at least some C-language wrapping or conversion. The component model, by contrast, provides a common way of expressing interfaces, and a standard binary representation of those interfaces. So if an import and an export have the same shape, they fit together directly. +> Component model interoperation is more convenient and expressive than language-specific foreign function interfaces. A typical C FFI involves language-specific types, so it is not possible to link between arbitrary languages without at least some C-language wrapping or conversion. The component model, by contrast, provides a common way of expressing interfaces, and a standard binary representation of those interfaces. So if an import and an export have the same shape, they fit together directly. ## What is composition? @@ -61,7 +61,7 @@ wasm-tools compose path/to/component.wasm -d path/to/dep1.wasm -d path/to/dep2.w Here `component.wasm` is the component that imports interfaces from `dep1.wasm` and `dep2.wasm`, which export them. The composed component, with those dependencies satisfied and tucked away inside it, is saved to `composed.wasm`. -> This syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'll need to use a [configuration file](https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wasm-compose/CONFIG.md). (Or you can compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. This doesn't scale to lots of transitive dependencies though!) +> This syntax doesn't cover transitive dependencies. If, for example, `dep1.wasm` has unsatisfied imports that you want to satisfy from `dep3.wasm`, you'll need to use a [configuration file](https://github.com/bytecodealliance/wasm-tools/blob/main/crates/wasm-compose/CONFIG.md). (Or you can compose `dep1.wasm` with `dep3.wasm` first, then refer to that composed component instead of `dep1.wasm`. This doesn't scale to lots of transitive dependencies though!) For full information about `wasm-tools compose` including how to configure more advanced scenarios, see [the `wasm-tools compose` documentation](https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-compose). diff --git a/component-model/src/creating-and-consuming/running.md b/component-model/src/creating-and-consuming/running.md index 9a61121..eb27bda 100644 --- a/component-model/src/creating-and-consuming/running.md +++ b/component-model/src/creating-and-consuming/running.md @@ -2,7 +2,7 @@ You can "run" a component by calling one of its exports. In some cases, this requires a custom host. For "command" components, though, you can use the `wasmtime` command line. This can be a convenient tool for testing components and exploring the component model. Other runtimes are also available - see the "Runtimes" section of the sidebar for more info. -> A "command" component is one that exports the `wasi:cli/run` interface, and imports only interfaces listed in the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit). +> A "command" component is one that exports the `wasi:cli/run` interface, and imports only interfaces listed in the [`wasi:cli/command` world](https://github.com/WebAssembly/wasi-cli/blob/main/wit/command.wit). You must use a recent version of `wasmtime` ([`v14.0.0` or greater](https://github.com/bytecodealliance/wasmtime/releases)), as earlier releases of the `wasmtime` command line do not include component model support. diff --git a/component-model/src/design/components.md b/component-model/src/design/components.md index 879d50e..53cfb1a 100644 --- a/component-model/src/design/components.md +++ b/component-model/src/design/components.md @@ -6,4 +6,4 @@ The external interface of a component - its imports and exports - corresponds to a [world](./worlds.md). The component, however, internally defines how that world is implemented. -> For a more formal definition of what a component is, take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). +> For a more formal definition of what a component is, take a look at the [Component Model specification](https://github.com/WebAssembly/component-model). diff --git a/component-model/src/design/interfaces.md b/component-model/src/design/interfaces.md index 5d0f571..69f3c57 100644 --- a/component-model/src/design/interfaces.md +++ b/component-model/src/design/interfaces.md @@ -7,4 +7,4 @@ An **interface** describes a single-focus, composable contract, through which co Interfaces are defined using [the WIT language](./wit.md). -> For a more formal definition of what an interface is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of what an interface is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/packages.md b/component-model/src/design/packages.md index 3fb1439..295c96a 100644 --- a/component-model/src/design/packages.md +++ b/component-model/src/design/packages.md @@ -6,4 +6,4 @@ A WIT package is not a [world](./worlds.md). It's a way of grouping related inte * The WebAssembly System Interface (WASI) defines a number of packages, including one named `wasi:clocks`. Our HTTP proxy world could import the `wall-clock` interface from the `wasi:clocks` package, rather than having to define a custom clock interface. -> For a more formal definition of what a WIT package is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of what a WIT package is, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/why-component-model.md b/component-model/src/design/why-component-model.md index a463b7f..4882d79 100644 --- a/component-model/src/design/why-component-model.md +++ b/component-model/src/design/why-component-model.md @@ -16,4 +16,4 @@ Moreover, a component interacts with a runtime or other components _only_ by cal Now that you have a better idea about how the component model can help you, take a look at [how to build components](../language-support.md) in your favorite language! -> For more background on why the component model was created, take a look at the specification's [goals](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Goals.md), [use cases](https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md) and [design choices](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Choices.md). +> For more background on why the component model was created, take a look at the specification's [goals](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Goals.md), [use cases](https://github.com/WebAssembly/component-model/blob/main/design/high-level/UseCases.md) and [design choices](https://github.com/WebAssembly/component-model/blob/main/design/high-level/Choices.md). diff --git a/component-model/src/design/wit.md b/component-model/src/design/wit.md index 83687d3..2a06ae1 100644 --- a/component-model/src/design/wit.md +++ b/component-model/src/design/wit.md @@ -33,7 +33,7 @@ The WIT (Wasm Interface Type) language is used to define Component Model [interf A WIT file contains one or more **interfaces** or **worlds**. An interface or world can define **types** and/or **functions**. -> Types and functions can't be defined outside of interfaces or worlds. +> Types and functions can't be defined outside of interfaces or worlds. A file may optionally start with a **package** declaration. @@ -98,15 +98,15 @@ WIT defines the following primitive types: | `char` | Unicode character. (Specifically, a [Unicode scalar value](https://unicode.org/glossary/#unicode_scalar_value).) | | `string` | A Unicode string - that is, a finite sequence of characters. | -> The `f32` and `f64` types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a single `nan` value. The exact bit-level representation of an IEEE 754 `NaN` is not guaranteed to be preserved when values pass through WIT interfaces as the singular WIT `nan` value. +> The `f32` and `f64` types support the usual set of IEEE 754 single and double-precision values, except that they logically only have a single `nan` value. The exact bit-level representation of an IEEE 754 `NaN` is not guaranteed to be preserved when values pass through WIT interfaces as the singular WIT `nan` value. ### Lists `list` for any type `T` denotes an ordered sequence of values of type `T`. `T` can be any type, built-in or user-defined: ```wit -list // byte buffer -list // a list of customers +list // byte buffer +list // a list of customers ``` This is similar to Rust `Vec`, or Java `List`. @@ -121,7 +121,7 @@ option This is similar to Rust `Option`, C++ `std::optional`, or Haskell `Maybe`. -> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every value type, and to enable it to be mapped idiomatically into languages with option types. +> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every value type, and to enable it to be mapped idiomatically into languages with option types. ### Results @@ -133,13 +133,13 @@ result This is similar to Rust `Result`, or Haskell `Either`. -> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every combination of value and error types, and to enable it to be mapped idiomatically into languages with result or "either" types. +> This is a special case of a [variant](#variants) type. WIT defines it so that there is a common way of expressing it, so that you don't need to create a variant type for every combination of value and error types, and to enable it to be mapped idiomatically into languages with result or "either" types. Sometimes there is no data associated with one or both of the cases. For example, a `print` function could return an error code if it fails, but has nothing to return if it succeeds. In this case, you can omit the corresponding type as follows: ```wit -result // no data associated with the error case -result<_, u32> // no data associated with the success case +result // no data associated with the error case +result<_, u32> // no data associated with the success case result // no data associated with either case ``` @@ -148,8 +148,8 @@ result // no data associated with either case A `tuple` type is an ordered _fixed length_ sequence of values of specified types. It is similar to a [_record_](#records), except that the fields are identified by their order instead of by names. ```wit -tuple // An integer and a string -tuple // An integer, then a string, then an integer +tuple // An integer and a string +tuple // An integer, then a string, then an integer ``` This is similar to tuples in Rust or OCaml. @@ -173,7 +173,7 @@ record customer { Records are similar to C or Rust `struct`s. -> User-defined records can't be generic (that is, parameterised by type). Only built-in types can be generic. +> User-defined records can't be generic (that is, parameterised by type). Only built-in types can be generic. ### Variants @@ -189,7 +189,7 @@ variant allowed-destinations { Variants are similar to Rust `enum`s or OCaml discriminated unions. The closest C equivalent is a tagged union, but WIT both takes care of the "tag" (the case) and enforces the correct data shape for each tag. -> User-defined variants can't be generic (that is, parameterised by type). Only built-in types can be generic. +> User-defined variants can't be generic (that is, parameterised by type). Only built-in types can be generic. ### Enums @@ -253,7 +253,7 @@ When a `resource` type name is wrapped with `borrow<...>`, it stands for a caller to the callee for the duration of the call. In contrast, when the owner of an owned resource drops that resource, the resource is destroyed. -> More precisely, these are borrowed or owned `handles` of the resource. Learn more about `handles` in the [upstream component model specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#handles). +> More precisely, these are borrowed or owned `handles` of the resource. Learn more about `handles` in the [upstream component model specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#handles). ### Flags @@ -268,7 +268,7 @@ flags allowed-methods { } ``` -> A `flags` type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. +> A `flags` type is logically equivalent to a record type where each field is of type `bool`, but it is represented more efficiently (as a bitfield) at the binary level. ### Type aliases @@ -345,7 +345,7 @@ interface canvas { } ``` -> Even if you are only using one type, it must still be enclosed in braces. For example, `use types.{dimension}` is legal but `use types.dimension` is not. +> Even if you are only using one type, it must still be enclosed in braces. For example, `use types.{dimension}` is legal but `use types.dimension` is not. This works across files as long as the files are in the same package (effectively, in the same directory). For information about using definitions from other packages, see [the specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#interfaces-worlds-and-use). @@ -383,7 +383,7 @@ world http-proxy { } ``` -> As this example shows, import and export apply at the interface level, not the package level. You can import one interface defined in a package, while exporting another interface defined in the same package. Packages group definitions; they don't represent behaviour. +> As this example shows, import and export apply at the interface level, not the package level. You can import one interface defined in a package, while exporting another interface defined in the same package. Packages group definitions; they don't represent behaviour. WIT does not define how packages are resolved - different tools may resolve them in different ways. @@ -453,4 +453,4 @@ world proxy { } ``` -> For a more formal definition of the WIT language, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). +> For a more formal definition of the WIT language, take a look at the [WIT specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md). diff --git a/component-model/src/design/worlds.md b/component-model/src/design/worlds.md index 37fd23c..e708c68 100644 --- a/component-model/src/design/worlds.md +++ b/component-model/src/design/worlds.md @@ -17,4 +17,4 @@ For a component to run, its imports must be fulfilled, by a host or by other com * A (trivial) "HTTP proxy" world would export a "handle HTTP requests" interface, and import a "send HTTP requests" interface. A host, or another component, would call the exported "handle" interface, passing an HTTP request; the component would forward it on via the imported "send" interface. To be a _useful_ proxy, the component may also need to import interfaces such as I/O and clock time - without those imports the component could not perform, for example, on-disk caching. * A "regex parser" world would export a "parse regex" function, and would import nothing. This declares not only that the component implementing this world can parse regular expressions, but also that it calls no other APIs. A user of such a parser could know, without looking at the implementation, that is does not access the file system, or send the user's regexes to a network service. -> For a more formal definition of what a WIT world is, take a look at the [WIT world specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#wit-worlds). +> For a more formal definition of what a WIT world is, take a look at the [WIT world specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#wit-worlds). diff --git a/component-model/src/introduction.md b/component-model/src/introduction.md index 1fe39f4..8321e57 100644 --- a/component-model/src/introduction.md +++ b/component-model/src/introduction.md @@ -25,7 +25,7 @@ The WebAssembly Component Model is a broad-reaching architecture for building in [Running]: ./creating-and-consuming/running.md [Distributing]: ./creating-and-consuming/distributing.md -> This documentation is aimed at _users_ of the component model: developers of libraries and applications. _Compiler and Wasm runtime developers_ can take a look at the [Component Model specification](https://github.com/WebAssembly/component-model) to see how to add support for the component model to their project. +> This documentation is aimed at _users_ of the component model: developers of libraries and applications. _Compiler and Wasm runtime developers_ can take a look at the [Component Model specification](https://github.com/WebAssembly/component-model) to see how to add support for the component model to their project. ## Status diff --git a/component-model/src/language-support.md b/component-model/src/language-support.md index 6257d11..010a591 100644 --- a/component-model/src/language-support.md +++ b/component-model/src/language-support.md @@ -5,7 +5,7 @@ languages; however, the level of support varies. This document details the subset of languages that target WASI and support components. -> This is a living document, so if you are aware of advancements in a toolchain, please do +> This is a living document, so if you are aware of advancements in a toolchain, please do not hesitate to [contribute documentation](https://github.com/bytecodealliance/component-docs/blob/main/CONTRIBUTING.md). You can find more information about the development of support for specific languages in the [Guest Languages Special Interest Group Proposal](https://github.com/bytecodealliance/governance/blob/main/SIGs/SIG-guest-languages/proposal.md) document. One of the benefits of components is their portability across host runtimes. The runtime only needs diff --git a/component-model/src/language-support/c.md b/component-model/src/language-support/c.md index c50a9e9..b84cfc9 100644 --- a/component-model/src/language-support/c.md +++ b/component-model/src/language-support/c.md @@ -35,7 +35,7 @@ Now, you can compile the function into a Wasm module via clang: clang add.c example.c example_component_type.o -o add-core.wasm -mexec-model=reactor ``` -> Use the `clang` included in the WASI SDK installation, for example at `/bin/clang`. +> Use the `clang` included in the WASI SDK installation, for example at `/bin/clang`. Next, you need to transform the module into a component. For this example, you can use `wasm-tools component new`: ```sh diff --git a/component-model/src/language-support/python.md b/component-model/src/language-support/python.md index 2487d5e..b1652ba 100644 --- a/component-model/src/language-support/python.md +++ b/component-model/src/language-support/python.md @@ -28,7 +28,7 @@ If you want to generate bindings produced for the WIT world (for an IDE or typec $ componentize-py --wit-path /path/to/examples/example-host/add.wit --world example bindings . ``` -> You do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component. +> You do not need to generate the bindings in order to `componentize` in the next step. `componentize` will generate bindings on-the-fly and bundle them into the produced component. You can see that bindings were created in an `example` package which contains an `Example` protocol with an `add` method that we can implement: @@ -100,7 +100,7 @@ Component built successfully Wasm components can also be invoked from Python applications. This walks through using tooling to call the [`app.wasm` component from the examples](../../examples/example-host/add.wasm). -> `wasmtime-py` does not currently support running components build with `componentize-py`. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), which components built with `componentize-py` always use, since `componentize-py` unconditionally imports most of the `wasi:cli` world. +> `wasmtime-py` does not currently support running components build with `componentize-py`. This is because `wasmtime-py` does not yet support [resources](../design/wit.md#resources), which components built with `componentize-py` always use, since `componentize-py` unconditionally imports most of the `wasi:cli` world. First, install [Python 3.11 or later](https://www.python.org/) and [pip](https://pypi.org/project/pip/) if you don't already have them. Then, install [`wasmtime-py`](https://github.com/bytecodealliance/wasmtime-py): diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index c81722d..658e21c 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -11,7 +11,7 @@ To install `cargo component`, run: cargo install cargo-component ``` -> You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). +> You can find more details about `cargo component` in its [crates.io page](https://crates.io/crates/cargo-component). ## Building a Component with `cargo component` @@ -115,7 +115,7 @@ impl Guest for Component { The world file (`wit/world.wit`) generated for you by `cargo component new --lib` doesn't specify any imports. -> `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. +> `cargo component build`, by default, uses the Rust `wasm32-wasi` target, and therefore automatically imports any required WASI interfaces - no action is needed from you to import these. This section is about importing custom WIT interfaces from library components. If your component consumes other components, you can edit the `world.wit` file to import their interfaces. @@ -210,7 +210,7 @@ Unlike library components, this does _not_ have the `--lib` flag. You will see t You can write Rust in this project, just as you normally would, including importing your own or third-party crates. -> All the crates that make up your project are linked together at build time, and compiled to a _single_ Wasm component. In this case, all the linking is happening at the Rust level: no WITs or component composition is involved. Only if you import Wasm interfaces do WIT and composition come into play. +> All the crates that make up your project are linked together at build time, and compiled to a _single_ Wasm component. In this case, all the linking is happening at the Rust level: no WITs or component composition is involved. Only if you import Wasm interfaces do WIT and composition come into play. To run your command component: @@ -219,7 +219,7 @@ cargo component build wasmtime run ./target/wasm32-wasi/debug/.wasm ``` -> **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. +> **WARNING:** If your program prints to standard out or error, you may not see the printed output! Some versions of `wasmtime` have a bug where they don't flush output streams before exiting. To work around this, add a `std::thread::sleep()` with a 10 millisecond delay before exiting `main`. ### Importing an interface into a command component @@ -235,7 +235,7 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co } ``` - > `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. + > `cargo component` sometimes fails to find packages if versions are not set explicitly. For example, if the calculator WIT declares `package docs:calculator` rather than `docs:calculator@0.1.0`, then you may get an error even though `cargo component build` automatically versions the binary export. 2. Edit `Cargo.toml` to tell `cargo component` about the new WIT file: @@ -254,7 +254,7 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co "docs:adder" = { path = "../adder/wit" } ``` - > If the external package refers to other packages, you need to provide the paths to them as well. + > If the external package refers to other packages, you need to provide the paths to them as well. 4. Use the imported interface in your Rust code: @@ -375,7 +375,7 @@ To implement the calculator using `cargo component`: } ``` - > Why is the stack wrapped in a `RefCell`? As we will see, the generated Rust trait for the calculator engine has _immutable_ references to `self`. But our implementation of that trait will need to mutate the stack. So we need a type that allows for interior mutability, such as `RefCell` or `Arc>`. + > Why is the stack wrapped in a `RefCell`? As we will see, the generated Rust trait for the calculator engine has _immutable_ references to `self`. But our implementation of that trait will need to mutate the stack. So we need a type that allows for interior mutability, such as `RefCell` or `Arc>`. 3. The generated bindings (`bindings.rs`) for an exported resource include a trait named `GuestX`, where `X` is the resource name. (You may need to run `cargo component build` to regenerate the bindings after updating the WIT.) For the calculator `engine` resource, the trait is `GuestEngine`. Implement this trait on the `struct` from step 2: @@ -496,7 +496,7 @@ If you are hosting a Wasm runtime, you can export a resource from your host for }); ``` - > If you don't specify the host representation for a resource, it defaults to an empty enum. This is rarely useful as resources are usually stateful. + > If you don't specify the host representation for a resource, it defaults to an empty enum. This is rarely useful as resources are usually stateful. 3. If the representation type isn't a built-in type, define it: @@ -514,7 +514,7 @@ If you are hosting a Wasm runtime, you can export a resource from your host for } ``` - > **Important:** You implement this on the 'overall' host type, *not* on the resource representation! Therefore, the `self` reference in these functions is to the 'overall' host type. For instance methods of the resource, the instance is identified by a second parameter (`self_`), of type `wasmtime::component::Resource`. + > **Important:** You implement this on the 'overall' host type, *not* on the resource representation! Therefore, the `self` reference in these functions is to the 'overall' host type. For instance methods of the resource, the instance is identified by a second parameter (`self_`), of type `wasmtime::component::Resource`. 5. Add a `wasmtime::component::ResourceTable` to the host: diff --git a/component-model/src/runtimes/wasmtime.md b/component-model/src/runtimes/wasmtime.md index 0e266af..d0a3b47 100644 --- a/component-model/src/runtimes/wasmtime.md +++ b/component-model/src/runtimes/wasmtime.md @@ -9,7 +9,7 @@ To run a command component with Wasmtime, execute: wasmtime run ``` -> If you are using an older version of `wasmtime`, you may need to add the `--wasm component-model` flag to specify that you are running a component rather than a core module. +> If you are using an older version of `wasmtime`, you may need to add the `--wasm component-model` flag to specify that you are running a component rather than a core module. By default, Wasmtime denies the component access to all system resources. For example, the component cannot access the file system or environment variables. See the [Wasmtime guide](https://docs.wasmtime.dev/) for information on granting access, and for other Wasmtime features. diff --git a/component-model/src/tutorial.md b/component-model/src/tutorial.md index 69226ee..b0e4abf 100644 --- a/component-model/src/tutorial.md +++ b/component-model/src/tutorial.md @@ -134,7 +134,7 @@ wasm-tools compose calculator.wasm -d adder.wasm -o composed.wasm wasm-tools compose command.wasm -d composed.wasm -o final.wasm ``` -> If you'd prefer to take a more visual approach to composing components, see the [documentation on composing components with wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). +> If you'd prefer to take a more visual approach to composing components, see the [documentation on composing components with wasmbuilder.app](creating-and-consuming/composing.md#composing-components-with-a-visual-interface). ## Running the calculator From a9ae52a9ac43dffdaafbb0e7741f5da03aec027f Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 28 Aug 2024 15:29:03 -0500 Subject: [PATCH 4/4] wit examples comment formatting --- component-model/src/design/wit.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/component-model/src/design/wit.md b/component-model/src/design/wit.md index 2a06ae1..9315c03 100644 --- a/component-model/src/design/wit.md +++ b/component-model/src/design/wit.md @@ -138,8 +138,8 @@ This is similar to Rust `Result`, or Haskell `Either`. Sometimes there is no data associated with one or both of the cases. For example, a `print` function could return an error code if it fails, but has nothing to return if it succeeds. In this case, you can omit the corresponding type as follows: ```wit -result // no data associated with the error case -result<_, u32> // no data associated with the success case +result // no data associated with the error case +result<_, u32> // no data associated with the success case result // no data associated with either case ``` @@ -148,7 +148,7 @@ result // no data associated with either case A `tuple` type is an ordered _fixed length_ sequence of values of specified types. It is similar to a [_record_](#records), except that the fields are identified by their order instead of by names. ```wit -tuple // An integer and a string +tuple // An integer and a string tuple // An integer, then a string, then an integer ``` @@ -257,7 +257,7 @@ of an owned resource drops that resource, the resource is destroyed. ### Flags -A `flags` type is a set of named `boolean`. In an instance of the type, each flag will be either `true` or `false`. +A `flags` type is a set of named booleans. In an instance of the type, each flag will be either `true` or `false`. ```wit flags allowed-methods { @@ -290,10 +290,10 @@ do-nothing: func(); The function type is the word `func`, followed by a parenthesised, comma-separated list of parameters (names and types). If the function returns a value, this is expressed as an arrow symbol (`->`) followed by the return type: ```wit -/// This function does not return a value +// This function does not return a value print: func(message: string); -/// These functions return values +// These functions return values add: func(a: u64, b: u64) -> u64; lookup: func(store: kv-store, key: string) -> option; ``` @@ -363,11 +363,13 @@ interface error-reporter { } world multi-function-device { - /// The component implements the `printer` interface + // The component implements the `printer` interface export printer; - /// The component implements the `scan` function + + // The component implements the `scan` function export scan: func() -> list; - /// The component needs to be supplied with an `error-reporter` + + // The component needs to be supplied with an `error-reporter` import error-reporter; } ``` @@ -405,8 +407,10 @@ You can `include` another world. This causes your world to export all that world ```wit world glow-in-the-dark-multi-function-device { - // The component provides all the same exports, and depends on all the same imports, as a `multi-function-device`... + // The component provides all the same exports, and depends on + // all the same imports, as a `multi-function-device`... include multi-function-device; + // ...but also exports a function to make it glow in the dark export glow: func(brightness: u8); }